-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[flang][OpenMP] Try to unify induction var privatization for OMP regions. #91116
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
Changes from 20 commits
6ad9565
833b600
e29c7d4
1bf0e55
d74cb3e
fe35620
fd2d53f
81f4e77
cdb92c9
894a83e
dfade68
0d24b41
001c0fe
82d8ea0
b513a79
919309e
27ebcea
6985a27
f77c47f
696cde8
05c013f
2e067c4
3abb935
1023e05
0fe21cf
eb20e54
b4612b3
9c909d0
cbdb1e5
799c616
25b8b9d
33114ee
dcc1558
9bb2215
3e5c63c
6f1bcee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,9 +29,10 @@ void DataSharingProcessor::processStep1( | |
collectSymbolsForPrivatization(); | ||
collectDefaultSymbols(); | ||
collectImplicitSymbols(); | ||
collectPreDeterminedSymbols(); | ||
|
||
privatize(clauseOps, privateSyms); | ||
defaultPrivatize(clauseOps, privateSyms); | ||
implicitPrivatize(clauseOps, privateSyms); | ||
|
||
insertBarrier(); | ||
} | ||
|
||
|
@@ -57,7 +58,7 @@ void DataSharingProcessor::processStep2(mlir::Operation *op, bool isLoop) { | |
} | ||
|
||
void DataSharingProcessor::insertDeallocs() { | ||
for (const Fortran::semantics::Symbol *sym : privatizedSymbols) | ||
for (const Fortran::semantics::Symbol *sym : allPrivatizedSymbols) | ||
if (Fortran::semantics::IsAllocatable(sym->GetUltimate())) { | ||
if (!useDelayedPrivatization) { | ||
converter.createHostAssociateVarCloneDealloc(*sym); | ||
|
@@ -92,10 +93,6 @@ void DataSharingProcessor::insertDeallocs() { | |
} | ||
|
||
void DataSharingProcessor::cloneSymbol(const Fortran::semantics::Symbol *sym) { | ||
// Privatization for symbols which are pre-determined (like loop index | ||
// variables) happen separately, for everything else privatize here. | ||
if (sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined)) | ||
return; | ||
bool success = converter.createHostAssociateVarClone(*sym); | ||
(void)success; | ||
assert(success && "Privatization failed due to existing binding"); | ||
|
@@ -127,20 +124,24 @@ void DataSharingProcessor::collectSymbolsForPrivatization() { | |
for (const omp::Clause &clause : clauses) { | ||
if (const auto &privateClause = | ||
std::get_if<omp::clause::Private>(&clause.u)) { | ||
collectOmpObjectListSymbol(privateClause->v, privatizedSymbols); | ||
collectOmpObjectListSymbol(privateClause->v, explicitlyPrivatizedSymbols); | ||
} else if (const auto &firstPrivateClause = | ||
std::get_if<omp::clause::Firstprivate>(&clause.u)) { | ||
collectOmpObjectListSymbol(firstPrivateClause->v, privatizedSymbols); | ||
collectOmpObjectListSymbol(firstPrivateClause->v, | ||
explicitlyPrivatizedSymbols); | ||
} else if (const auto &lastPrivateClause = | ||
std::get_if<omp::clause::Lastprivate>(&clause.u)) { | ||
const ObjectList &objects = std::get<ObjectList>(lastPrivateClause->t); | ||
collectOmpObjectListSymbol(objects, privatizedSymbols); | ||
collectOmpObjectListSymbol(objects, explicitlyPrivatizedSymbols); | ||
hasLastPrivateOp = true; | ||
} else if (std::get_if<omp::clause::Collapse>(&clause.u)) { | ||
hasCollapse = true; | ||
} | ||
} | ||
|
||
for (auto *sym : explicitlyPrivatizedSymbols) | ||
allPrivatizedSymbols.insert(sym); | ||
|
||
if (hasCollapse && hasLastPrivateOp) | ||
TODO(converter.getCurrentLocation(), "Collapse clause with lastprivate"); | ||
} | ||
|
@@ -150,7 +151,7 @@ bool DataSharingProcessor::needBarrier() { | |
// initialization of firstprivate variables and post-update of lastprivate | ||
// variables. | ||
// Emit implicit barrier for linear clause. Maybe on somewhere else. | ||
for (const Fortran::semantics::Symbol *sym : privatizedSymbols) { | ||
for (const Fortran::semantics::Symbol *sym : allPrivatizedSymbols) { | ||
if (sym->test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate) && | ||
sym->test(Fortran::semantics::Symbol::Flag::OmpLastPrivate)) | ||
return true; | ||
|
@@ -289,12 +290,34 @@ void DataSharingProcessor::collectSymbolsInNestedRegions( | |
eval.getNestedEvaluations()) { | ||
if (nestedEval.hasNestedEvaluations()) { | ||
if (nestedEval.isConstruct()) | ||
// Recursively look for OpenMP constructs within `nestedEval`'s region | ||
ergawy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
collectSymbolsInNestedRegions(nestedEval, flag, symbolsInNestedRegions); | ||
else | ||
converter.collectSymbolSet(nestedEval, symbolsInNestedRegions, flag, | ||
/*collectSymbols=*/true, | ||
/*collectHostAssociatedSymbols=*/false); | ||
else { | ||
bool isOrderedConstruct = [&]() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kiranchandramohan @luporl just to clarify this change: The changes here make sure that for the following input, !$omp do ordered
do i = 2, 10
!$omp ordered
a(i) = a(i-1) + 1
!$omp end ordered
end do
!$omp end do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not clear to me why the ordered construct is a special case. Will the same issue be resolved by a fix similar to #90671 ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can describe the problem in more detail but cannot claim my solution is the proper one. For the above example program, this is the output of
So, However, when you call This in turn, causes Since, That said, I am not sure this is the proper location for that kind of fix. But a similar fix to what was introduced in #90671 does not seem to work. Tried adding that in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can fix this separately. Could you check whether the same issue happens with the Critical construct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks both for the review.
That indeed causes the same issue. I will add a similar "fix" and a test before merging. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a small question. I am not able to map how control-flow is coming to
I get semantic error as: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this error happens earlier in semantics because There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! Indeed it is from semantics. I was mainly checking if default privatization logic is being invoked uncharacteristically when it should not (i.e. when I'm looking into this |
||
if (auto *ompConstruct = | ||
nestedEval.getIf<parser::OpenMPConstruct>()) { | ||
if (auto *ompBlockConstruct = | ||
std::get_if<parser::OpenMPBlockConstruct>( | ||
&ompConstruct->u)) { | ||
const auto &beginBlockDirective = | ||
std::get<Fortran::parser::OmpBeginBlockDirective>( | ||
ompBlockConstruct->t); | ||
const auto origDirective = | ||
std::get<Fortran::parser::OmpBlockDirective>( | ||
beginBlockDirective.t) | ||
.v; | ||
|
||
return origDirective == llvm::omp::Directive::OMPD_ordered; | ||
} | ||
} | ||
|
||
return false; | ||
}(); | ||
|
||
if (!isOrderedConstruct) | ||
converter.collectSymbolSet(nestedEval, symbolsInNestedRegions, flag, | ||
/*collectSymbols=*/true, | ||
/*collectHostAssociatedSymbols=*/false); | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -330,25 +353,46 @@ void DataSharingProcessor::collectSymbols( | |
converter.collectSymbolSet(eval, allSymbols, flag, | ||
/*collectSymbols=*/true, | ||
/*collectHostAssociatedSymbols=*/true); | ||
|
||
llvm::SetVector<const Fortran::semantics::Symbol *> symbolsInNestedRegions; | ||
collectSymbolsInNestedRegions(eval, flag, symbolsInNestedRegions); | ||
// Filter-out symbols that must not be privatized. | ||
bool collectImplicit = flag == Fortran::semantics::Symbol::Flag::OmpImplicit; | ||
bool collectPreDetermined = | ||
flag == Fortran::semantics::Symbol::Flag::OmpPreDetermined; | ||
|
||
auto isPrivatizable = [](const Fortran::semantics::Symbol &sym) -> bool { | ||
return !Fortran::semantics::IsProcedure(sym) && | ||
!sym.GetUltimate().has<Fortran::semantics::DerivedTypeDetails>() && | ||
!sym.GetUltimate().has<Fortran::semantics::NamelistDetails>() && | ||
!Fortran::semantics::IsImpliedDoIndex(sym.GetUltimate()); | ||
}; | ||
|
||
auto shouldCollectSymbol = [&](const Fortran::semantics::Symbol *sym) { | ||
if (collectImplicit && | ||
sym->test(Fortran::semantics::Symbol::Flag::OmpImplicit) && | ||
!sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined)) | ||
return true; | ||
|
||
if (collectPreDetermined && | ||
sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined)) | ||
return true; | ||
|
||
if (!sym->test(Fortran::semantics::Symbol::Flag::OmpImplicit) && | ||
!sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined)) | ||
return true; | ||
|
||
return false; | ||
ergawy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}; | ||
|
||
for (const auto *sym : allSymbols) { | ||
assert(curScope && "couldn't find current scope"); | ||
if (isPrivatizable(*sym) && !symbolsInNestedRegions.contains(sym) && | ||
!privatizedSymbols.contains(sym) && | ||
!sym->test(Fortran::semantics::Symbol::Flag::OmpPreDetermined) && | ||
ergawy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(collectImplicit || | ||
!sym->test(Fortran::semantics::Symbol::Flag::OmpImplicit)) && | ||
clauseScopes.contains(&sym->owner())) | ||
!explicitlyPrivatizedSymbols.contains(sym) && | ||
shouldCollectSymbol(sym) && clauseScopes.contains(&sym->owner())) { | ||
allPrivatizedSymbols.insert(sym); | ||
symbols.insert(sym); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -365,6 +409,9 @@ void DataSharingProcessor::collectDefaultSymbols() { | |
defaultSymbols); | ||
} | ||
} | ||
|
||
for (auto *sym : defaultSymbols) | ||
allPrivatizedSymbols.insert(sym); | ||
ergawy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
void DataSharingProcessor::collectImplicitSymbols() { | ||
|
@@ -374,10 +421,15 @@ void DataSharingProcessor::collectImplicitSymbols() { | |
implicitSymbols); | ||
} | ||
|
||
void DataSharingProcessor::collectPreDeterminedSymbols() { | ||
collectSymbols(Fortran::semantics::Symbol::Flag::OmpPreDetermined, | ||
preDeterminedSymbols); | ||
} | ||
|
||
void DataSharingProcessor::privatize( | ||
mlir::omp::PrivateClauseOps *clauseOps, | ||
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) { | ||
for (const Fortran::semantics::Symbol *sym : privatizedSymbols) { | ||
for (const Fortran::semantics::Symbol *sym : allPrivatizedSymbols) { | ||
if (const auto *commonDet = | ||
sym->detailsIf<Fortran::semantics::CommonBlockDetails>()) { | ||
for (const auto &mem : commonDet->objects()) | ||
|
@@ -389,7 +441,7 @@ void DataSharingProcessor::privatize( | |
|
||
void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) { | ||
insertLastPrivateCompare(op); | ||
for (const Fortran::semantics::Symbol *sym : privatizedSymbols) | ||
for (const Fortran::semantics::Symbol *sym : allPrivatizedSymbols) | ||
if (const auto *commonDet = | ||
sym->detailsIf<Fortran::semantics::CommonBlockDetails>()) { | ||
for (const auto &mem : commonDet->objects()) { | ||
|
@@ -400,20 +452,6 @@ void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) { | |
} | ||
} | ||
|
||
void DataSharingProcessor::defaultPrivatize( | ||
mlir::omp::PrivateClauseOps *clauseOps, | ||
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) { | ||
for (const Fortran::semantics::Symbol *sym : defaultSymbols) | ||
doPrivatize(sym, clauseOps, privateSyms); | ||
} | ||
|
||
void DataSharingProcessor::implicitPrivatize( | ||
mlir::omp::PrivateClauseOps *clauseOps, | ||
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) { | ||
for (const Fortran::semantics::Symbol *sym : implicitSymbols) | ||
doPrivatize(sym, clauseOps, privateSyms); | ||
} | ||
|
||
void DataSharingProcessor::doPrivatize( | ||
const Fortran::semantics::Symbol *sym, | ||
mlir::omp::PrivateClauseOps *clauseOps, | ||
|
Uh oh!
There was an error while loading. Please reload this page.