Skip to content

[flang][Lower][OpenMP] Don't read moldarg for static sized array #125901

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,8 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,

lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym);
assert(hsb && "Host symbol box not found");
hlfir::Entity entity{hsb.getAddr()};
bool cannotHaveNonDefaultLowerBounds = !entity.mayHaveNonDefaultLowerBounds();

mlir::Location symLoc = hsb.getAddr().getLoc();
std::string privatizerName = sym->name().ToString() + ".privatizer";
Expand All @@ -528,7 +530,6 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
// an alloca for a fir.array type there. Get around this by boxing all
// arrays.
if (mlir::isa<fir::SequenceType>(allocType)) {
hlfir::Entity entity{hsb.getAddr()};
entity = genVariableBox(symLoc, firOpBuilder, entity);
privVal = entity.getBase();
allocType = privVal.getType();
Expand Down Expand Up @@ -590,7 +591,7 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
result.getDeallocRegion(),
isFirstPrivate ? DeclOperationKind::FirstPrivate
: DeclOperationKind::Private,
sym);
sym, cannotHaveNonDefaultLowerBounds);
// TODO: currently there are false positives from dead uses of the mold
// arg
if (!result.getInitMoldArg().getUses().empty())
Expand Down
61 changes: 41 additions & 20 deletions flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,25 +122,40 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
typeError();
}

fir::ShapeShiftOp Fortran::lower::omp::getShapeShift(fir::FirOpBuilder &builder,
mlir::Location loc,
mlir::Value box) {
fir::ShapeShiftOp
Fortran::lower::omp::getShapeShift(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value box,
bool cannotHaveNonDefaultLowerBounds) {
fir::SequenceType sequenceType = mlir::cast<fir::SequenceType>(
hlfir::getFortranElementOrSequenceType(box.getType()));
const unsigned rank = sequenceType.getDimension();

llvm::SmallVector<mlir::Value> lbAndExtents;
lbAndExtents.reserve(rank * 2);

mlir::Type idxTy = builder.getIndexType();
for (unsigned i = 0; i < rank; ++i) {
// TODO: ideally we want to hoist box reads out of the critical section.
// We could do this by having box dimensions in block arguments like
// OpenACC does
mlir::Value dim = builder.createIntegerConstant(loc, idxTy, i);
auto dimInfo =
builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, dim);
lbAndExtents.push_back(dimInfo.getLowerBound());
lbAndExtents.push_back(dimInfo.getExtent());

if (cannotHaveNonDefaultLowerBounds && !sequenceType.hasDynamicExtents()) {
// We don't need fir::BoxDimsOp if all of the extents are statically known
// and we can assume default lower bounds. This helps avoids reads from the
// mold arg.
mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
for (int64_t extent : sequenceType.getShape()) {
assert(extent != sequenceType.getUnknownExtent());
mlir::Value extentVal = builder.createIntegerConstant(loc, idxTy, extent);
lbAndExtents.push_back(one);
lbAndExtents.push_back(extentVal);
}
} else {
for (unsigned i = 0; i < rank; ++i) {
// TODO: ideally we want to hoist box reads out of the critical section.
// We could do this by having box dimensions in block arguments like
// OpenACC does
mlir::Value dim = builder.createIntegerConstant(loc, idxTy, i);
auto dimInfo =
builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, dim);
lbAndExtents.push_back(dimInfo.getLowerBound());
lbAndExtents.push_back(dimInfo.getExtent());
}
}

auto shapeShiftTy = fir::ShapeShiftType::get(builder.getContext(), rank);
Expand Down Expand Up @@ -249,12 +264,13 @@ class PopulateInitAndCleanupRegionsHelper {
mlir::Type argType, mlir::Value scalarInitValue,
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
mlir::Block *initBlock, mlir::Region &cleanupRegion,
DeclOperationKind kind, const Fortran::semantics::Symbol *sym)
DeclOperationKind kind, const Fortran::semantics::Symbol *sym,
bool cannotHaveLowerBounds)
: converter{converter}, builder{converter.getFirOpBuilder()}, loc{loc},
argType{argType}, scalarInitValue{scalarInitValue},
allocatedPrivVarArg{allocatedPrivVarArg}, moldArg{moldArg},
initBlock{initBlock}, cleanupRegion{cleanupRegion}, kind{kind},
sym{sym} {
sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds} {
valType = fir::unwrapRefType(argType);
}

