================
@@ -609,208 +880,210 @@ class MapInfoFinalizationPass
       assert(mapMemberUsers.size() == 1 &&
              "OMPMapInfoFinalization currently only supports single users of a 
"
              "MapInfoOp");
-      auto baseAddr = genBaseAddrMap(descriptor, op.getBounds(),
-                                     op.getMapType(), builder, mapperId);
       ParentAndPlacement mapUser = mapMemberUsers[0];
-      adjustMemberIndices(memberIndices, mapUser.index);
+      adjustMemberIndices(memberIndices, mapUser);
       llvm::SmallVector<mlir::Value> newMemberOps;
       for (auto v : mapUser.parent.getMembers()) {
         newMemberOps.push_back(v);
-        if (v == op)
+        if (v == parentOp)
           newMemberOps.push_back(baseAddr);
       }
       mapUser.parent.getMembersMutable().assign(newMemberOps);
       mapUser.parent.setMembersIndexAttr(
           builder.create2DI64ArrayAttr(memberIndices));
-    } else if (!isHasDeviceAddrFlag) {
-      auto baseAddr = genBaseAddrMap(descriptor, op.getBounds(),
-                                     op.getMapType(), builder, mapperId);
+    } else {
       newMembers.push_back(baseAddr);
-      if (!op.getMembers().empty()) {
+      if (!parentOp.getMembers().empty()) {
         for (auto &indices : memberIndices)
           indices.insert(indices.begin(), 0);
         memberIndices.insert(memberIndices.begin(), {0});
         newMembersAttr = builder.create2DI64ArrayAttr(memberIndices);
-        newMembers.append(op.getMembers().begin(), op.getMembers().end());
+        newMembers.append(parentOp.getMembers().begin(),
+                          parentOp.getMembers().end());
       } else {
         llvm::SmallVector<llvm::SmallVector<int64_t>> memberIdx = {{0}};
         newMembersAttr = builder.create2DI64ArrayAttr(memberIdx);
       }
     }
-
-    // Descriptors for objects listed on the `has_device_addr` will always
-    // be copied. This is because the descriptor can be rematerialized by the
-    // compiler, and so the address of the descriptor for a given object at
-    // one place in the code may differ from that address in another place.
-    // The contents of the descriptor (the base address in particular) will
-    // remain unchanged though.
-    mlir::omp::ClauseMapFlags mapType = op.getMapType();
-    if (isHasDeviceAddrFlag) {
-      mapType |= mlir::omp::ClauseMapFlags::always;
-    }
-
-    mlir::omp::MapInfoOp newDescParentMapOp = mlir::omp::MapInfoOp::create(
-        builder, op->getLoc(), op.getResult().getType(), descriptor,
-        mlir::TypeAttr::get(fir::unwrapRefType(descriptor.getType())),
-        builder.getAttr<mlir::omp::ClauseMapFlagsAttr>(
-            getDescriptorMapType(mapType, target)),
-        op.getMapCaptureTypeAttr(), /*varPtrPtr=*/mlir::Value{},
-        /*varPtrPtrType=*/mlir::TypeAttr{}, newMembers, newMembersAttr,
-        /*bounds=*/mlir::SmallVector<mlir::Value>{},
-        /*mapperId=*/mlir::FlatSymbolRefAttr(), op.getNameAttr(),
-        /*partial_map=*/builder.getBoolAttr(false));
-    op.replaceAllUsesWith(newDescParentMapOp.getResult());
-    op->erase();
-
-    if (descCanBeDeferred)
-      deferrableDesc.push_back(newDescParentMapOp);
-
-    return newDescParentMapOp;
   }
 
-  // We add all mapped record members not directly used in the target region
-  // to the block arguments in front of their parent and we place them into
-  // the map operands list for consistency.
+  // This function handles the spliting of allocatable/pointer maps in
+  // Fortran into descriptor, pointer and attach map components, as
+  // well as the handling of ref_ptr, ref_ptee, ref_ptr_ptee and attach
+  // modifier semantics.
   //
-  // These indirect uses (via accesses to their parent) will still be
-  // mapped individually in most cases, and a parent mapping doesn't
-  // guarantee the parent will be mapped in its totality, partial
-  // mapping is common.
+  // For ref_ptr, we generate a map of the descriptor with user specified
+  // map types and, in the default auto attach case, we generate an
+  // additional attach map which indicates to the runtime to try and attach
+  // the base address to the descriptor if it's available and it's the first
+  // time the ref_ptr has been allocated on the device.
   //
-  // For example:
-  //    map(tofrom: x%y)
+  // For ref_ptee, we generate a map of the base address with user specified
+  // map types and, in the default auto attach case, we generate an
+  // additional attach map which indicates to the runtime to try and attach
+  // the base address to the descriptor if it's available and it's the first
+  // time the ref_ptee has been allocated on the device.
   //
