https://github.com/tblah updated https://github.com/llvm/llvm-project/pull/125901
>From 8a7e449cfa357e18ba094cc61d14bf481668ddcd Mon Sep 17 00:00:00 2001 From: Tom Eccles <tom.ecc...@arm.com> Date: Wed, 5 Feb 2025 17:29:42 +0000 Subject: [PATCH] [flang][Lower][OpenMP] Don't read moldarg for static sized array This should further reduce the number of spurious barriers --- .../lib/Lower/OpenMP/DataSharingProcessor.cpp | 5 +- .../Lower/OpenMP/PrivateReductionUtils.cpp | 61 +++++++++++++------ .../lib/Lower/OpenMP/PrivateReductionUtils.h | 6 +- .../OpenMP/delayed-privatization-array.f90 | 7 +-- 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 55f543ca38178d1..800d332b74e3182 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -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"; @@ -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(); @@ -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()) diff --git a/flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp b/flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp index 951293b133677d3..e970968eb72887b 100644 --- a/flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp +++ b/flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp @@ -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); @@ -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); } @@ -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 definately 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); } @@ -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()); @@ -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(), + cannotHaveNonDefaultLowerBounds); mlir::Type boxType = getLoadedMoldArg().getType(); if (mlir::isa<fir::BaseBoxType>(temp.getType())) // the box created by the declare form createTempFromMold is missing @@ -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) diff --git a/flang/lib/Lower/OpenMP/PrivateReductionUtils.h b/flang/lib/Lower/OpenMP/PrivateReductionUtils.h index fcd36392a29e0a5..0a3513bff19b0cb 100644 --- a/flang/lib/Lower/OpenMP/PrivateReductionUtils.h +++ b/flang/lib/Lower/OpenMP/PrivateReductionUtils.h @@ -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 diff --git a/flang/test/Lower/OpenMP/delayed-privatization-array.f90 b/flang/test/Lower/OpenMP/delayed-privatization-array.f90 index 95fa3f9e0305274..c447fa6f27a7592 100644 --- a/flang/test/Lower/OpenMP/delayed-privatization-array.f90 +++ b/flang/test/Lower/OpenMP/delayed-privatization-array.f90 @@ -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]]) _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits