@@ -295,55 +295,60 @@ mlir::Value ReductionProcessor::createScalarCombiner(
295
295
return reductionOp;
296
296
}
297
297
298
- // / Create reduction combiner region for reduction variables which are boxed
299
- // / arrays
300
- static void genBoxCombiner (fir::FirOpBuilder &builder, mlir::Location loc,
301
- ReductionProcessor::ReductionIdentifier redId,
302
- fir::BaseBoxType boxTy, mlir::Value lhs,
303
- mlir::Value rhs) {
304
- fir::SequenceType seqTy =
305
- mlir::dyn_cast_or_null<fir::SequenceType>(boxTy.getEleTy ());
306
- // TODO: support allocatable arrays: !fir.box<!fir.heap<!fir.array<...>>>
307
- if (!seqTy || seqTy.hasUnknownShape ())
308
- TODO (loc, " Unsupported boxed type in OpenMP reduction" );
309
-
310
- // load fir.ref<fir.box<...>>
311
- mlir::Value lhsAddr = lhs;
312
- lhs = builder.create <fir::LoadOp>(loc, lhs);
313
- rhs = builder.create <fir::LoadOp>(loc, rhs);
314
-
315
- const unsigned rank = seqTy.getDimension ();
316
- llvm::SmallVector<mlir::Value> extents;
317
- extents.reserve (rank);
298
+ // / Generate a fir::ShapeShift op describing the provided boxed array.
299
+ static fir::ShapeShiftOp getShapeShift (fir::FirOpBuilder &builder,
300
+ mlir::Location loc, mlir::Value box) {
301
+ fir::SequenceType sequenceType = mlir::cast<fir::SequenceType>(
302
+ hlfir::getFortranElementOrSequenceType (box.getType ()));
303
+ const unsigned rank = sequenceType.getDimension ();
318
304
llvm::SmallVector<mlir::Value> lbAndExtents;
319
305
lbAndExtents.reserve (rank * 2 );
320
306
321
- // Get box lowerbounds and extents:
322
307
mlir::Type idxTy = builder.getIndexType ();
323
308
for (unsigned i = 0 ; i < rank; ++i) {
324
309
// TODO: ideally we want to hoist box reads out of the critical section.
325
310
// We could do this by having box dimensions in block arguments like
326
311
// OpenACC does
327
312
mlir::Value dim = builder.createIntegerConstant (loc, idxTy, i);
328
313
auto dimInfo =
329
- builder.create <fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, lhs, dim);
330
- extents.push_back (dimInfo.getExtent ());
314
+ builder.create <fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, dim);
331
315
lbAndExtents.push_back (dimInfo.getLowerBound ());
332
316
lbAndExtents.push_back (dimInfo.getExtent ());
333
317
}
334
318
335
319
auto shapeShiftTy = fir::ShapeShiftType::get (builder.getContext (), rank);
336
320
auto shapeShift =
337
321
builder.create <fir::ShapeShiftOp>(loc, shapeShiftTy, lbAndExtents);
322
+ return shapeShift;
323
+ }
324
+
325
+ // / Create reduction combiner region for reduction variables which are boxed
326
+ // / arrays
327
+ static void genBoxCombiner (fir::FirOpBuilder &builder, mlir::Location loc,
328
+ ReductionProcessor::ReductionIdentifier redId,
329
+ fir::BaseBoxType boxTy, mlir::Value lhs,
330
+ mlir::Value rhs) {
331
+ fir::SequenceType seqTy =
332
+ mlir::dyn_cast_or_null<fir::SequenceType>(boxTy.getEleTy ());
333
+ // TODO: support allocatable arrays: !fir.box<!fir.heap<!fir.array<...>>>
334
+ if (!seqTy || seqTy.hasUnknownShape ())
335
+ TODO (loc, " Unsupported boxed type in OpenMP reduction" );
336
+
337
+ // load fir.ref<fir.box<...>>
338
+ mlir::Value lhsAddr = lhs;
339
+ lhs = builder.create <fir::LoadOp>(loc, lhs);
340
+ rhs = builder.create <fir::LoadOp>(loc, rhs);
341
+
342
+ fir::ShapeShiftOp shapeShift = getShapeShift (builder, loc, lhs);
338
343
339
344
// Iterate over array elements, applying the equivalent scalar reduction:
340
345
341
346
// A hlfir::elemental here gets inlined with a temporary so create the
342
347
// loop nest directly.
343
348
// This function already controls all of the code in this region so we
344
349
// know this won't miss any opportuinties for clever elemental inlining
345
- hlfir::LoopNest nest =
346
- hlfir::genLoopNest ( loc, builder, extents , /* isUnordered=*/ true );
350
+ hlfir::LoopNest nest = hlfir::genLoopNest (
351
+ loc, builder, shapeShift. getExtents () , /* isUnordered=*/ true );
347
352
builder.setInsertionPointToStart (nest.innerLoop .getBody ());
348
353
mlir::Type refTy = fir::ReferenceType::get (seqTy.getEleTy ());
349
354
auto lhsEleAddr = builder.create <fir::ArrayCoorOp>(
@@ -470,7 +475,9 @@ createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc,
470
475
if (!mlir::isa<fir::SequenceType>(innerTy))
471
476
TODO (loc, " Unsupported boxed type for reduction" );
472
477
// Create the private copy from the initial fir.box:
473
- hlfir::Entity source = hlfir::Entity{builder.getBlock ()->getArgument (0 )};
478
+ mlir::Value loadedBox =
479
+ builder.loadIfRef (loc, builder.getBlock ()->getArgument (0 ));
480
+ hlfir::Entity source = hlfir::Entity{loadedBox};
474
481
475
482
// Allocating on the heap in case the whole reduction is nested inside of a
476
483
// loop
@@ -491,7 +498,21 @@ createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc,
491
498
}
492
499
493
500
// Put the temporary inside of a box:
494
- hlfir::Entity box = hlfir::genVariableBox (loc, builder, temp);
501
+ // hlfir::genVariableBox doesn't handle non-default lower bounds
502
+ mlir::Value box;
503
+ fir::ShapeShiftOp shapeShift = getShapeShift (builder, loc, loadedBox);
504
+ mlir::Type boxType = loadedBox.getType ();
505
+ if (mlir::isa<fir::BaseBoxType>(temp.getType ()))
506
+ // the box created by the declare form createTempFromMold is missing lower
507
+ // bounds info
508
+ box = builder.create <fir::ReboxOp>(loc, boxType, temp, shapeShift,
509
+ /* shift=*/ mlir::Value{});
510
+ else
511
+ box = builder.create <fir::EmboxOp>(
512
+ loc, boxType, temp, shapeShift,
513
+ /* slice=*/ mlir::Value{},
514
+ /* typeParams=*/ llvm::ArrayRef<mlir::Value>{});
515
+
495
516
builder.create <hlfir::AssignOp>(loc, initValue, box);
496
517
mlir::Value boxAlloca = builder.create <fir::AllocaOp>(loc, ty);
497
518
builder.create <fir::StoreOp>(loc, box, boxAlloca);
0 commit comments