@@ -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);
@@ -249,12 +264,13 @@ class PopulateInitAndCleanupRegionsHelper {
249264 mlir::Type argType, mlir::Value scalarInitValue,
250265 mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
251266 mlir::Block *initBlock, mlir::Region &cleanupRegion,
252- DeclOperationKind kind, const Fortran::semantics::Symbol *sym)
267+ DeclOperationKind kind, const Fortran::semantics::Symbol *sym,
268+ bool cannotHaveLowerBounds)
253269 : converter{converter}, builder{converter.getFirOpBuilder ()}, loc{loc},
254270 argType{argType}, scalarInitValue{scalarInitValue},
255271 allocatedPrivVarArg{allocatedPrivVarArg}, moldArg{moldArg},
256272 initBlock{initBlock}, cleanupRegion{cleanupRegion}, kind{kind},
257- sym{sym} {
273+ sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds} {
258274 valType = fir::unwrapRefType (argType);
259275 }
260276
@@ -296,6 +312,10 @@ class PopulateInitAndCleanupRegionsHelper {
296312 // / Any length parameters which have been fetched for the type
297313 mlir::SmallVector<mlir::Value> lenParams;
298314
315+ // / If the source variable being privatized definately can't have non-default
316+ // / lower bounds then we don't need to generate code to read them.
317+ bool cannotHaveNonDefaultLowerBounds;
318+
299319 void createYield (mlir::Value ret) {
300320 builder.create <mlir::omp::YieldOp>(loc, ret);
301321 }
@@ -433,7 +453,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
433453 // Special case for (possibly allocatable) arrays of polymorphic types
434454 // e.g. !fir.class<!fir.heap<!fir.array<?x!fir.type<>>>>
435455 if (source.isPolymorphic ()) {
436- fir::ShapeShiftOp shape = getShapeShift (builder, loc, source);
456+ fir::ShapeShiftOp shape =
457+ getShapeShift (builder, loc, source, cannotHaveNonDefaultLowerBounds);
437458 mlir::Type arrayType = source.getElementOrSequenceType ();
438459 mlir::Value allocatedArray = builder.create <fir::AllocMemOp>(
439460 loc, arrayType, /* typeparams=*/ mlir::ValueRange{}, shape.getExtents ());
@@ -472,8 +493,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
472493 // Put the temporary inside of a box:
473494 // hlfir::genVariableBox doesn't handle non-default lower bounds
474495 mlir::Value box;
475- fir::ShapeShiftOp shapeShift =
476- getShapeShift (builder, loc, getLoadedMoldArg () );
496+ fir::ShapeShiftOp shapeShift = getShapeShift (builder, loc, getLoadedMoldArg (),
497+ cannotHaveNonDefaultLowerBounds );
477498 mlir::Type boxType = getLoadedMoldArg ().getType ();
478499 if (mlir::isa<fir::BaseBoxType>(temp.getType ()))
479500 // the box created by the declare form createTempFromMold is missing
@@ -608,10 +629,10 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
608629 mlir::Type argType, mlir::Value scalarInitValue, mlir::Block *initBlock,
609630 mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
610631 mlir::Region &cleanupRegion, DeclOperationKind kind,
611- const Fortran::semantics::Symbol *sym) {
632+ const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds ) {
612633 PopulateInitAndCleanupRegionsHelper helper (
613634 converter, loc, argType, scalarInitValue, allocatedPrivVarArg, moldArg,
614- initBlock, cleanupRegion, kind, sym);
635+ initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds );
615636 helper.populateByRefInitAndCleanupRegions ();
616637
617638 // Often we load moldArg to check something (e.g. length parameters, shape)
0 commit comments