@@ -295,6 +295,33 @@ mlir::Value ReductionProcessor::createScalarCombiner(
295
295
return reductionOp;
296
296
}
297
297
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 ();
304
+ llvm::SmallVector<mlir::Value> lbAndExtents;
305
+ lbAndExtents.reserve (rank * 2 );
306
+
307
+ mlir::Type idxTy = builder.getIndexType ();
308
+ for (unsigned i = 0 ; i < rank; ++i) {
309
+ // TODO: ideally we want to hoist box reads out of the critical section.
310
+ // We could do this by having box dimensions in block arguments like
311
+ // OpenACC does
312
+ mlir::Value dim = builder.createIntegerConstant (loc, idxTy, i);
313
+ auto dimInfo =
314
+ builder.create <fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, dim);
315
+ lbAndExtents.push_back (dimInfo.getLowerBound ());
316
+ lbAndExtents.push_back (dimInfo.getExtent ());
317
+ }
318
+
319
+ auto shapeShiftTy = fir::ShapeShiftType::get (builder.getContext (), rank);
320
+ auto shapeShift =
321
+ builder.create <fir::ShapeShiftOp>(loc, shapeShiftTy, lbAndExtents);
322
+ return shapeShift;
323
+ }
324
+
298
325
// / Create reduction combiner region for reduction variables which are boxed
299
326
// / arrays
300
327
static void genBoxCombiner (fir::FirOpBuilder &builder, mlir::Location loc,
@@ -330,29 +357,7 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc,
330
357
return ;
331
358
}
332
359
333
- const unsigned rank = seqTy.getDimension ();
334
- llvm::SmallVector<mlir::Value> extents;
335
- extents.reserve (rank);
336
- llvm::SmallVector<mlir::Value> lbAndExtents;
337
- lbAndExtents.reserve (rank * 2 );
338
-
339
- // Get box lowerbounds and extents:
340
- mlir::Type idxTy = builder.getIndexType ();
341
- for (unsigned i = 0 ; i < rank; ++i) {
342
- // TODO: ideally we want to hoist box reads out of the critical section.
343
- // We could do this by having box dimensions in block arguments like
344
- // OpenACC does
345
- mlir::Value dim = builder.createIntegerConstant (loc, idxTy, i);
346
- auto dimInfo =
347
- builder.create <fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, lhs, dim);
348
- extents.push_back (dimInfo.getExtent ());
349
- lbAndExtents.push_back (dimInfo.getLowerBound ());
350
- lbAndExtents.push_back (dimInfo.getExtent ());
351
- }
352
-
353
- auto shapeShiftTy = fir::ShapeShiftType::get (builder.getContext (), rank);
354
- auto shapeShift =
355
- builder.create <fir::ShapeShiftOp>(loc, shapeShiftTy, lbAndExtents);
360
+ fir::ShapeShiftOp shapeShift = getShapeShift (builder, loc, lhs);
356
361
357
362
// Iterate over array elements, applying the equivalent scalar reduction:
358
363
@@ -364,8 +369,8 @@ static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc,
364
369
// loop nest directly.
365
370
// This function already controls all of the code in this region so we
366
371
// know this won't miss any opportuinties for clever elemental inlining
367
- hlfir::LoopNest nest =
368
- hlfir::genLoopNest ( loc, builder, extents , /* isUnordered=*/ true );
372
+ hlfir::LoopNest nest = hlfir::genLoopNest (
373
+ loc, builder, shapeShift. getExtents () , /* isUnordered=*/ true );
369
374
builder.setInsertionPointToStart (nest.innerLoop .getBody ());
370
375
mlir::Type refTy = fir::ReferenceType::get (seqTy.getEleTy ());
371
376
auto lhsEleAddr = builder.create <fir::ArrayCoorOp>(
@@ -561,7 +566,8 @@ createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc,
561
566
}
562
567
563
568
// Create the private copy from the initial fir.box:
564
- hlfir::Entity source = hlfir::Entity{blockArg};
569
+ mlir::Value loadedBox = builder.loadIfRef (loc, blockArg);
570
+ hlfir::Entity source = hlfir::Entity{loadedBox};
565
571
566
572
// Allocating on the heap in case the whole reduction is nested inside of a
567
573
// loop
@@ -585,11 +591,23 @@ createReductionInitRegion(fir::FirOpBuilder &builder, mlir::Location loc,
585
591
}
586
592
587
593
// Put the temporary inside of a box:
588
- hlfir::Entity box = hlfir::genVariableBox (loc, builder, temp);
589
- // hlfir::genVariableBox removes fir.heap<> around the element type
590
- mlir::Value convertedBox = builder.createConvert (loc, ty, box.getBase ());
591
- builder.create <hlfir::AssignOp>(loc, initValue, convertedBox);
592
- builder.create <fir::StoreOp>(loc, convertedBox, boxAlloca);
594
+ // hlfir::genVariableBox doesn't handle non-default lower bounds
595
+ mlir::Value box;
596
+ fir::ShapeShiftOp shapeShift = getShapeShift (builder, loc, loadedBox);
597
+ mlir::Type boxType = loadedBox.getType ();
598
+ if (mlir::isa<fir::BaseBoxType>(temp.getType ()))
599
+ // the box created by the declare form createTempFromMold is missing lower
600
+ // bounds info
601
+ box = builder.create <fir::ReboxOp>(loc, boxType, temp, shapeShift,
602
+ /* shift=*/ mlir::Value{});
603
+ else
604
+ box = builder.create <fir::EmboxOp>(
605
+ loc, boxType, temp, shapeShift,
606
+ /* slice=*/ mlir::Value{},
607
+ /* typeParams=*/ llvm::ArrayRef<mlir::Value>{});
608
+
609
+ builder.create <hlfir::AssignOp>(loc, initValue, box);
610
+ builder.create <fir::StoreOp>(loc, box, boxAlloca);
593
611
if (ifUnallocated)
594
612
builder.setInsertionPointAfter (ifUnallocated);
595
613
return boxAlloca;
0 commit comments