@@ -147,6 +147,68 @@ mlir::Value calculateTripCount(fir::FirOpBuilder &builder, mlir::Location loc,
147
147
148
148
return tripCount;
149
149
}
150
+
151
+ // / Check if cloning the bounds introduced any dependency on the outer region.
152
+ // / If so, then either clone them as well if they are MemoryEffectFree, or else
153
+ // / copy them to a new temporary and add them to the map and block_argument
154
+ // / lists and replace their uses with the new temporary.
155
+ // /
156
+ // / TODO: similar to the above functions, this is copied from OpenMP lowering
157
+ // / (in this case, from `genBodyOfTargetOp`). Once we move to a common lib for
158
+ // / these utils this will move as well.
159
+ void cloneOrMapRegionOutsiders (fir::FirOpBuilder &builder,
160
+ mlir::omp::TargetOp targetOp) {
161
+ mlir::Region &targetRegion = targetOp.getRegion ();
162
+ mlir::Block *targetEntryBlock = &targetRegion.getBlocks ().front ();
163
+ llvm::SetVector<mlir::Value> valuesDefinedAbove;
164
+ mlir::getUsedValuesDefinedAbove (targetRegion, valuesDefinedAbove);
165
+
166
+ while (!valuesDefinedAbove.empty ()) {
167
+ for (mlir::Value val : valuesDefinedAbove) {
168
+ mlir::Operation *valOp = val.getDefiningOp ();
169
+ assert (valOp != nullptr );
170
+ if (mlir::isMemoryEffectFree (valOp)) {
171
+ mlir::Operation *clonedOp = valOp->clone ();
172
+ targetEntryBlock->push_front (clonedOp);
173
+ assert (clonedOp->getNumResults () == 1 );
174
+ val.replaceUsesWithIf (
175
+ clonedOp->getResult (0 ), [targetEntryBlock](mlir::OpOperand &use) {
176
+ return use.getOwner ()->getBlock () == targetEntryBlock;
177
+ });
178
+ } else {
179
+ mlir::OpBuilder::InsertionGuard guard (builder);
180
+ builder.setInsertionPointAfter (valOp);
181
+ auto copyVal = builder.createTemporary (val.getLoc (), val.getType ());
182
+ builder.createStoreWithConvert (copyVal.getLoc (), val, copyVal);
183
+
184
+ llvm::SmallVector<mlir::Value> bounds;
185
+ std::stringstream name;
186
+ builder.setInsertionPoint (targetOp);
187
+ mlir::Value mapOp = createMapInfoOp (
188
+ builder, copyVal.getLoc (), copyVal,
189
+ /* varPtrPtr=*/ mlir::Value{}, name.str (), bounds,
190
+ /* members=*/ llvm::SmallVector<mlir::Value>{},
191
+ /* membersIndex=*/ mlir::DenseIntElementsAttr{},
192
+ static_cast <
193
+ std::underlying_type_t <llvm::omp::OpenMPOffloadMappingFlags>>(
194
+ llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT),
195
+ mlir::omp::VariableCaptureKind::ByCopy, copyVal.getType ());
196
+ targetOp.getMapVarsMutable ().append (mapOp);
197
+ mlir::Value clonedValArg =
198
+ targetRegion.addArgument (copyVal.getType (), copyVal.getLoc ());
199
+ builder.setInsertionPointToStart (targetEntryBlock);
200
+ auto loadOp =
201
+ builder.create <fir::LoadOp>(clonedValArg.getLoc (), clonedValArg);
202
+ val.replaceUsesWithIf (
203
+ loadOp->getResult (0 ), [targetEntryBlock](mlir::OpOperand &use) {
204
+ return use.getOwner ()->getBlock () == targetEntryBlock;
205
+ });
206
+ }
207
+ }
208
+ valuesDefinedAbove.clear ();
209
+ mlir::getUsedValuesDefinedAbove (targetRegion, valuesDefinedAbove);
210
+ }
211
+ }
150
212
} // namespace internal
151
213
} // namespace omp
152
214
} // namespace lower
@@ -720,14 +782,19 @@ class DoConcurrentConversion : public mlir::OpConversionPattern<fir::DoLoopOp> {
720
782
llvm::SmallVector<mlir::Value> boundsOps;
721
783
genBoundsOps (rewriter, liveIn.getLoc (), declareOp, boundsOps);
722
784
785
+ // Use the raw address to avoid unboxing `fir.box` values whenever possible.
786
+ // Put differently, if we have access to the direct value memory
787
+ // reference/address, we use it.
788
+ mlir::Value rawAddr = declareOp.getOriginalBase ();
723
789
return Fortran::lower::omp ::internal::createMapInfoOp (
724
- rewriter, liveIn.getLoc (), declareOp.getBase (), /* varPtrPtr=*/ {},
725
- declareOp.getUniqName ().str (), boundsOps, /* members=*/ {},
790
+ rewriter, liveIn.getLoc (), rawAddr,
791
+ /* varPtrPtr=*/ {}, declareOp.getUniqName ().str (), boundsOps,
792
+ /* members=*/ {},
726
793
/* membersIndex=*/ mlir::DenseIntElementsAttr{},
727
794
static_cast <
728
795
std::underlying_type_t <llvm::omp::OpenMPOffloadMappingFlags>>(
729
796
mapFlag),
730
- captureKind, liveInType );
797
+ captureKind, rawAddr. getType () );
731
798
}
732
799
733
800
mlir::omp::TargetOp genTargetOp (mlir::Location loc,
@@ -754,14 +821,24 @@ class DoConcurrentConversion : public mlir::OpConversionPattern<fir::DoLoopOp> {
754
821
auto miOp = mlir::cast<mlir::omp::MapInfoOp>(mapInfoOp.getDefiningOp ());
755
822
hlfir::DeclareOp liveInDeclare = genLiveInDeclare (rewriter, arg, miOp);
756
823
mlir::Value miOperand = miOp.getVariableOperand (0 );
757
- mapper.map (miOperand, liveInDeclare.getBase ());
824
+
825
+ // TODO If `miOperand.getDefiningOp()` is a `fir::BoxAddrOp`, we probably
826
+ // need to "unpack" the box by getting the defining op of it's value.
827
+ // However, we did not hit this case in reality yet so leaving it as a
828
+ // todo for now.
829
+
830
+ mapper.map (miOperand, liveInDeclare.getOriginalBase ());
758
831
759
832
if (auto origDeclareOp = mlir::dyn_cast_if_present<hlfir::DeclareOp>(
760
833
miOperand.getDefiningOp ()))
761
- mapper.map (origDeclareOp.getOriginalBase (),
762
- liveInDeclare.getOriginalBase ());
834
+ mapper.map (origDeclareOp.getBase (), liveInDeclare.getBase ());
763
835
}
764
836
837
+ fir::FirOpBuilder firBuilder (
838
+ rewriter,
839
+ fir::getKindMapping (targetOp->getParentOfType <mlir::ModuleOp>()));
840
+ Fortran::lower::omp::internal::cloneOrMapRegionOutsiders (firBuilder,
841
+ targetOp);
765
842
rewriter.setInsertionPoint (
766
843
rewriter.create <mlir::omp::TerminatorOp>(targetOp.getLoc ()));
767
844
0 commit comments