@@ -82,6 +82,10 @@ class MapInfoFinalizationPass
82
82
// / | |
83
83
std::map<mlir::Operation *, mlir::Value> localBoxAllocas;
84
84
85
+ // List of deferrable descriptors to process at the end of
86
+ // the pass.
87
+ llvm::SmallVector<mlir::Operation *> deferrableDesc;
88
+
85
89
// / getMemberUserList gathers all users of a particular MapInfoOp that are
86
90
// / other MapInfoOp's and places them into the mapMemberUsers list, which
87
91
// / records the map that the current argument MapInfoOp "op" is part of
@@ -126,20 +130,51 @@ class MapInfoFinalizationPass
126
130
});
127
131
}
128
132
133
+ // Check if the declaration operation we have refers to a dummy
134
+ // function argument.
135
+ bool isDummyArgument (mlir::Operation *op) {
136
+ if (auto declareOp = mlir::dyn_cast<hlfir::DeclareOp>(op))
137
+ if (auto dummyScope = declareOp.getDummyScope ())
138
+ return true ;
139
+ return false ;
140
+ }
141
+
142
+ // Relevant for OpenMP < 5.2, where attach semantics and rules don't exist.
143
+ // As descriptors were an unspoken implementation detail in these versions
144
+ // there's certain cases where the user (and the compiler implementation)
145
+ // can create data mapping errors by having temporary descriptors stuck
146
+ // in memory. To avoid this we can defer the descriptor mapping in these
147
+ // cases until target or target data regions, when we can be sure they
148
+ // have a clear limited scope on device.
149
+ bool canDeferDescriptorMapping (mlir::Value descriptor) {
150
+ if (!fir::isAllocatableType (descriptor.getType ()) ||
151
+ !fir::isPointerType (descriptor.getType ())) {
152
+ if (isDummyArgument (descriptor.getDefiningOp ()) &&
153
+ (fir::isAssumedType (descriptor.getType ()) ||
154
+ fir::isAssumedShape (descriptor.getType ()))) {
155
+ return true ;
156
+ }
157
+ }
158
+ return false ;
159
+ }
160
+
129
161
// / When provided a MapInfoOp containing a descriptor type that
130
162
// / we must expand into multiple maps this function will extract
131
163
// / the value from it and return it, in certain cases we must
132
164
// / generate a new allocation to store into so that the
133
165
// / fir::BoxOffsetOp we utilise to access the descriptor datas
134
166
// / base address can be utilised.
135
167
mlir::Value getDescriptorFromBoxMap (mlir::omp::MapInfoOp boxMap,
136
- fir::FirOpBuilder &builder) {
168
+ fir::FirOpBuilder &builder,
169
+ bool &canDescBeDeferred) {
137
170
mlir::Value descriptor = boxMap.getVarPtr ();
138
171
if (!fir::isTypeWithDescriptor (boxMap.getVarType ()))
139
172
if (auto addrOp = mlir::dyn_cast_if_present<fir::BoxAddrOp>(
140
173
boxMap.getVarPtr ().getDefiningOp ()))
141
174
descriptor = addrOp.getVal ();
142
175
176
+ canDescBeDeferred = canDeferDescriptorMapping (descriptor);
177
+
143
178
if (!mlir::isa<fir::BaseBoxType>(descriptor.getType ()) &&
144
179
!fir::factory::isOptionalArgument (descriptor.getDefiningOp ()))
145
180
return descriptor;
@@ -291,7 +326,7 @@ class MapInfoFinalizationPass
291
326
if (llvm::isa_and_nonnull<mlir::omp::TargetExitDataOp,
292
327
mlir::omp::TargetUpdateOp>(target)) {
293
328
mapFlags flags = mapFlags (mapTypeFlag);
294
- if (!IsHasDeviceAddr)
329
+ if (!IsHasDeviceAddr)
295
330
flags |= mapFlags::OMP_MAP_DESCRIPTOR;
296
331
return llvm::to_underlying (flags);
297
332
}
@@ -415,7 +450,9 @@ class MapInfoFinalizationPass
415
450
416
451
// TODO: map the addendum segment of the descriptor, similarly to the
417
452
// base address/data pointer member.
418
- mlir::Value descriptor = getDescriptorFromBoxMap (op, builder);
453
+ bool descCanBeDeferred = false ;
454
+ mlir::Value descriptor =
455
+ getDescriptorFromBoxMap (op, builder, descCanBeDeferred);
419
456
420
457
mlir::ArrayAttr newMembersAttr;
421
458
mlir::SmallVector<mlir::Value> newMembers;
@@ -491,6 +528,10 @@ class MapInfoFinalizationPass
491
528
/* partial_map=*/ builder.getBoolAttr (false ));
492
529
op.replaceAllUsesWith (newDescParentMapOp.getResult ());
493
530
op->erase ();
531
+
532
+ if (descCanBeDeferred)
533
+ deferrableDesc.push_back (newDescParentMapOp);
534
+
494
535
return newDescParentMapOp;
495
536
}
496
537
@@ -784,6 +825,7 @@ class MapInfoFinalizationPass
784
825
// clear all local allocations we made for any boxes in any prior
785
826
// iterations from previous function scopes.
786
827
localBoxAllocas.clear ();
828
+ deferrableDesc.clear ();
787
829
788
830
// First, walk `omp.map.info` ops to see if any of them have varPtrs
789
831
// with an underlying type of fir.char<k, ?>, i.e a character
@@ -817,7 +859,7 @@ class MapInfoFinalizationPass
817
859
op.getBoundsMutable ().append (boundsOps);
818
860
});
819
861
820
- // Next, walk `omp.map.info` ops to see if any record members should be
862
+ // Next, walk `omp.map.info` ops to see if any record members should be
821
863
// implicitly mapped.
822
864
// TODO/FIXME/UPDATE: I believe we need to add implicit capture of
823
865
// allocatable members of arbitrary depths for this before we can
@@ -1059,18 +1101,14 @@ class MapInfoFinalizationPass
1059
1101
// data and the runtime should correctly associate the data with the
1060
1102
// descriptor and bind together and allow clean mapping and execution.
1061
1103
if (deferDescMapping) {
1062
- func->walk ([&](mlir::omp::MapInfoOp op) {
1063
- if (fir::isTypeWithDescriptor (op.getVarType ()) ||
1064
- mlir::isa_and_present<fir::BoxAddrOp>(
1065
- op.getVarPtr ().getDefiningOp ())) {
1066
- mlir::Operation *targetUser = getFirstTargetUser (op);
1067
- assert (targetUser &&
1068
- " expected user of map operation was not found" );
1069
- builder.setInsertionPoint (op);
1070
- removeTopLevelDescriptor (op, builder, targetUser);
1071
- addImplictDescriptorMapToTargetDataOp (op, builder, targetUser);
1072
- }
1073
- });
1104
+ for (auto *op : deferrableDesc) {
1105
+ auto mapOp = llvm::dyn_cast<mlir::omp::MapInfoOp>(op);
1106
+ mlir::Operation *targetUser = getFirstTargetUser (mapOp);
1107
+ assert (targetUser && " expected user of map operation was not found" );
1108
+ builder.setInsertionPoint (mapOp);
1109
+ removeTopLevelDescriptor (mapOp, builder, targetUser);
1110
+ addImplictDescriptorMapToTargetDataOp (mapOp, builder, targetUser);
1111
+ }
1074
1112
}
1075
1113
1076
1114
// Wait until after we have generated all of our maps to add them onto
0 commit comments