@@ -122,25 +122,40 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
122
122
typeError ();
123
123
}
124
124
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) {
128
129
fir::SequenceType sequenceType = mlir::cast<fir::SequenceType>(
129
130
hlfir::getFortranElementOrSequenceType (box.getType ()));
130
131
const unsigned rank = sequenceType.getDimension ();
132
+
131
133
llvm::SmallVector<mlir::Value> lbAndExtents;
132
134
lbAndExtents.reserve (rank * 2 );
133
-
134
135
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
+ }
144
159
}
145
160
146
161
auto shapeShiftTy = fir::ShapeShiftType::get (builder.getContext (), rank);
@@ -249,12 +264,13 @@ class PopulateInitAndCleanupRegionsHelper {
249
264
mlir::Type argType, mlir::Value scalarInitValue,
250
265
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
251
266
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)
253
269
: converter{converter}, builder{converter.getFirOpBuilder ()}, loc{loc},
254
270
argType{argType}, scalarInitValue{scalarInitValue},
255
271
allocatedPrivVarArg{allocatedPrivVarArg}, moldArg{moldArg},
256
272
initBlock{initBlock}, cleanupRegion{cleanupRegion}, kind{kind},
257
- sym{sym} {
273
+ sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds} {
258
274
valType = fir::unwrapRefType (argType);
259
275
}
260
276
@@ -296,6 +312,10 @@ class PopulateInitAndCleanupRegionsHelper {
296
312
// / Any length parameters which have been fetched for the type
297
313
mlir::SmallVector<mlir::Value> lenParams;
298
314
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
+
299
319
void createYield (mlir::Value ret) {
300
320
builder.create <mlir::omp::YieldOp>(loc, ret);
301
321
}
@@ -433,7 +453,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
433
453
// Special case for (possibly allocatable) arrays of polymorphic types
434
454
// e.g. !fir.class<!fir.heap<!fir.array<?x!fir.type<>>>>
435
455
if (source.isPolymorphic ()) {
436
- fir::ShapeShiftOp shape = getShapeShift (builder, loc, source);
456
+ fir::ShapeShiftOp shape =
457
+ getShapeShift (builder, loc, source, cannotHaveNonDefaultLowerBounds);
437
458
mlir::Type arrayType = source.getElementOrSequenceType ();
438
459
mlir::Value allocatedArray = builder.create <fir::AllocMemOp>(
439
460
loc, arrayType, /* typeparams=*/ mlir::ValueRange{}, shape.getExtents ());
@@ -472,8 +493,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
472
493
// Put the temporary inside of a box:
473
494
// hlfir::genVariableBox doesn't handle non-default lower bounds
474
495
mlir::Value box;
475
- fir::ShapeShiftOp shapeShift =
476
- getShapeShift (builder, loc, getLoadedMoldArg () );
496
+ fir::ShapeShiftOp shapeShift = getShapeShift (builder, loc, getLoadedMoldArg (),
497
+ cannotHaveNonDefaultLowerBounds );
477
498
mlir::Type boxType = getLoadedMoldArg ().getType ();
478
499
if (mlir::isa<fir::BaseBoxType>(temp.getType ()))
479
500
// the box created by the declare form createTempFromMold is missing
@@ -608,10 +629,10 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
608
629
mlir::Type argType, mlir::Value scalarInitValue, mlir::Block *initBlock,
609
630
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
610
631
mlir::Region &cleanupRegion, DeclOperationKind kind,
611
- const Fortran::semantics::Symbol *sym) {
632
+ const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds ) {
612
633
PopulateInitAndCleanupRegionsHelper helper (
613
634
converter, loc, argType, scalarInitValue, allocatedPrivVarArg, moldArg,
614
- initBlock, cleanupRegion, kind, sym);
635
+ initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds );
615
636
helper.populateByRefInitAndCleanupRegions ();
616
637
617
638
// Often we load moldArg to check something (e.g. length parameters, shape)
0 commit comments