-  // Will generate a mapping for "x" (the parent) and "y" (the member).
-  // The parent "x" will not be mapped, but the member "y" will.
-  // However, we must have the parent as a BlockArg and MapOperand
-  // in these cases, to maintain the correct uses within the region and
-  // to help tracking that the member is part of a larger object.
-  //
-  // In the case of:
-  //    map(tofrom: x%y, x%z)
-  //
-  // The parent member becomes more critical, as we perform a partial
-  // structure mapping where we link the mapping of the members y
-  // and z together via the parent x. We do this at a kernel argument
-  // level in LLVM IR and not just MLIR, which is important to maintain
-  // similarity to Clang and for the runtime to do the correct thing.
-  // However, we still do not map the structure in its totality but
-  // rather we generate an un-sized "binding" map entry for it.
-  //
-  // In the case of:
-  //    map(tofrom: x, x%y, x%z)
-  //
-  // We do actually map the entirety of "x", so the explicit mapping of
-  // x%y, x%z becomes unnecessary. It is redundant to write this from a
-  // Fortran OpenMP perspective (although it is legal), as even if the
-  // members were allocatables or pointers, we are mandated by the
-  // specification to map these (and any recursive components) in their
-  // entirety, which is different to the C++ equivalent, which requires
-  // explicit mapping of these segments.
-  void addImplicitMembersToTarget(mlir::omp::MapInfoOp op,
-                                  fir::FirOpBuilder &builder,
-                                  mlir::Operation *target) {
-    auto mapClauseOwner =
-        llvm::dyn_cast_if_present<mlir::omp::MapClauseOwningOpInterface>(
-            target);
-    // TargetDataOp is technically a MapClauseOwningOpInterface, so we
-    // do not need to explicitly check for the extra cases here for use_device
-    // addr/ptr
-    if (!mapClauseOwner)
-      return;
+  // For ref_ptr_ptee, it is the standard descriptor mapping that combines both
+  // of the above, a map is generated for the descriptor and its base address,
+  // similarly in the default auto attach case, we generate an additional 
attach
+  // map.
+  void genDescriptorMaps(mlir::omp::MapInfoOp op, fir::FirOpBuilder &builder,
+                         mlir::Operation *target) {
+    bool descCanBeDeferred = false;
+    llvm::SmallVector<ParentAndPlacement> mapMemberUsers;
+    getMemberUserList(op, mapMemberUsers);
 
-    auto addOperands = [&](mlir::MutableOperandRange &mutableOpRange,
-                           mlir::Operation *directiveOp,
-                           unsigned blockArgInsertIndex = 0) {
-      if (!llvm::is_contained(mutableOpRange.getAsOperandRange(),
-                              op.getResult()))
-        return;
+    // TODO: map the addendum segment of the descriptor, similarly to the
+    // base address/data pointer member.
+    bool isHasDeviceAddrFlag = isHasDeviceAddr(op, *target);
+    bool isUseDeviceFlag =
+        isUseDeviceAddr(op, *target) || isUseDevicePtr(op, *target);
+    bool isAttachNever = bitEnumContainsAll(
+        op.getMapType(), mlir::omp::ClauseMapFlags::attach_never);
+    bool isAttachAlways = bitEnumContainsAll(
+        op.getMapType(), mlir::omp::ClauseMapFlags::attach_always);
+    bool isRefPtr = bitEnumContainsAll(op.getMapType(),
+                                       mlir::omp::ClauseMapFlags::ref_ptr) &&
+                    !bitEnumContainsAll(op.getMapType(),
+                                        mlir::omp::ClauseMapFlags::ref_ptee);
+    bool isRefPtee = bitEnumContainsAll(op.getMapType(),
+                                        mlir::omp::ClauseMapFlags::ref_ptee) &&
+                     !bitEnumContainsAll(op.getMapType(),
+                                         mlir::omp::ClauseMapFlags::ref_ptr);
 
-      // There doesn't appear to be a simple way to convert MutableOperandRange
-      // to a vector currently, so we instead use a for_each to populate our
-      // vector.
-      llvm::SmallVector<mlir::Value> newMapOps;
-      newMapOps.reserve(mutableOpRange.size());
-      llvm::for_each(
-          mutableOpRange.getAsOperandRange(),
-          [&newMapOps](mlir::Value oper) { newMapOps.push_back(oper); });
+    mlir::Value descriptor =
+        getDescriptorFromBoxMap(op, builder, descCanBeDeferred);
+    mlir::FlatSymbolRefAttr mapperId = op.getMapperIdAttr();
 
-      for (auto mapMember : op.getMembers()) {
-        if (llvm::is_contained(mutableOpRange.getAsOperandRange(), mapMember))
-          continue;
-        newMapOps.push_back(mapMember);
-        if (directiveOp) {
-          directiveOp->getRegion(0).insertArgument(
-              blockArgInsertIndex, mapMember.getType(), mapMember.getLoc());
-          blockArgInsertIndex++;
-        }
+    // If we're a derived type descriptor, that's been flagged as ref_ptr,
+    // but, in the same mapping, we also have members with their own
+    // descriptors also mapped as ref_ptr, then we have to map the parent
+    // derived type descriptors data. This is because the member's ref_ptrs
+    // are parts of the parent and must be mapped and attached as a contiguous
+    // storage block. Relevant for mappings like:
+    //
+    // !$omp target enter data map(ref_ptr, to: obj, obj%arr,
+    // obj%dtype_nest2%arr3, obj%dtype_nest2%scalar_ptr)
+    //
+    // In which a user has basically told us to map the descriptor of obj, but
+    // also bits of its ref_ptee data with its descriptor members.
+    //
+    // TODO: This currently only works for the first level of a
+    // derived-type descriptor chain and will likely need to be extended for 
the
+    // case where we do a similar style of mapping for deeper nestings.
+    if (isRefPtr && op.getMembers().empty()) {
+      auto newMapInfoOp = mlir::omp::MapInfoOp::create(
+          builder, op->getLoc(), op.getResult().getType(), descriptor,
+          mlir::TypeAttr::get(fir::unwrapRefType(descriptor.getType())),
+          builder.getAttr<mlir::omp::ClauseMapFlagsAttr>(op.getMapType()),
+          op.getMapCaptureTypeAttr(), /*varPtrPtr=*/op.getVarPtrPtr(),
+          /*varPtrPtrType=*/op.getVarPtrPtrTypeAttr(), op.getMembers(),
+          op.getMembersIndexAttr(),
+          /*bounds=*/mlir::SmallVector<mlir::Value>{},
+          /*mapperId*/ mlir::FlatSymbolRefAttr(), op.getNameAttr(),
+          /*partial_map=*/builder.getBoolAttr(false));
+
+      // If we're a map exiting construct we skip the generation of the
+      // attach map. It should be unnecessary in these cases as it exists to
+      // bind the pointer and pointee and shouldn't increment or decrement
+      // the ref counter on its own. However, equally having it doesn't
+      // cause issues either, it's just ideal to remove the noise where
+      // feasible.
+      // TODO: Extend this to perhaps check for target updates and target data
+      //  with release and from applied.
+      if (!llvm::isa<mlir::omp::TargetExitDataOp>(target) && !isAttachNever)
+        genImplicitAttachMap(op, descriptor, mapMemberUsers, target, builder,
+                             mlir::omp::ClauseMapFlags::ref_ptr,
+                             isAttachAlways);
+      op.replaceAllUsesWith(newMapInfoOp.getResult());
+      op->erase();
+    } else if (isRefPtee) {
+      // NOTE: We replace the descriptor map with the base address map. This
+      // effectively replaces the descriptor's index position in any complex
+      // structure mapping. This is a little different to the
+      // ref_ptr_ptee/default map case, where we effectively insert a new 
member
+      // with its own index position and have to nudge all children down an
+      // index. This should be fine but it's worth noting the oddity in case
+      // issues do pop up.
+      auto newMapInfoOp = genBaseAddrMap(descriptor, op, op.getMapType(),
+                                         builder, /*IsRefPtee=*/true, 
mapperId);
+
+      // If we're a map exiting construct, we skip the generation of the attach
+      // map. It should be unnecessary in these cases as it exists to bind the
+      // pointer and pointee and shouldn't increment or decrement the ref
+      // counter on its own. However, equally having it doesn't cause issues
+      // either, it's just ideal to remove the noise where feasible.
+      // TODO: Extend this to perhaps check for target updates and target data
+      // with release and from applied.
+      if (!llvm::isa<mlir::omp::TargetExitDataOp>(target) && !isAttachNever)
+        genImplicitAttachMap(op, descriptor, mapMemberUsers, target, builder,
+                             mlir::omp::ClauseMapFlags::ref_ptee,
+                             isAttachAlways, newMapInfoOp.getVarPtrPtr());
+      op.replaceAllUsesWith(newMapInfoOp.getResult());
+      op->erase();
+    } else {
+      bool isRefPtrPtee =
+          (op.getMapType() & mlir::omp::ClauseMapFlags::ref_ptr) ==
+              mlir::omp::ClauseMapFlags::ref_ptr &&
+          (op.getMapType() & mlir::omp::ClauseMapFlags::ref_ptee) ==
+              mlir::omp::ClauseMapFlags::ref_ptee;
----------------
agozillon wrote:

This similarly to the previous statement won't work as expected in this 
particular case with the bit shift combination, so I've opted to leave out the 
merge into a singular bit check but  I've swapped to the function, thanks for 
the catch! 

https://github.com/llvm/llvm-project/pull/177715
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to