Expand Down Expand Up @@ -296,6 +312,10 @@ class PopulateInitAndCleanupRegionsHelper {
/// Any length parameters which have been fetched for the type
mlir::SmallVector<mlir::Value> lenParams;

/// If the source variable being privatized definitely can't have non-default
/// lower bounds then we don't need to generate code to read them.
bool cannotHaveNonDefaultLowerBounds;

void createYield(mlir::Value ret) {
builder.create<mlir::omp::YieldOp>(loc, ret);
}
Expand Down Expand Up @@ -433,7 +453,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
// Special case for (possibly allocatable) arrays of polymorphic types
// e.g. !fir.class<!fir.heap<!fir.array<?x!fir.type<>>>>
if (source.isPolymorphic()) {
fir::ShapeShiftOp shape = getShapeShift(builder, loc, source);
fir::ShapeShiftOp shape =
getShapeShift(builder, loc, source, cannotHaveNonDefaultLowerBounds);
mlir::Type arrayType = source.getElementOrSequenceType();
mlir::Value allocatedArray = builder.create<fir::AllocMemOp>(
loc, arrayType, /*typeparams=*/mlir::ValueRange{}, shape.getExtents());
Expand Down Expand Up @@ -472,8 +493,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
// Put the temporary inside of a box:
// hlfir::genVariableBox doesn't handle non-default lower bounds
mlir::Value box;
fir::ShapeShiftOp shapeShift =
getShapeShift(builder, loc, getLoadedMoldArg());
fir::ShapeShiftOp shapeShift = getShapeShift(builder, loc, getLoadedMoldArg(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does loading moldArg count as an use?
Or will we only insert a barrier if the loaded moldArg is referenced?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Judging by the code in #125900, if there is only a load of moldArg it will be removed and no barrier will be inserted.

cannotHaveNonDefaultLowerBounds);
mlir::Type boxType = getLoadedMoldArg().getType();
if (mlir::isa<fir::BaseBoxType>(temp.getType()))
// the box created by the declare form createTempFromMold is missing
Expand Down Expand Up @@ -608,10 +629,10 @@ void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
mlir::Type argType, mlir::Value scalarInitValue, mlir::Block *initBlock,
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
mlir::Region &cleanupRegion, DeclOperationKind kind,
const Fortran::semantics::Symbol *sym) {
const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds) {
PopulateInitAndCleanupRegionsHelper helper(
converter, loc, argType, scalarInitValue, allocatedPrivVarArg, moldArg,
initBlock, cleanupRegion, kind, sym);
initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds);
helper.populateByRefInitAndCleanupRegions();

// Often we load moldArg to check something (e.g. length parameters, shape)
Expand Down
6 changes: 4 additions & 2 deletions flang/lib/Lower/OpenMP/PrivateReductionUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ void populateByRefInitAndCleanupRegions(
mlir::Value scalarInitValue, mlir::Block *initBlock,
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
mlir::Region &cleanupRegion, DeclOperationKind kind,
const Fortran::semantics::Symbol *sym = nullptr);
const Fortran::semantics::Symbol *sym = nullptr,
bool cannotHaveNonDefaultLowerBounds = false);

/// Generate a fir::ShapeShift op describing the provided boxed array.
fir::ShapeShiftOp getShapeShift(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value box);
mlir::Value box,
bool cannotHaveNonDefaultLowerBounds = false);

} // namespace omp
} // namespace lower
Expand Down
7 changes: 3 additions & 4 deletions flang/test/Lower/OpenMP/delayed-privatization-array.f90
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,14 @@ program main
! ONE_DIM_DEFAULT_LB-SAME: @[[PRIVATIZER_SYM:.*]] : [[BOX_TYPE:!fir.box<!fir.array<10xi32>>]] init {

! ONE_DIM_DEFAULT_LB-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE:!fir.ref<!fir.box<!fir.array<10xi32>>>]], %[[PRIV_BOX_ALLOC:.*]]: [[TYPE]]):
! ONE_DIM_DEFAULT_LB-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]]
! ONE_DIM_DEFAULT_LB-NEXT: %[[C10:.*]] = arith.constant 10 : index
! ONE_DIM_DEFAULT_LB-NEXT: %[[SHAPE:.*]] = fir.shape %[[C10]]
! ONE_DIM_DEFAULT_LB-NEXT: %[[ARRAY_ALLOC:.*]] = fir.allocmem !fir.array<10xi32>
! ONE_DIM_DEFAULT_LB-NEXT: %[[TRUE:.*]] = arith.constant true
! ONE_DIM_DEFAULT_LB-NEXT: %[[DECL:.*]]:2 = hlfir.declare %[[ARRAY_ALLOC]](%[[SHAPE]])
! ONE_DIM_DEFAULT_LB-NEXT: %[[C0_0:.*]] = arith.constant 0
! ONE_DIM_DEFAULT_LB-NEXT: %[[DIMS2:.*]]:3 = fir.box_dims %[[PRIV_ARG_VAL]], %[[C0_0]]
! ONE_DIM_DEFAULT_LB-NEXT: %[[SHAPE_SHIFT:.*]] = fir.shape_shift %[[DIMS2]]#0, %[[DIMS2]]#1
! ONE_DIM_DEFAULT_LB-NEXT: %[[ONE:.*]] = arith.constant 1 : index
! ONE_DIM_DEFAULT_LB-NEXT: %[[TEN:.*]] = arith.constant 10 : index
! ONE_DIM_DEFAULT_LB-NEXT: %[[SHAPE_SHIFT:.*]] = fir.shape_shift %[[ONE]], %[[TEN]]
! ONE_DIM_DEFAULT_LB-NEXT: %[[EMBOX:.*]] = fir.embox %[[DECL]]#0(%[[SHAPE_SHIFT]])
! ONE_DIM_DEFAULT_LB-NEXT: fir.store %[[EMBOX]] to %[[PRIV_BOX_ALLOC]]
! ONE_DIM_DEFAULT_LB-NEXT: omp.yield(%[[PRIV_BOX_ALLOC]] : [[TYPE]])