@@ -122,25 +122,40 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
122122 typeError ();
123123}
124124
125- fir::ShapeShiftOp Fortran::lower::omp::getShapeShift (fir::FirOpBuilder &builder,
126- mlir::Location loc,
127- mlir::Value box) {
125+ fir::ShapeShiftOp
126+ Fortran::lower::omp::getShapeShift (fir::FirOpBuilder &builder,
127+ mlir::Location loc, mlir::Value box,
128+ bool cannotHaveNonDefaultLowerBounds) {
128129 fir::SequenceType sequenceType = mlir::cast<fir::SequenceType>(
129130 hlfir::getFortranElementOrSequenceType (box.getType ()));
130131 const unsigned rank = sequenceType.getDimension ();
132+
131133 llvm::SmallVector<mlir::Value> lbAndExtents;
132134 lbAndExtents.reserve (rank * 2 );
133-
134135 mlir::Type idxTy = builder.getIndexType ();
135- for (unsigned i = 0 ; i < rank; ++i) {
136- // TODO: ideally we want to hoist box reads out of the critical section.
137- // We could do this by having box dimensions in block arguments like
138- // OpenACC does
139- mlir::Value dim = builder.createIntegerConstant (loc, idxTy, i);
140- auto dimInfo =
141- builder.create <fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, dim);
142- lbAndExtents.push_back (dimInfo.getLowerBound ());
143- lbAndExtents.push_back (dimInfo.getExtent ());
136+
137+ if (cannotHaveNonDefaultLowerBounds && !sequenceType.hasDynamicExtents ()) {
138+ // We don't need fir::BoxDimsOp if all of the extents are statically known
139+ // and we can assume default lower bounds. This helps avoids reads from the
140+ // mold arg.
141+ mlir::Value one = builder.createIntegerConstant (loc, idxTy, 1 );
142+ for (int64_t extent : sequenceType.getShape ()) {
143+ assert (extent != sequenceType.getUnknownExtent ());
144+ mlir::Value extentVal = builder.createIntegerConstant (loc, idxTy, extent);
145+ lbAndExtents.push_back (one);
146+ lbAndExtents.push_back (extentVal);
147+ }
148+ } else {
149+ for (unsigned i = 0 ; i < rank; ++i) {
150+ // TODO: ideally we want to hoist box reads out of the critical section.
151+ // We could do this by having box dimensions in block arguments like
152+ // OpenACC does
153+ mlir::Value dim = builder.createIntegerConstant (loc, idxTy, i);
154+ auto dimInfo =
155+ builder.create <fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, dim);
156+ lbAndExtents.push_back (dimInfo.getLowerBound ());
157+ lbAndExtents.push_back (dimInfo.getExtent ());
158+ }
144159 }
145160
146161 auto shapeShiftTy = fir::ShapeShiftType::get (builder.getContext (), rank);
@@ -248,12 +263,13 @@ class PopulateInitAndCleanupRegionsHelper {
248263 mlir::Type argType, mlir::Value scalarInitValue,
249264 mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
250265 mlir::Block *initBlock, mlir::Region &cleanupRegion,
251- DeclOperationKind kind, const Fortran::semantics::Symbol *sym)
266+ DeclOperationKind kind, const Fortran::semantics::Symbol *sym,
267+ bool cannotHaveLowerBounds)
252268 : converter{converter}, builder{converter.getFirOpBuilder ()}, loc{loc},
253269 argType{argType}, scalarInitValue{scalarInitValue},
254270 allocatedPrivVarArg{allocatedPrivVarArg}, moldArg{moldArg},
255271 initBlock{initBlock}, cleanupRegion{cleanupRegion}, kind{kind},
256- sym{sym} {
272+ sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds} {
257273 valType = fir::unwrapRefType (argType);
258274 }
259275
@@ -295,6 +311,10 @@ class PopulateInitAndCleanupRegionsHelper {
295311 // / Any length parameters which have been fetched for the type
296312 mlir::SmallVector<mlir::Value> lenParams;
297313
314+ // / If the source variable being privatized definitely can't have non-default
315+ // / lower bounds then we don't need to generate code to read them.
316+ bool cannotHaveNonDefaultLowerBounds;
317+
298318 void createYield (mlir::Value ret) {
299319 builder.create <mlir::omp::YieldOp>(loc, ret);
300320 }
@@ -432,7 +452,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
432452 // Special case for (possibly allocatable) arrays of polymorphic types
433453 // e.g. !fir.class<!fir.heap<!fir.array<?x!fir.type<>>>>
434454 if (source.isPolymorphic ()) {
435- fir::ShapeShiftOp shape = getShapeShift (builder, loc, source);
455+ fir::ShapeShiftOp shape =
456+ getShapeShift (builder, loc, source, cannotHaveNonDefaultLowerBounds);
436457 mlir::Type arrayType = source.getElementOrSequenceType ();
437458 mlir::Value allocatedArray = builder.create <fir::AllocMemOp>(
438459 loc, arrayType, /* typeparams=*/ mlir::ValueRange{}, shape.getExtents ());
@@ -471,8 +492,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
471492 // Put the temporary inside of a box:
472493 // hlfir::genVariableBox doesn't handle non-default lower bounds
473494 mlir::Value box;
474- fir::ShapeShiftOp shapeShift =
475- getShapeShift (builder, loc, getLoadedMoldArg () );
495+ fir::ShapeShiftOp shapeShift = getShapeShift (builder, loc, getLoadedMoldArg (),
496+ cannotHaveNonDefaultLowerBounds );
476497 mlir::Type boxType = getLoadedMoldArg ().getType ();
477498 if (mlir::isa<fir::BaseBoxType>(temp.getType ()))
478499 // the box created by the declare form createTempFromMold is missing
@@ -607,10 +628,10 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
607628 mlir::Type argType, mlir::Value scalarInitValue, mlir::Block *initBlock,
608629 mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
609630 mlir::Region &cleanupRegion, DeclOperationKind kind,
610- const Fortran::semantics::Symbol *sym) {
631+ const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds ) {
611632 PopulateInitAndCleanupRegionsHelper helper (
612633 converter, loc, argType, scalarInitValue, allocatedPrivVarArg, moldArg,
613- initBlock, cleanupRegion, kind, sym);
634+ initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds );
614635 helper.populateByRefInitAndCleanupRegions ();
615636
616637 // Often we load moldArg to check something (e.g. length parameters, shape)
0 commit comments