[flang] Extend localization support for do concurrent (init regions) (#142564)
Extends support for locality specifiers in `do concurrent` by supporting data types that need `init` regions. This further unifies the paths taken by the compiler for OpenMP privatization clauses and `do concurrent` locality specifiers.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 <typename OpType, typename OperandsStructType>
|
||||
void privatizeSymbol(
|
||||
lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder,
|
||||
lower::SymMap &symTable, std::function<void(OpType, mlir::Type)> initGen,
|
||||
lower::SymMap &symTable,
|
||||
llvm::SetVector<const semantics::Symbol *> &allPrivatizedSymbols,
|
||||
llvm::SmallSet<const semantics::Symbol *, 16> &mightHaveReadHostSym,
|
||||
const semantics::Symbol *symToPrivatize, OperandsStructType *clauseOps);
|
||||
|
||||
} // end namespace Fortran::lower
|
||||
|
||||
@@ -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 @@ private:
|
||||
bool useDelayedPriv =
|
||||
enableDelayedPrivatizationStaging && doConcurrentLoopOp;
|
||||
llvm::SetVector<const Fortran::semantics::Symbol *> allPrivatizedSymbols;
|
||||
llvm::SmallSet<const Fortran::semantics::Symbol *, 16> mightHaveReadHostSym;
|
||||
|
||||
for (const Fortran::semantics::Symbol *sym : info.localSymList) {
|
||||
for (const Fortran::semantics::Symbol *symToPrivatize : info.localSymList) {
|
||||
if (useDelayedPriv) {
|
||||
Fortran::lower::privatizeSymbol<fir::LocalitySpecifierOp>(
|
||||
*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<fir::LocalitySpecifierOp>(
|
||||
*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<Fortran::semantics::HostAssocDetails>();
|
||||
symToPrivatize->detailsIf<Fortran::semantics::HostAssocDetails>();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<mlir::omp::PrivateClauseOp,
|
||||
mlir::omp::PrivateClauseOps>(
|
||||
converter, firOpBuilder, symTable, initGen, allPrivatizedSymbols,
|
||||
symToPrivatize, clauseOps);
|
||||
converter, firOpBuilder, symTable, allPrivatizedSymbols,
|
||||
mightHaveReadHostSym, symToPrivatize, clauseOps);
|
||||
}
|
||||
} // namespace omp
|
||||
} // namespace lower
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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<mlir::omp::YieldOp>(loc);
|
||||
if (isDoConcurrent)
|
||||
builder.create<fir::YieldOp>(loc);
|
||||
else
|
||||
builder.create<mlir::omp::YieldOp>(loc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -100,7 +104,10 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
|
||||
builder.create<fir::FreeMemOp>(loc, cast);
|
||||
|
||||
builder.setInsertionPointAfter(ifOp);
|
||||
builder.create<mlir::omp::YieldOp>(loc);
|
||||
if (isDoConcurrent)
|
||||
builder.create<fir::YieldOp>(loc);
|
||||
else
|
||||
builder.create<mlir::omp::YieldOp>(loc);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,14 +122,18 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
|
||||
addr = builder.createConvert(loc, heapTy, addr);
|
||||
|
||||
builder.create<fir::FreeMemOp>(loc, addr);
|
||||
builder.create<mlir::omp::YieldOp>(loc);
|
||||
if (isDoConcurrent)
|
||||
builder.create<fir::YieldOp>(loc);
|
||||
else
|
||||
builder.create<mlir::omp::YieldOp>(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<fir::SequenceType>(
|
||||
@@ -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 @@ public:
|
||||
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 @@ private:
|
||||
/// lower bounds then we don't need to generate code to read them.
|
||||
bool cannotHaveNonDefaultLowerBounds;
|
||||
|
||||
bool isDoConcurrent;
|
||||
|
||||
void createYield(mlir::Value ret) {
|
||||
builder.create<mlir::omp::YieldOp>(loc, ret);
|
||||
if (isDoConcurrent)
|
||||
builder.create<fir::YieldOp>(loc, ret);
|
||||
else
|
||||
builder.create<mlir::omp::YieldOp>(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<fir::StoreOp>(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<fir::StoreOp>(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<fir::StoreOp>(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<fir::EmboxOp>(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)
|
||||
@@ -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 <cstdint>
|
||||
#include <optional>
|
||||
@@ -645,17 +646,26 @@ void copyFirstPrivateSymbol(lower::AbstractConverter &converter,
|
||||
template <typename OpType, typename OperandsStructType>
|
||||
void privatizeSymbol(
|
||||
lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder,
|
||||
lower::SymMap &symTable, std::function<void(OpType, mlir::Type)> initGen,
|
||||
lower::SymMap &symTable,
|
||||
llvm::SetVector<const semantics::Symbol *> &allPrivatizedSymbols,
|
||||
llvm::SmallSet<const semantics::Symbol *, 16> &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<OpType, fir::LocalitySpecifierOp>;
|
||||
mlir::OpBuilder::InsertPoint dcIP;
|
||||
|
||||
if (isDoConcurrent) {
|
||||
dcIP = firOpBuilder.saveInsertionPoint();
|
||||
firOpBuilder.setInsertionPoint(
|
||||
firOpBuilder.getRegion().getParentOfType<fir::DoConcurrentOp>());
|
||||
}
|
||||
|
||||
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<fir::SequenceType>(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<fir::BaseBoxType>(allocType) ||
|
||||
mlir::isa<fir::BoxCharType>(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<mlir::omp::PrivateClauseOp, mlir::omp::PrivateClauseOps>(
|
||||
lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder,
|
||||
lower::SymMap &symTable,
|
||||
std::function<void(mlir::omp::PrivateClauseOp, mlir::Type)> initGen,
|
||||
llvm::SetVector<const semantics::Symbol *> &allPrivatizedSymbols,
|
||||
llvm::SmallSet<const semantics::Symbol *, 16> &mightHaveReadHostSym,
|
||||
const semantics::Symbol *symToPrivatize,
|
||||
mlir::omp::PrivateClauseOps *clauseOps);
|
||||
|
||||
@@ -807,8 +849,8 @@ template void
|
||||
privatizeSymbol<fir::LocalitySpecifierOp, fir::LocalitySpecifierOperands>(
|
||||
lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder,
|
||||
lower::SymMap &symTable,
|
||||
std::function<void(fir::LocalitySpecifierOp, mlir::Type)> initGen,
|
||||
llvm::SetVector<const semantics::Symbol *> &allPrivatizedSymbols,
|
||||
llvm::SmallSet<const semantics::Symbol *, 16> &mightHaveReadHostSym,
|
||||
const semantics::Symbol *symToPrivatize,
|
||||
fir::LocalitySpecifierOperands *clauseOps);
|
||||
|
||||
|
||||
@@ -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<!fir.array<8xf32>> 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<!fir.box<!fir.array<8xf32>>>)
|
||||
! 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<!fir.array<8xf32>>
|
||||
! 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<!fir.box<!fir.array<8xf32>>>) {
|
||||
! CHECK: %[[LOCAL_DECL:.*]]:2 = hlfir.declare %[[LOCAL_ARG]]
|
||||
! CHECK: %[[LOCAL_LD:.*]] = fir.load %[[LOCAL_DECL]]#0 : !fir.ref<!fir.box<!fir.array<8xf32>>>
|
||||
! CHECK: hlfir.designate %[[LOCAL_LD]] (%{{.*}})
|
||||
! CHECK: }
|
||||
|
||||
@@ -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<!fir.type<_QFtest_default_initTt{i:i32}>>):
|
||||
! 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<!fir.ptr<!fir.array<?x!fir.char<1,?>>>> 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.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>> {fir.bindc_name = "p"}) {
|
||||
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
|
||||
! CHECK: %[[VAL_7:.*]] = fir.box_elesize %[[VAL_6]] : (!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>) -> index
|
||||
! CHECK: fir.do_concurrent.loop
|
||||
! CHECK: %[[VAL_16:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>> {bindc_name = "p", pinned, uniq_name = "_QFtest_ptrEp"}
|
||||
! CHECK: %[[VAL_17:.*]] = fir.zero_bits !fir.ptr<!fir.array<?x!fir.char<1,?>>>
|
||||
! 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.array<?x!fir.char<1,?>>>, !fir.shape<1>, index) -> !fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>
|
||||
! CHECK: fir.store %[[VAL_20]] to %[[VAL_16]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>
|
||||
! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[VAL_16]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptrEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>)
|
||||
! CHECK: fir.do_concurrent.loop {{.*}} local(@[[PTR_LOCALIZER]] %{{.*}}#0 -> %[[LOCAL_ARG:.*]] : {{.*}})
|
||||
! CHECK: %[[VAL_21:.*]]:2 = hlfir.declare %[[LOCAL_ARG]] {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QFtest_ptrEp"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>)
|
||||
! CHECK: fir.call @_QPtakes_ptr(%[[VAL_21]]#0) proc_attrs<pure> fastmath<contract> : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x!fir.char<1,?>>>>>) -> ()
|
||||
! 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.type<_QFtest_default_initTt{i:i32}>>) -> !fir.box<!fir.type<_QFtest_default_initTt{i:i32}>>
|
||||
! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_27]] : (!fir.box<!fir.type<_QFtest_default_initTt{i:i32}>>) -> !fir.box<none>
|
||||
! CHECK: fir.call @_FortranAInitialize(%[[VAL_30]], {{.*}}
|
||||
! CHECK: %[[VAL_33:.*]]:2 = hlfir.declare %[[VAL_26]] {uniq_name = "_QFtest_default_initEa"} : (!fir.ref<!fir.type<_QFtest_default_initTt{i:i32}>>) -> (!fir.ref<!fir.type<_QFtest_default_initTt{i:i32}>>, !fir.ref<!fir.type<_QFtest_default_initTt{i:i32}>>)
|
||||
! 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.type<_QFtest_default_initTt{i:i32}>>) -> (!fir.ref<!fir.type<_QFtest_default_initTt{i:i32}>>, !fir.ref<!fir.type<_QFtest_default_initTt{i:i32}>>)
|
||||
! CHECK: }
|
||||
|
||||
Reference in New Issue
Block a user