================
@@ -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,
----------------
agozillon wrote:
I personally prefer it as is, as I can tell at a glance what the differences
are without digging around, but I also wrote it and have been staring at it for
a while, so I can appreciate that it's likely not so easy for others! So, happy
to change it to the more compartmentalized style :-)
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