diff --git a/flang/lib/Lower/OpenMP/PrivateReductionUtils.h b/flang/include/flang/Lower/Support/PrivateReductionUtils.h similarity index 89% rename from flang/lib/Lower/OpenMP/PrivateReductionUtils.h rename to flang/include/flang/Lower/Support/PrivateReductionUtils.h index 9f8c9aee4d8ec..7c0f11a24afd8 100644 --- a/flang/lib/Lower/OpenMP/PrivateReductionUtils.h +++ b/flang/include/flang/Lower/Support/PrivateReductionUtils.h @@ -35,12 +35,14 @@ namespace Fortran { namespace lower { class AbstractConverter; -namespace omp { - -enum class DeclOperationKind { Private, FirstPrivate, Reduction }; +enum class DeclOperationKind { + PrivateOrLocal, + FirstPrivateOrLocalInit, + Reduction +}; inline bool isPrivatization(DeclOperationKind kind) { - return (kind == DeclOperationKind::FirstPrivate) || - (kind == DeclOperationKind::Private); + return (kind == DeclOperationKind::FirstPrivateOrLocalInit) || + (kind == DeclOperationKind::PrivateOrLocal); } inline bool isReduction(DeclOperationKind kind) { return kind == DeclOperationKind::Reduction; @@ -56,7 +58,7 @@ void populateByRefInitAndCleanupRegions( mlir::Value allocatedPrivVarArg, mlir::Value moldArg, mlir::Region &cleanupRegion, DeclOperationKind kind, const Fortran::semantics::Symbol *sym = nullptr, - bool cannotHaveNonDefaultLowerBounds = false); + bool cannotHaveNonDefaultLowerBounds = false, bool isDoConcurrent = false); /// Generate a fir::ShapeShift op describing the provided boxed array. /// `cannotHaveNonDefaultLowerBounds` should be set if `box` is known to have @@ -69,7 +71,6 @@ fir::ShapeShiftOp getShapeShift(fir::FirOpBuilder &builder, mlir::Location loc, bool cannotHaveNonDefaultLowerBounds = false, bool useDefaultLowerBounds = false); -} // namespace omp } // namespace lower } // namespace Fortran diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h index 8ad3a903beee9..e544542e2ff71 100644 --- a/flang/include/flang/Lower/Support/Utils.h +++ b/flang/include/flang/Lower/Support/Utils.h @@ -20,6 +20,7 @@ #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/BuiltinAttributes.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringRef.h" namespace Fortran::lower { @@ -98,8 +99,9 @@ bool isEqual(const Fortran::lower::ExplicitIterSpace::ArrayBases &x, template void privatizeSymbol( lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder, - lower::SymMap &symTable, std::function initGen, + lower::SymMap &symTable, llvm::SetVector &allPrivatizedSymbols, + llvm::SmallSet &mightHaveReadHostSym, const semantics::Symbol *symToPrivatize, OperandsStructType *clauseOps); } // end namespace Fortran::lower diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 1970c2263f318..64b16b3abe991 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -12,7 +12,6 @@ #include "flang/Lower/Bridge.h" -#include "OpenMP/DataSharingProcessor.h" #include "flang/Lower/Allocatable.h" #include "flang/Lower/CallInterface.h" #include "flang/Lower/Coarray.h" @@ -2040,44 +2039,38 @@ class FirConverter : public Fortran::lower::AbstractConverter { bool useDelayedPriv = enableDelayedPrivatizationStaging && doConcurrentLoopOp; llvm::SetVector allPrivatizedSymbols; + llvm::SmallSet mightHaveReadHostSym; - for (const Fortran::semantics::Symbol *sym : info.localSymList) { + for (const Fortran::semantics::Symbol *symToPrivatize : info.localSymList) { if (useDelayedPriv) { Fortran::lower::privatizeSymbol( - *this, this->getFirOpBuilder(), localSymbols, - [this](fir::LocalitySpecifierOp result, mlir::Type argType) { - TODO(this->toLocation(), - "Localizers that need init regions are not supported yet."); - }, - allPrivatizedSymbols, sym, &privateClauseOps); + *this, this->getFirOpBuilder(), localSymbols, allPrivatizedSymbols, + mightHaveReadHostSym, symToPrivatize, &privateClauseOps); continue; } - createHostAssociateVarClone(*sym, /*skipDefaultInit=*/false); + createHostAssociateVarClone(*symToPrivatize, /*skipDefaultInit=*/false); } - for (const Fortran::semantics::Symbol *sym : info.localInitSymList) { + for (const Fortran::semantics::Symbol *symToPrivatize : + info.localInitSymList) { if (useDelayedPriv) { Fortran::lower::privatizeSymbol( - *this, this->getFirOpBuilder(), localSymbols, - [this](fir::LocalitySpecifierOp result, mlir::Type argType) { - TODO(this->toLocation(), - "Localizers that need init regions are not supported yet."); - }, - allPrivatizedSymbols, sym, &privateClauseOps); + *this, this->getFirOpBuilder(), localSymbols, allPrivatizedSymbols, + mightHaveReadHostSym, symToPrivatize, &privateClauseOps); continue; } - createHostAssociateVarClone(*sym, /*skipDefaultInit=*/true); + createHostAssociateVarClone(*symToPrivatize, /*skipDefaultInit=*/true); const auto *hostDetails = - sym->detailsIf(); + symToPrivatize->detailsIf(); assert(hostDetails && "missing locality spec host symbol"); const Fortran::semantics::Symbol *hostSym = &hostDetails->symbol(); Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext}; Fortran::evaluate::Assignment assign{ - ea.Designate(Fortran::evaluate::DataRef{*sym}).value(), + ea.Designate(Fortran::evaluate::DataRef{*symToPrivatize}).value(), ea.Designate(Fortran::evaluate::DataRef{*hostSym}).value()}; - if (Fortran::semantics::IsPointer(*sym)) + if (Fortran::semantics::IsPointer(*symToPrivatize)) assign.u = Fortran::evaluate::Assignment::BoundsSpec{}; genAssignment(assign); } diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt index bc817ff8f1f3e..9c5db2b126510 100644 --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -28,11 +28,11 @@ add_flang_library(FortranLower OpenMP/DataSharingProcessor.cpp OpenMP/Decomposer.cpp OpenMP/OpenMP.cpp - OpenMP/PrivateReductionUtils.cpp OpenMP/ReductionProcessor.cpp OpenMP/Utils.cpp PFTBuilder.cpp Runtime.cpp + Support/PrivateReductionUtils.cpp Support/Utils.cpp SymbolMap.cpp VectorSubscripts.cpp diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 03109c82a976a..8b334d7a392ac 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -12,10 +12,10 @@ #include "DataSharingProcessor.h" -#include "PrivateReductionUtils.h" #include "Utils.h" #include "flang/Lower/ConvertVariable.h" #include "flang/Lower/PFTBuilder.h" +#include "flang/Lower/Support/PrivateReductionUtils.h" #include "flang/Lower/Support/Utils.h" #include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/BoxValue.h" @@ -537,38 +537,10 @@ void DataSharingProcessor::privatizeSymbol( return; } - auto initGen = [&](mlir::omp::PrivateClauseOp result, mlir::Type argType) { - lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*symToPrivatize); - assert(hsb && "Host symbol box not found"); - hlfir::Entity entity{hsb.getAddr()}; - bool cannotHaveNonDefaultLowerBounds = - !entity.mayHaveNonDefaultLowerBounds(); - - mlir::Region &initRegion = result.getInitRegion(); - mlir::Location symLoc = hsb.getAddr().getLoc(); - mlir::Block *initBlock = firOpBuilder.createBlock( - &initRegion, /*insertPt=*/{}, {argType, argType}, {symLoc, symLoc}); - - bool emitCopyRegion = - symToPrivatize->test(semantics::Symbol::Flag::OmpFirstPrivate); - - populateByRefInitAndCleanupRegions( - converter, symLoc, argType, /*scalarInitValue=*/nullptr, initBlock, - result.getInitPrivateArg(), result.getInitMoldArg(), - result.getDeallocRegion(), - emitCopyRegion ? omp::DeclOperationKind::FirstPrivate - : omp::DeclOperationKind::Private, - symToPrivatize, cannotHaveNonDefaultLowerBounds); - // TODO: currently there are false positives from dead uses of the mold - // arg - if (result.initReadsFromMold()) - mightHaveReadHostSym.insert(symToPrivatize); - }; - Fortran::lower::privatizeSymbol( - converter, firOpBuilder, symTable, initGen, allPrivatizedSymbols, - symToPrivatize, clauseOps); + converter, firOpBuilder, symTable, allPrivatizedSymbols, + mightHaveReadHostSym, symToPrivatize, clauseOps); } } // namespace omp } // namespace lower diff --git a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp index 7ef0f2a0ef7c5..d7f520e86e532 100644 --- a/flang/lib/Lower/OpenMP/ReductionProcessor.cpp +++ b/flang/lib/Lower/OpenMP/ReductionProcessor.cpp @@ -12,9 +12,9 @@ #include "ReductionProcessor.h" -#include "PrivateReductionUtils.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/ConvertType.h" +#include "flang/Lower/Support/PrivateReductionUtils.h" #include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/Complex.h" #include "flang/Optimizer/Builder/HLFIRTools.h" diff --git a/flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp b/flang/lib/Lower/Support/PrivateReductionUtils.cpp similarity index 95% rename from flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp rename to flang/lib/Lower/Support/PrivateReductionUtils.cpp index 268c7828ab56f..595d1fa1490e0 100644 --- a/flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp +++ b/flang/lib/Lower/Support/PrivateReductionUtils.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "PrivateReductionUtils.h" +#include "flang/Lower/Support/PrivateReductionUtils.h" #include "flang/Lower/AbstractConverter.h" #include "flang/Lower/Allocatable.h" @@ -42,7 +42,8 @@ static bool hasFinalization(const Fortran::semantics::Symbol &sym) { static void createCleanupRegion(Fortran::lower::AbstractConverter &converter, mlir::Location loc, mlir::Type argType, mlir::Region &cleanupRegion, - const Fortran::semantics::Symbol *sym) { + const Fortran::semantics::Symbol *sym, + bool isDoConcurrent) { fir::FirOpBuilder &builder = converter.getFirOpBuilder(); assert(cleanupRegion.empty()); mlir::Block *block = builder.createBlock(&cleanupRegion, cleanupRegion.end(), @@ -72,7 +73,10 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter, fir::MutableBoxValue mutableBox{converted, /*lenParameters=*/{}, /*mutableProperties=*/{}}; Fortran::lower::genDeallocateIfAllocated(converter, mutableBox, loc); - builder.create(loc); + if (isDoConcurrent) + builder.create(loc); + else + builder.create(loc); return; } } @@ -100,7 +104,10 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter, builder.create(loc, cast); builder.setInsertionPointAfter(ifOp); - builder.create(loc); + if (isDoConcurrent) + builder.create(loc); + else + builder.create(loc); return; } @@ -115,14 +122,18 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter, addr = builder.createConvert(loc, heapTy, addr); builder.create(loc, addr); - builder.create(loc); + if (isDoConcurrent) + builder.create(loc); + else + builder.create(loc); + return; } typeError(); } -fir::ShapeShiftOp Fortran::lower::omp::getShapeShift( +fir::ShapeShiftOp Fortran::lower::getShapeShift( fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value box, bool cannotHaveNonDefaultLowerBounds, bool useDefaultLowerBounds) { fir::SequenceType sequenceType = mlir::cast( @@ -262,7 +273,7 @@ static mlir::Value generateZeroShapeForRank(fir::FirOpBuilder &builder, } namespace { -using namespace Fortran::lower::omp; +using namespace Fortran::lower; /// Class to store shared data so we don't have to maintain so many function /// arguments class PopulateInitAndCleanupRegionsHelper { @@ -273,12 +284,13 @@ class PopulateInitAndCleanupRegionsHelper { mlir::Value allocatedPrivVarArg, mlir::Value moldArg, mlir::Block *initBlock, mlir::Region &cleanupRegion, DeclOperationKind kind, const Fortran::semantics::Symbol *sym, - bool cannotHaveLowerBounds) + bool cannotHaveLowerBounds, bool isDoConcurrent) : converter{converter}, builder{converter.getFirOpBuilder()}, loc{loc}, argType{argType}, scalarInitValue{scalarInitValue}, allocatedPrivVarArg{allocatedPrivVarArg}, moldArg{moldArg}, initBlock{initBlock}, cleanupRegion{cleanupRegion}, kind{kind}, - sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds} { + sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds}, + isDoConcurrent{isDoConcurrent} { valType = fir::unwrapRefType(argType); } @@ -324,8 +336,13 @@ class PopulateInitAndCleanupRegionsHelper { /// lower bounds then we don't need to generate code to read them. bool cannotHaveNonDefaultLowerBounds; + bool isDoConcurrent; + void createYield(mlir::Value ret) { - builder.create(loc, ret); + if (isDoConcurrent) + builder.create(loc, ret); + else + builder.create(loc, ret); } void initTrivialType() { @@ -429,11 +446,12 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedScalar( /*slice=*/mlir::Value{}, lenParams); initializeIfDerivedTypeBox( builder, loc, box, getLoadedMoldArg(), needsInitialization, - /*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivate); + /*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit); fir::StoreOp lastOp = builder.create(loc, box, allocatedPrivVarArg); - createCleanupRegion(converter, loc, argType, cleanupRegion, sym); + createCleanupRegion(converter, loc, argType, cleanupRegion, sym, + isDoConcurrent); if (ifUnallocated) builder.setInsertionPointAfter(ifUnallocated); @@ -470,13 +488,14 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray( allocatedArray, shape); initializeIfDerivedTypeBox( builder, loc, firClass, source, needsInitialization, - /*isFirstprivate=*/kind == DeclOperationKind::FirstPrivate); + /*isFirstprivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit); builder.create(loc, firClass, allocatedPrivVarArg); if (ifUnallocated) builder.setInsertionPointAfter(ifUnallocated); createYield(allocatedPrivVarArg); mlir::OpBuilder::InsertionGuard guard(builder); - createCleanupRegion(converter, loc, argType, cleanupRegion, sym); + createCleanupRegion(converter, loc, argType, cleanupRegion, sym, + isDoConcurrent); return; } @@ -492,7 +511,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray( "createTempFromMold decides this statically"); if (cstNeedsDealloc.has_value() && *cstNeedsDealloc != false) { mlir::OpBuilder::InsertionGuard guard(builder); - createCleanupRegion(converter, loc, argType, cleanupRegion, sym); + createCleanupRegion(converter, loc, argType, cleanupRegion, sym, + isDoConcurrent); } else { assert(!isAllocatableOrPointer && "Pointer-like arrays must be heap allocated"); @@ -520,7 +540,7 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray( initializeIfDerivedTypeBox( builder, loc, box, getLoadedMoldArg(), needsInitialization, - /*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivate); + /*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit); builder.create(loc, box, allocatedPrivVarArg); if (ifUnallocated) @@ -548,7 +568,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxchar( loc, eleTy, /*name=*/{}, /*shape=*/{}, /*lenParams=*/len); mlir::Value boxChar = charExprHelper.createEmboxChar(privateAddr, len); - createCleanupRegion(converter, loc, argType, cleanupRegion, sym); + createCleanupRegion(converter, loc, argType, cleanupRegion, sym, + isDoConcurrent); builder.setInsertionPointToEnd(initBlock); createYield(boxChar); @@ -563,10 +584,11 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupUnboxedDerivedType( mlir::Value moldBox = builder.create(loc, boxedTy, moldArg); initializeIfDerivedTypeBox(builder, loc, newBox, moldBox, needsInitialization, /*isFirstPrivate=*/kind == - DeclOperationKind::FirstPrivate); + DeclOperationKind::FirstPrivateOrLocalInit); if (sym && hasFinalization(*sym)) - createCleanupRegion(converter, loc, argType, cleanupRegion, sym); + createCleanupRegion(converter, loc, argType, cleanupRegion, sym, + isDoConcurrent); builder.setInsertionPointToEnd(initBlock); createYield(allocatedPrivVarArg); @@ -632,15 +654,17 @@ void PopulateInitAndCleanupRegionsHelper::populateByRefInitAndCleanupRegions() { "creating reduction/privatization init region for unsupported type"); } -void Fortran::lower::omp::populateByRefInitAndCleanupRegions( +void Fortran::lower::populateByRefInitAndCleanupRegions( Fortran::lower::AbstractConverter &converter, mlir::Location loc, 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, bool cannotHaveLowerBounds) { + const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds, + bool isDoConcurrent) { PopulateInitAndCleanupRegionsHelper helper( converter, loc, argType, scalarInitValue, allocatedPrivVarArg, moldArg, - initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds); + initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds, + isDoConcurrent); helper.populateByRefInitAndCleanupRegions(); // Often we load moldArg to check something (e.g. length parameters, shape) diff --git a/flang/lib/Lower/Support/Utils.cpp b/flang/lib/Lower/Support/Utils.cpp index 2de9db992e278..674f9911b1276 100644 --- a/flang/lib/Lower/Support/Utils.cpp +++ b/flang/lib/Lower/Support/Utils.cpp @@ -14,6 +14,7 @@ #include "flang/Common/indirection.h" #include "flang/Lower/IterationSpace.h" +#include "flang/Lower/Support/PrivateReductionUtils.h" #include "flang/Semantics/tools.h" #include #include @@ -645,17 +646,26 @@ void copyFirstPrivateSymbol(lower::AbstractConverter &converter, template void privatizeSymbol( lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder, - lower::SymMap &symTable, std::function initGen, + lower::SymMap &symTable, llvm::SetVector &allPrivatizedSymbols, + llvm::SmallSet &mightHaveReadHostSym, const semantics::Symbol *symToPrivatize, OperandsStructType *clauseOps) { - const semantics::Symbol *sym = symToPrivatize->HasLocalLocality() - ? &symToPrivatize->GetUltimate() - : symToPrivatize; - lower::SymbolBox hsb = symToPrivatize->HasLocalLocality() - ? converter.shallowLookupSymbol(*sym) - : converter.lookupOneLevelUpSymbol(*sym); + constexpr bool isDoConcurrent = + std::is_same_v; + mlir::OpBuilder::InsertPoint dcIP; + + if (isDoConcurrent) { + dcIP = firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPoint( + firOpBuilder.getRegion().getParentOfType()); + } + + const semantics::Symbol *sym = + isDoConcurrent ? &symToPrivatize->GetUltimate() : symToPrivatize; + const lower::SymbolBox hsb = isDoConcurrent + ? converter.shallowLookupSymbol(*sym) + : converter.lookupOneLevelUpSymbol(*sym); assert(hsb && "Host symbol box not found"); - hlfir::Entity entity{hsb.getAddr()}; mlir::Location symLoc = hsb.getAddr().getLoc(); std::string privatizerName = sym->name().ToString() + ".privatizer"; @@ -678,6 +688,7 @@ void privatizeSymbol( // an alloca for a fir.array type there. Get around this by boxing all // arrays. if (mlir::isa(allocType)) { + hlfir::Entity entity{hsb.getAddr()}; entity = genVariableBox(symLoc, firOpBuilder, entity); privVal = entity.getBase(); allocType = privVal.getType(); @@ -738,7 +749,35 @@ void privatizeSymbol( mlir::isa(allocType) || mlir::isa(allocType); if (needsInitialization) { - initGen(result, argType); + lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol( + isDoConcurrent ? symToPrivatize->GetUltimate() : *symToPrivatize); + + assert(hsb && "Host symbol box not found"); + hlfir::Entity entity{hsb.getAddr()}; + bool cannotHaveNonDefaultLowerBounds = + !entity.mayHaveNonDefaultLowerBounds(); + + mlir::Region &initRegion = result.getInitRegion(); + mlir::Location symLoc = hsb.getAddr().getLoc(); + mlir::Block *initBlock = firOpBuilder.createBlock( + &initRegion, /*insertPt=*/{}, {argType, argType}, {symLoc, symLoc}); + + bool emitCopyRegion = + symToPrivatize->test(semantics::Symbol::Flag::OmpFirstPrivate) || + symToPrivatize->test( + Fortran::semantics::Symbol::Flag::LocalityLocalInit); + + populateByRefInitAndCleanupRegions( + converter, symLoc, argType, /*scalarInitValue=*/nullptr, initBlock, + result.getInitPrivateArg(), result.getInitMoldArg(), + result.getDeallocRegion(), + emitCopyRegion ? DeclOperationKind::FirstPrivateOrLocalInit + : DeclOperationKind::PrivateOrLocal, + symToPrivatize, cannotHaveNonDefaultLowerBounds, isDoConcurrent); + // TODO: currently there are false positives from dead uses of the mold + // arg + if (result.initReadsFromMold()) + mightHaveReadHostSym.insert(symToPrivatize); } // Populate the `copy` region if this is a `firstprivate`. @@ -790,16 +829,19 @@ void privatizeSymbol( clauseOps->privateVars.push_back(privVal); } - if (symToPrivatize->HasLocalLocality()) + if (isDoConcurrent) allPrivatizedSymbols.insert(symToPrivatize); + + if (isDoConcurrent) + firOpBuilder.restoreInsertionPoint(dcIP); } template void privatizeSymbol( lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder, lower::SymMap &symTable, - std::function initGen, llvm::SetVector &allPrivatizedSymbols, + llvm::SmallSet &mightHaveReadHostSym, const semantics::Symbol *symToPrivatize, mlir::omp::PrivateClauseOps *clauseOps); @@ -807,8 +849,8 @@ template void privatizeSymbol( lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder, lower::SymMap &symTable, - std::function initGen, llvm::SetVector &allPrivatizedSymbols, + llvm::SmallSet &mightHaveReadHostSym, const semantics::Symbol *symToPrivatize, fir::LocalitySpecifierOperands *clauseOps); diff --git a/flang/test/Lower/do_concurrent_local_assoc_entity.f90 b/flang/test/Lower/do_concurrent_local_assoc_entity.f90 index 280827871aaf4..ee931ffdfdcc7 100644 --- a/flang/test/Lower/do_concurrent_local_assoc_entity.f90 +++ b/flang/test/Lower/do_concurrent_local_assoc_entity.f90 @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -mmlir --enable-delayed-privatization-staging=true -o - %s | FileCheck %s subroutine local_assoc implicit none @@ -12,11 +12,27 @@ subroutine local_assoc end associate end subroutine local_assoc -! CHECK: %[[C8:.*]] = arith.constant 8 : index +! CHECK: fir.local {type = local} @[[LOCALIZER:.*local_assocEa.*]] : !fir.box> init { +! CHECK-NEXT: ^{{.*}}(%{{.*}}: !{{.*}}, %[[LOCAL_ARG:.*]]: !{{.*}}): +! CHECK-NEXT: %[[C8:.*]] = arith.constant 8 : index +! CHECK-NEXT: %[[SHAPE:.*]] = fir.shape %[[C8]] +! CHECK-NEXT: %[[TMP_ALLOC:.*]] = fir.allocmem !{{.*}} {bindc_name = ".tmp", {{.*}}} +! CHECK: %[[TMP_DECL:.*]]:2 = hlfir.declare %[[TMP_ALLOC]](%[[SHAPE]]) +! CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index +! CHECK-NEXT: %[[C8:.*]] = arith.constant 8 : index +! CHECK-NEXT: %[[SHAPE_SHIFT:.*]] = fir.shape_shift %[[C1]], %[[C8]] +! CHECK-NEXT: %[[TMP_BOX:.*]] = fir.embox %[[TMP_DECL]]#0(%[[SHAPE_SHIFT]]) +! CHECK-NEXT: fir.store %[[TMP_BOX]] to %[[LOCAL_ARG]] +! CHECK-NEXT: fir.yield(%[[LOCAL_ARG]] : !fir.ref>>) +! CHECK-NEXT: } -! CHECK: fir.do_concurrent.loop {{.*}} { -! CHECK: %[[LOCAL_ALLOC:.*]] = fir.alloca !fir.array<8xf32> {bindc_name = "a", pinned, uniq_name = "{{.*}}local_assocEa"} -! CHECK: %[[LOCAL_SHAPE:.*]] = fir.shape %[[C8]] : -! CHECK: %[[LOCAL_DECL:.*]]:2 = hlfir.declare %[[LOCAL_ALLOC]](%[[LOCAL_SHAPE]]) -! CHECK: hlfir.designate %[[LOCAL_DECL]]#0 (%{{.*}}) +! CHECK: func.func @_QPlocal_assoc() +! CHECK: %[[BOX_REF:.*]] = fir.alloca !fir.box> +! CHECK: %[[ASSOC_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "{{.*}}local_assocEa"} +! CHECK: %[[ASSOC_BOX:.*]] = fir.embox %[[ASSOC_DECL]]#0(%{{.*}}) +! CHECK: fir.store %[[ASSOC_BOX]] to %[[BOX_REF]] +! CHECK: fir.do_concurrent.loop {{.*}} local(@[[LOCALIZER]] %[[BOX_REF]] -> %[[LOCAL_ARG:.*]] : !fir.ref>>) { +! CHECK: %[[LOCAL_DECL:.*]]:2 = hlfir.declare %[[LOCAL_ARG]] +! CHECK: %[[LOCAL_LD:.*]] = fir.load %[[LOCAL_DECL]]#0 : !fir.ref>> +! CHECK: hlfir.designate %[[LOCAL_LD]] (%{{.*}}) ! CHECK: } diff --git a/flang/test/Lower/do_concurrent_local_default_init.f90 b/flang/test/Lower/do_concurrent_local_default_init.f90 index 207704ac1a990..d643213854744 100644 --- a/flang/test/Lower/do_concurrent_local_default_init.f90 +++ b/flang/test/Lower/do_concurrent_local_default_init.f90 @@ -1,5 +1,5 @@ ! Test default initialization of DO CONCURRENT LOCAL() entities. -! RUN: bbc -emit-hlfir -I nowhere -o - %s | FileCheck %s +! RUN: bbc -emit-hlfir --enable-delayed-privatization-staging=true -I nowhere -o - %s | FileCheck %s subroutine test_ptr(p) interface @@ -25,28 +25,39 @@ subroutine test_default_init() end do call something(res) end subroutine + +! CHECK: fir.local {type = local} @[[DEFAULT_INIT_LOCALIZER:.*test_default_init.*]] : !fir.type<{{.*}}test_default_initTt{i:i32}> init { +! CHECK-NEXT: ^{{.*}}(%{{.*}}: !{{.*}}, %[[LOCAL_ARG:.*]]: !fir.ref>): +! CHECK-NEXT: %[[LOCAL_ARG_BOX:.*]] = fir.embox %[[LOCAL_ARG]] +! CHECK: %[[LOCAL_ARG_BOX_CVT:.*]] = fir.convert %[[LOCAL_ARG_BOX]] +! CHECK: fir.call @_FortranAInitialize(%[[LOCAL_ARG_BOX_CVT]], {{.*}}) +! CHECK-NEXT: fir.yield(%[[LOCAL_ARG]] : {{.*}}) +! CHECK-NEXT: } + +! CHECK: fir.local {type = local} @[[PTR_LOCALIZER:.*test_ptrEp_private_box.*]] : !fir.box>>> init { +! CHECK-NEXT: ^{{.*}}(%[[ORIG_ARG:.*]]: !{{.*}}, %[[LOCAL_ARG:.*]]: !{{.*}}): +! CHECK-NEXT: %[[ORIG_ARG_LD:.*]] = fir.load %[[ORIG_ARG]] +! CHECK-NEXT: %[[ELEM_SIZE:.*]] = fir.box_elesize %[[ORIG_ARG_LD]] +! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : index +! CHECK-NEXT: %[[SHAPE:.*]] = fir.shape %[[C0]] +! CHECK-NEXT: %[[ZERO_BITS:.*]] = fir.zero_bits +! CHECK-NEXT: %[[LOCAL_BOX:.*]] = fir.embox %[[ZERO_BITS]](%[[SHAPE]]) typeparams %[[ELEM_SIZE]] +! CHECK-NEXT: fir.store %[[LOCAL_BOX]] to %[[LOCAL_ARG]] +! CHECK-NEXT: fir.yield(%[[LOCAL_ARG]] : {{.*}}) +! CHECK-NEXT: } + ! CHECK-LABEL: func.func @_QPtest_ptr( ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>>>> {fir.bindc_name = "p"}) { ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_0]] : !fir.ref>>>> ! CHECK: %[[VAL_7:.*]] = fir.box_elesize %[[VAL_6]] : (!fir.box>>>) -> index -! CHECK: fir.do_concurrent.loop -! CHECK: %[[VAL_16:.*]] = fir.alloca !fir.box>>> {bindc_name = "p", pinned, uniq_name = "_QFtest_ptrEp"} -! CHECK: %[[VAL_17:.*]] = fir.zero_bits !fir.ptr>> -! CHECK: %[[VAL_18:.*]] = arith.constant 0 : index -! CHECK: %[[VAL_19:.*]] = fir.shape %[[VAL_18]] : (index) -> !fir.shape<1> -! CHECK: %[[VAL_20:.*]] = fir.embox %[[VAL_17]](%[[VAL_19]]) typeparams %[[VAL_7]] : (!fir.ptr>>, !fir.shape<1>, index) -> !fir.box>>> -! CHECK: fir.store %[[VAL_20]] to %[[VAL_16]] : !fir.ref>>>> -! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_16]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_ptrEp"} : (!fir.ref>>>>) -> (!fir.ref>>>>, !fir.ref>>>>) +! CHECK: fir.do_concurrent.loop {{.*}} local(@[[PTR_LOCALIZER]] %{{.*}}#0 -> %[[LOCAL_ARG:.*]] : {{.*}}) +! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[LOCAL_ARG]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_ptrEp"} : (!fir.ref>>>>) -> (!fir.ref>>>>, !fir.ref>>>>) ! CHECK: fir.call @_QPtakes_ptr(%[[VAL_21]]#0) proc_attrs fastmath : (!fir.ref>>>>) -> () ! CHECK: } ! CHECK: return ! CHECK: } ! CHECK-LABEL: func.func @_QPtest_default_init( -! CHECK: fir.do_concurrent.loop -! CHECK: %[[VAL_26:.*]] = fir.alloca !fir.type<_QFtest_default_initTt{i:i32}> {bindc_name = "a", pinned, uniq_name = "_QFtest_default_initEa"} -! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_26]] : (!fir.ref>) -> !fir.box> -! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_27]] : (!fir.box>) -> !fir.box -! CHECK: fir.call @_FortranAInitialize(%[[VAL_30]], {{.*}} -! CHECK: %[[VAL_33:.*]]:2 = hlfir.declare %[[VAL_26]] {uniq_name = "_QFtest_default_initEa"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: fir.do_concurrent.loop {{.*}} local(@[[DEFAULT_INIT_LOCALIZER]] %{{.*}}#0 -> %[[LOCAL_ARG:.*]] : {{.*}}) +! CHECK: %[[VAL_33:.*]]:2 = hlfir.declare %[[LOCAL_ARG]] {uniq_name = "_QFtest_default_initEa"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) ! CHECK: }