@@ -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);
@@ -248,12 +263,13 @@ class PopulateInitAndCleanupRegionsHelper {
248
263
mlir::Type argType, mlir::Value scalarInitValue,
249
264
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
250
265
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)
252
268
: converter{converter}, builder{converter.getFirOpBuilder ()}, loc{loc},
253
269
argType{argType}, scalarInitValue{scalarInitValue},
254
270
allocatedPrivVarArg{allocatedPrivVarArg}, moldArg{moldArg},
255
271
initBlock{initBlock}, cleanupRegion{cleanupRegion}, kind{kind},
256
- sym{sym} {
272
+ sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds} {
257
273
valType = fir::unwrapRefType (argType);
258
274
}
259
275
@@ -295,6 +311,10 @@ class PopulateInitAndCleanupRegionsHelper {
295
311
// / Any length parameters which have been fetched for the type
296
312
mlir::SmallVector<mlir::Value> lenParams;
297
313
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
+
298
318
void createYield (mlir::Value ret) {
299
319
builder.create <mlir::omp::YieldOp>(loc, ret);
300
320
}
@@ -432,7 +452,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
432
452
// Special case for (possibly allocatable) arrays of polymorphic types
433
453
// e.g. !fir.class<!fir.heap<!fir.array<?x!fir.type<>>>>
434
454
if (source.isPolymorphic ()) {
435
- fir::ShapeShiftOp shape = getShapeShift (builder, loc, source);
455
+ fir::ShapeShiftOp shape =
456
+ getShapeShift (builder, loc, source, cannotHaveNonDefaultLowerBounds);
436
457
mlir::Type arrayType = source.getElementOrSequenceType ();
437
458
mlir::Value allocatedArray = builder.create <fir::AllocMemOp>(
438
459
loc, arrayType, /* typeparams=*/ mlir::ValueRange{}, shape.getExtents ());
@@ -471,8 +492,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
471
492
// Put the temporary inside of a box:
472
493
// hlfir::genVariableBox doesn't handle non-default lower bounds
473
494
mlir::Value box;
474
- fir::ShapeShiftOp shapeShift =
475
- getShapeShift (builder, loc, getLoadedMoldArg () );
495
+ fir::ShapeShiftOp shapeShift = getShapeShift (builder, loc, getLoadedMoldArg (),
496
+ cannotHaveNonDefaultLowerBounds );
476
497
mlir::Type boxType = getLoadedMoldArg ().getType ();
477
498
if (mlir::isa<fir::BaseBoxType>(temp.getType ()))
478
499
// the box created by the declare form createTempFromMold is missing
@@ -607,10 +628,10 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
607
628
mlir::Type argType, mlir::Value scalarInitValue, mlir::Block *initBlock,
608
629
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
609
630
mlir::Region &cleanupRegion, DeclOperationKind kind,
610
- const Fortran::semantics::Symbol *sym) {
631
+ const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds ) {
611
632
PopulateInitAndCleanupRegionsHelper helper (
612
633
converter, loc, argType, scalarInitValue, allocatedPrivVarArg, moldArg,
613
- initBlock, cleanupRegion, kind, sym);
634
+ initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds );
614
635
helper.populateByRefInitAndCleanupRegions ();
615
636
616
637
// Often we load moldArg to check something (e.g. length parameters, shape)
0 commit comments