-
Notifications
You must be signed in to change notification settings - Fork 14.1k
[flang][fir][OpenMP] Refactor privtization code into shared location #141767
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
Conversation
@llvm/pr-subscribers-flang-fir-hlfir Author: Kareem Ergawy (ergawy) ChangesRefactors the utils needed to create privtization/locatization ops for both the fir and OpenMP dialects into a shared location isolating OpenMP stuff out of it as much as possible. Patch is 22.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141767.diff 5 Files Affected:
diff --git a/flang/include/flang/Lower/Support/Utils.h b/flang/include/flang/Lower/Support/Utils.h
index baaf644dd6efb..8ad3a903beee9 100644
--- a/flang/include/flang/Lower/Support/Utils.h
+++ b/flang/include/flang/Lower/Support/Utils.h
@@ -94,6 +94,14 @@ bool isEqual(const Fortran::lower::SomeExpr *x,
const Fortran::lower::SomeExpr *y);
bool isEqual(const Fortran::lower::ExplicitIterSpace::ArrayBases &x,
const Fortran::lower::ExplicitIterSpace::ArrayBases &y);
+
+template <typename OpType, typename OperandsStructType>
+void privatizeSymbol(
+ lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder,
+ lower::SymMap &symTable, std::function<void(OpType, mlir::Type)> initGen,
+ llvm::SetVector<const semantics::Symbol *> &allPrivatizedSymbols,
+ const semantics::Symbol *symToPrivatize, OperandsStructType *clauseOps);
+
} // end namespace Fortran::lower
// DenseMapInfo for pointers to Fortran::lower::SomeExpr.
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 9f3c50a52973a..4e6db3eaa990d 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2029,10 +2029,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
void handleLocalitySpecs(const IncrementLoopInfo &info) {
Fortran::semantics::SemanticsContext &semanticsContext =
bridge.getSemanticsContext();
- // TODO Extract `DataSharingProcessor` from omp to a more general location.
- Fortran::lower::omp::DataSharingProcessor dsp(
- *this, semanticsContext, getEval(),
- /*useDelayedPrivatization=*/true, localSymbols);
fir::LocalitySpecifierOperands privateClauseOps;
auto doConcurrentLoopOp =
mlir::dyn_cast_if_present<fir::DoConcurrentLoopOp>(info.loopOp);
@@ -2041,10 +2037,17 @@ class FirConverter : public Fortran::lower::AbstractConverter {
// complete.
bool useDelayedPriv =
enableDelayedPrivatizationStaging && doConcurrentLoopOp;
+ llvm::SetVector<const Fortran::semantics::Symbol *> allPrivatizedSymbols;
for (const Fortran::semantics::Symbol *sym : info.localSymList) {
if (useDelayedPriv) {
- dsp.privatizeSymbol<fir::LocalitySpecifierOp>(sym, &privateClauseOps);
+ 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);
continue;
}
@@ -2053,7 +2056,13 @@ class FirConverter : public Fortran::lower::AbstractConverter {
for (const Fortran::semantics::Symbol *sym : info.localInitSymList) {
if (useDelayedPriv) {
- dsp.privatizeSymbol<fir::LocalitySpecifierOp>(sym, &privateClauseOps);
+ 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);
continue;
}
@@ -2083,7 +2092,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
builder->getArrayAttr(privateClauseOps.privateSyms));
for (auto [sym, privateVar] : llvm::zip_equal(
- dsp.getAllSymbolsToPrivatize(), privateClauseOps.privateVars)) {
+ allPrivatizedSymbols, privateClauseOps.privateVars)) {
auto arg = doConcurrentLoopOp.getRegion().begin()->addArgument(
privateVar.getType(), doConcurrentLoopOp.getLoc());
bindSymbol(*sym, hlfir::translateToExtendedValue(
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index 629478294ef5b..03109c82a976a 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -16,6 +16,7 @@
#include "Utils.h"
#include "flang/Lower/ConvertVariable.h"
#include "flang/Lower/PFTBuilder.h"
+#include "flang/Lower/Support/Utils.h"
#include "flang/Lower/SymbolMap.h"
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Optimizer/Builder/HLFIRTools.h"
@@ -527,188 +528,48 @@ void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) {
}
}
-template <typename OpType, typename OperandsStructType>
void DataSharingProcessor::privatizeSymbol(
- const semantics::Symbol *symToPrivatize, OperandsStructType *clauseOps) {
+ const semantics::Symbol *symToPrivatize,
+ mlir::omp::PrivateClauseOps *clauseOps) {
if (!useDelayedPrivatization) {
cloneSymbol(symToPrivatize);
copyFirstPrivateSymbol(symToPrivatize);
return;
}
- const semantics::Symbol *sym = symToPrivatize->HasLocalLocality()
- ? &symToPrivatize->GetUltimate()
- : symToPrivatize;
- lower::SymbolBox hsb = symToPrivatize->HasLocalLocality()
- ? converter.shallowLookupSymbol(*sym)
- : 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";
- bool isFirstPrivate =
- symToPrivatize->test(semantics::Symbol::Flag::OmpFirstPrivate) ||
- symToPrivatize->test(semantics::Symbol::Flag::LocalityLocalInit);
-
- mlir::Value privVal = hsb.getAddr();
- mlir::Type allocType = privVal.getType();
- if (!mlir::isa<fir::PointerType>(privVal.getType()))
- allocType = fir::unwrapRefType(privVal.getType());
-
- if (auto poly = mlir::dyn_cast<fir::ClassType>(allocType)) {
- if (!mlir::isa<fir::PointerType>(poly.getEleTy()) && isFirstPrivate)
- TODO(symLoc, "create polymorphic host associated copy");
- }
-
- // fir.array<> cannot be converted to any single llvm type and fir helpers
- // are not available in openmp to llvmir translation so we cannot generate
- // an alloca for a fir.array type there. Get around this by boxing all
- // arrays.
- if (mlir::isa<fir::SequenceType>(allocType)) {
- entity = genVariableBox(symLoc, firOpBuilder, entity);
- privVal = entity.getBase();
- allocType = privVal.getType();
- }
-
- if (mlir::isa<fir::BaseBoxType>(privVal.getType())) {
- // Boxes should be passed by reference into nested regions:
- auto oldIP = firOpBuilder.saveInsertionPoint();
- firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock());
- auto alloca = firOpBuilder.create<fir::AllocaOp>(symLoc, privVal.getType());
- firOpBuilder.restoreInsertionPoint(oldIP);
- firOpBuilder.create<fir::StoreOp>(symLoc, privVal, alloca);
- privVal = alloca;
- }
-
- mlir::Type argType = privVal.getType();
-
- OpType privatizerOp = [&]() {
- auto moduleOp = firOpBuilder.getModule();
- auto uniquePrivatizerName = fir::getTypeAsString(
- allocType, converter.getKindMap(),
- converter.mangleName(*sym) +
- (isFirstPrivate ? "_firstprivate" : "_private"));
-
- if (auto existingPrivatizer =
- moduleOp.lookupSymbol<OpType>(uniquePrivatizerName))
- return existingPrivatizer;
-
- mlir::OpBuilder::InsertionGuard guard(firOpBuilder);
- firOpBuilder.setInsertionPointToStart(moduleOp.getBody());
- OpType result;
-
- if constexpr (std::is_same_v<OpType, mlir::omp::PrivateClauseOp>) {
- result = firOpBuilder.create<OpType>(
- symLoc, uniquePrivatizerName, allocType,
- isFirstPrivate ? mlir::omp::DataSharingClauseType::FirstPrivate
- : mlir::omp::DataSharingClauseType::Private);
- } else {
- result = firOpBuilder.create<OpType>(
- symLoc, uniquePrivatizerName, allocType,
- isFirstPrivate ? fir::LocalitySpecifierType::LocalInit
- : fir::LocalitySpecifierType::Local);
- }
-
- fir::ExtendedValue symExV = converter.getSymbolExtendedValue(*sym);
- lower::SymMapScope outerScope(symTable);
-
- // Populate the `init` region.
- // We need to initialize in the following cases:
- // 1. The allocation was for a derived type which requires initialization
- // (this can be skipped if it will be initialized anyway by the copy
- // region, unless the derived type has allocatable components)
- // 2. The allocation was for any kind of box
- // 3. The allocation was for a boxed character
- const bool needsInitialization =
- (Fortran::lower::hasDefaultInitialization(sym->GetUltimate()) &&
- (!isFirstPrivate || hlfir::mayHaveAllocatableComponent(allocType))) ||
- mlir::isa<fir::BaseBoxType>(allocType) ||
- mlir::isa<fir::BoxCharType>(allocType);
- if (needsInitialization) {
- mlir::Region &initRegion = result.getInitRegion();
- mlir::Block *initBlock = firOpBuilder.createBlock(
- &initRegion, /*insertPt=*/{}, {argType, argType}, {symLoc, symLoc});
-
- populateByRefInitAndCleanupRegions(
- converter, symLoc, argType, /*scalarInitValue=*/nullptr, initBlock,
- result.getInitPrivateArg(), result.getInitMoldArg(),
- result.getDeallocRegion(),
- isFirstPrivate ? DeclOperationKind::FirstPrivate
- : DeclOperationKind::Private,
- sym, cannotHaveNonDefaultLowerBounds);
- // TODO: currently there are false positives from dead uses of the mold
- // arg
- if (result.initReadsFromMold())
- mightHaveReadHostSym.insert(sym);
- }
-
- // Populate the `copy` region if this is a `firstprivate`.
- if (isFirstPrivate) {
- mlir::Region ©Region = result.getCopyRegion();
- // First block argument corresponding to the original/host value while
- // second block argument corresponding to the privatized value.
- mlir::Block *copyEntryBlock = firOpBuilder.createBlock(
- ©Region, /*insertPt=*/{}, {argType, argType}, {symLoc, symLoc});
- firOpBuilder.setInsertionPointToEnd(copyEntryBlock);
-
- auto addSymbol = [&](unsigned argIdx, const semantics::Symbol *symToMap,
- bool force = false) {
- symExV.match(
- [&](const fir::MutableBoxValue &box) {
- symTable.addSymbol(
- *symToMap,
- fir::substBase(box, copyRegion.getArgument(argIdx)), force);
- },
- [&](const auto &box) {
- symTable.addSymbol(*symToMap, copyRegion.getArgument(argIdx),
- force);
- });
- };
-
- addSymbol(0, sym, true);
- lower::SymMapScope innerScope(symTable);
- addSymbol(1, symToPrivatize);
-
- auto ip = firOpBuilder.saveInsertionPoint();
- copyFirstPrivateSymbol(symToPrivatize, &ip);
-
- if constexpr (std::is_same_v<OpType, mlir::omp::PrivateClauseOp>) {
- firOpBuilder.create<mlir::omp::YieldOp>(
- hsb.getAddr().getLoc(),
- symTable.shallowLookupSymbol(*symToPrivatize).getAddr());
- } else {
- firOpBuilder.create<fir::YieldOp>(
- hsb.getAddr().getLoc(),
- symTable.shallowLookupSymbol(*symToPrivatize).getAddr());
- }
- }
-
- return result;
- }();
-
- if (clauseOps) {
- clauseOps->privateSyms.push_back(mlir::SymbolRefAttr::get(privatizerOp));
- clauseOps->privateVars.push_back(privVal);
- }
+ 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);
+ };
- if (symToPrivatize->HasLocalLocality())
- allPrivatizedSymbols.insert(symToPrivatize);
+ Fortran::lower::privatizeSymbol<mlir::omp::PrivateClauseOp,
+ mlir::omp::PrivateClauseOps>(
+ converter, firOpBuilder, symTable, initGen, allPrivatizedSymbols,
+ symToPrivatize, clauseOps);
}
-
-template void
-DataSharingProcessor::privatizeSymbol<mlir::omp::PrivateClauseOp,
- mlir::omp::PrivateClauseOps>(
- const semantics::Symbol *symToPrivatize,
- mlir::omp::PrivateClauseOps *clauseOps);
-
-template void
-DataSharingProcessor::privatizeSymbol<fir::LocalitySpecifierOp,
- fir::LocalitySpecifierOperands>(
- const semantics::Symbol *symToPrivatize,
- fir::LocalitySpecifierOperands *clauseOps);
-
} // namespace omp
} // namespace lower
} // namespace Fortran
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.h b/flang/lib/Lower/OpenMP/DataSharingProcessor.h
index ae759bfef566b..8a7dbb2ae30b7 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.h
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.h
@@ -153,10 +153,8 @@ class DataSharingProcessor {
: llvm::ArrayRef<const semantics::Symbol *>();
}
- template <typename OpType = mlir::omp::PrivateClauseOp,
- typename OperandsStructType = mlir::omp::PrivateClauseOps>
void privatizeSymbol(const semantics::Symbol *symToPrivatize,
- OperandsStructType *clauseOps);
+ mlir::omp::PrivateClauseOps *clauseOps);
};
} // namespace omp
diff --git a/flang/lib/Lower/Support/Utils.cpp b/flang/lib/Lower/Support/Utils.cpp
index 668ee31a36bc3..f93c4238665a5 100644
--- a/flang/lib/Lower/Support/Utils.cpp
+++ b/flang/lib/Lower/Support/Utils.cpp
@@ -633,4 +633,185 @@ bool isEqual(const Fortran::lower::ExplicitIterSpace::ArrayBases &x,
}},
x, y);
}
+
+void copyFirstPrivateSymbol(lower::AbstractConverter &converter,
+ const semantics::Symbol *sym,
+ mlir::OpBuilder::InsertPoint *copyAssignIP) {
+ if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate) ||
+ sym->test(semantics::Symbol::Flag::LocalityLocalInit))
+ converter.copyHostAssociateVar(*sym, copyAssignIP);
+}
+
+template <typename OpType, typename OperandsStructType>
+void privatizeSymbol(
+ lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder,
+ lower::SymMap &symTable,
+ std::function<void(OpType, mlir::Type)> initGen,
+ llvm::SetVector<const semantics::Symbol *> &allPrivatizedSymbols,
+ 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);
+ 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";
+ bool emitCopyRegion =
+ symToPrivatize->test(semantics::Symbol::Flag::OmpFirstPrivate) ||
+ symToPrivatize->test(semantics::Symbol::Flag::LocalityLocalInit);
+
+ mlir::Value privVal = hsb.getAddr();
+ mlir::Type allocType = privVal.getType();
+ if (!mlir::isa<fir::PointerType>(privVal.getType()))
+ allocType = fir::unwrapRefType(privVal.getType());
+
+ if (auto poly = mlir::dyn_cast<fir::ClassType>(allocType)) {
+ if (!mlir::isa<fir::PointerType>(poly.getEleTy()) && emitCopyRegion)
+ TODO(symLoc, "create polymorphic host associated copy");
+ }
+
+ // fir.array<> cannot be converted to any single llvm type and fir helpers
+ // are not available in openmp to llvmir translation so we cannot generate
+ // an alloca for a fir.array type there. Get around this by boxing all
+ // arrays.
+ if (mlir::isa<fir::SequenceType>(allocType)) {
+ entity = genVariableBox(symLoc, firOpBuilder, entity);
+ privVal = entity.getBase();
+ allocType = privVal.getType();
+ }
+
+ if (mlir::isa<fir::BaseBoxType>(privVal.getType())) {
+ // Boxes should be passed by reference into nested regions:
+ auto oldIP = firOpBuilder.saveInsertionPoint();
+ firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock());
+ auto alloca = firOpBuilder.create<fir::AllocaOp>(symLoc, privVal.getType());
+ firOpBuilder.restoreInsertionPoint(oldIP);
+ firOpBuilder.create<fir::StoreOp>(symLoc, privVal, alloca);
+ privVal = alloca;
+ }
+
+ mlir::Type argType = privVal.getType();
+
+ OpType privatizerOp = [&]() {
+ auto moduleOp = firOpBuilder.getModule();
+ auto uniquePrivatizerName = fir::getTypeAsString(
+ allocType, converter.getKindMap(),
+ converter.mangleName(*sym) +
+ (emitCopyRegion ? "_firstprivate" : "_private"));
+
+ if (auto existingPrivatizer =
+ moduleOp.lookupSymbol<OpType>(uniquePrivatizerName))
+ return existingPrivatizer;
+
+ mlir::OpBuilder::InsertionGuard guard(firOpBuilder);
+ firOpBuilder.setInsertionPointToStart(moduleOp.getBody());
+ OpType result;
+
+ if constexpr (std::is_same_v<OpType, mlir::omp::PrivateClauseOp>) {
+ result = firOpBuilder.create<OpType>(
+ symLoc, uniquePrivatizerName, allocType,
+ emitCopyRegion ? mlir::omp::DataSharingClauseType::FirstPrivate
+ : mlir::omp::DataSharingClauseType::Private);
+ } else {
+ result = firOpBuilder.create<OpType>(
+ symLoc, uniquePrivatizerName, allocType,
+ emitCopyRegion ? fir::LocalitySpecifierType::LocalInit
+ : fir::LocalitySpecifierType::Local);
+ }
+
+ fir::ExtendedValue symExV = converter.getSymbolExtendedValue(*sym);
+ lower::SymMapScope outerScope(symTable);
+
+ // Populate the `init` region.
+ // We need to initialize in the following cases:
+ // 1. The allocation was for a derived type which requires initialization
+ // (this can be skipped if it will be initialized anyway by the copy
+ // region, unless the derived type has allocatable components)
+ // 2. The allocation was for any kind of box
+ // 3. The allocation was for a boxed character
+ const bool needsInitialization =
+ (Fortran::lower::hasDefaultInitialization(sym->GetUltimate()) &&
+ (!emitCopyRegion || hlfir::mayHaveAllocatableComponent(allocType))) ||
+ mlir::isa<fir::BaseBoxType>(allocType) ||
+ mlir::isa<fir::BoxCharType>(allocType);
+ if (needsInitialization) {
+ initGen(result, argType);
+ }
+
+ // Populate the `copy` region if this is a `firstprivate`.
+ if (emitCopyRegion) {
+ mlir::Region ©Region = result.getCopyRegion();
+ // First block argument corresponding to the original/host value while
+ // second block argument corresponding to the privatized value.
+ mlir::Block *copyEntryBlock = firOpBuilder.createBlo...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
2524b27
to
cfee9fe
Compare
e0eb161
to
68494ba
Compare
Refactors the utils needed to create privtization/locatization ops for both the fir and OpenMP dialects into a shared location isolating OpenMP stuff out of it as much as possible.
cfee9fe
to
a69412f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/157/builds/29376 Here is the relevant piece of the build log for the reference
|
Hopefully, fixed in #141938 |
…141767) Refactors the utils needed to create privtization/locatization ops for both the fir and OpenMP dialects into a shared location isolating OpenMP stuff out of it as much as possible.
…lvm#141767) Refactors the utils needed to create privtization/locatization ops for both the fir and OpenMP dialects into a shared location isolating OpenMP stuff out of it as much as possible.
…lvm#141767) Refactors the utils needed to create privtization/locatization ops for both the fir and OpenMP dialects into a shared location isolating OpenMP stuff out of it as much as possible.
Refactors the utils needed to create privtization/locatization ops for both the fir and OpenMP dialects into a shared location isolating OpenMP stuff out of it as much as possible.