- Notifications
You must be signed in to change notification settings - Fork 15.3k
[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 all 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 semantics::Symbol *sym : privatizedSymbols) | ||
| for (const semantics::Symbol *sym : allPrivatizedSymbols) | ||
| if (semantics::IsAllocatable(sym->GetUltimate())) { | ||
| if (!useDelayedPrivatization) { | ||
| converter.createHostAssociateVarCloneDealloc(*sym); | ||
| | @@ -92,10 +93,6 @@ void DataSharingProcessor::insertDeallocs() { | |
| } | ||
| | ||
| void DataSharingProcessor::cloneSymbol(const semantics::Symbol *sym) { | ||
| // Privatization for symbols which are pre-determined (like loop index | ||
| // variables) happen separately, for everything else privatize here. | ||
| if (sym->test(semantics::Symbol::Flag::OmpPreDetermined)) | ||
| return; | ||
| bool success = converter.createHostAssociateVarClone(*sym); | ||
| (void)success; | ||
| assert(success && "Privatization failed due to existing binding"); | ||
| | @@ -126,20 +123,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"); | ||
| } | ||
| | @@ -149,7 +150,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 semantics::Symbol *sym : privatizedSymbols) { | ||
| for (const semantics::Symbol *sym : allPrivatizedSymbols) { | ||
| if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate) && | ||
| sym->test(semantics::Symbol::Flag::OmpLastPrivate)) | ||
| return true; | ||
| | @@ -283,10 +284,40 @@ void DataSharingProcessor::collectSymbolsInNestedRegions( | |
| if (nestedEval.isConstruct()) | ||
| // Recursively look for OpenMP constructs within `nestedEval`'s region | ||
| collectSymbolsInNestedRegions(nestedEval, flag, symbolsInNestedRegions); | ||
| else | ||
| converter.collectSymbolSet(nestedEval, symbolsInNestedRegions, flag, | ||
| /*collectSymbols=*/true, | ||
| /*collectHostAssociatedSymbols=*/false); | ||
| else { | ||
| bool isOrderedConstruct = [&]() { | ||
| Member Author 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 Contributor 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 ? Member Author 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 Contributor 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? Contributor 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. Member Author 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. Contributor 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: Member 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 Contributor 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<parser::OmpBeginBlockDirective>( | ||
| ompBlockConstruct->t); | ||
| const auto origDirective = | ||
| std::get<parser::OmpBlockDirective>(beginBlockDirective.t).v; | ||
| | ||
| return origDirective == llvm::omp::Directive::OMPD_ordered; | ||
| } | ||
| } | ||
| | ||
| return false; | ||
| }(); | ||
| | ||
| bool isCriticalConstruct = [&]() { | ||
| if (auto *ompConstruct = | ||
| nestedEval.getIf<parser::OpenMPConstruct>()) { | ||
| return std::get_if<parser::OpenMPCriticalConstruct>( | ||
| &ompConstruct->u) != nullptr; | ||
| } | ||
| return false; | ||
| }(); | ||
| | ||
| if (!isOrderedConstruct && !isCriticalConstruct) | ||
| converter.collectSymbolSet(nestedEval, symbolsInNestedRegions, flag, | ||
| /*collectSymbols=*/true, | ||
| /*collectHostAssociatedSymbols=*/false); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| | @@ -322,24 +353,39 @@ void DataSharingProcessor::collectSymbols( | |
| converter.collectSymbolSet(eval, allSymbols, flag, | ||
| /*collectSymbols=*/true, | ||
| /*collectHostAssociatedSymbols=*/true); | ||
| | ||
| llvm::SetVector<const semantics::Symbol *> symbolsInNestedRegions; | ||
| collectSymbolsInNestedRegions(eval, flag, symbolsInNestedRegions); | ||
| // Filter-out symbols that must not be privatized. | ||
| bool collectImplicit = flag == semantics::Symbol::Flag::OmpImplicit; | ||
| bool collectPreDetermined = flag == semantics::Symbol::Flag::OmpPreDetermined; | ||
| | ||
| auto isPrivatizable = [](const semantics::Symbol &sym) -> bool { | ||
| return !semantics::IsProcedure(sym) && | ||
| !sym.GetUltimate().has<semantics::DerivedTypeDetails>() && | ||
| !sym.GetUltimate().has<semantics::NamelistDetails>() && | ||
| !semantics::IsImpliedDoIndex(sym.GetUltimate()); | ||
| }; | ||
| | ||
| auto shouldCollectSymbol = [&](const semantics::Symbol *sym) { | ||
| if (collectImplicit) | ||
| return sym->test(semantics::Symbol::Flag::OmpImplicit); | ||
| | ||
| if (collectPreDetermined) | ||
| return sym->test(semantics::Symbol::Flag::OmpPreDetermined); | ||
| | ||
| return !sym->test(semantics::Symbol::Flag::OmpImplicit) && | ||
| !sym->test(semantics::Symbol::Flag::OmpPreDetermined); | ||
| }; | ||
| | ||
| for (const auto *sym : allSymbols) { | ||
| assert(curScope && "couldn't find current scope"); | ||
| if (isPrivatizable(*sym) && !symbolsInNestedRegions.contains(sym) && | ||
| !privatizedSymbols.contains(sym) && | ||
| !sym->test(semantics::Symbol::Flag::OmpPreDetermined) && | ||
| (collectImplicit || !sym->test(semantics::Symbol::Flag::OmpImplicit)) && | ||
| clauseScopes.contains(&sym->owner())) | ||
| !explicitlyPrivatizedSymbols.contains(sym) && | ||
| shouldCollectSymbol(sym) && clauseScopes.contains(&sym->owner())) { | ||
| allPrivatizedSymbols.insert(sym); | ||
| symbols.insert(sym); | ||
| } | ||
| } | ||
| } | ||
| | ||
| | @@ -363,10 +409,16 @@ void DataSharingProcessor::collectImplicitSymbols() { | |
| collectSymbols(semantics::Symbol::Flag::OmpImplicit, implicitSymbols); | ||
| } | ||
| | ||
| void DataSharingProcessor::collectPreDeterminedSymbols() { | ||
| if (shouldCollectPreDeterminedSymbols) | ||
| collectSymbols(semantics::Symbol::Flag::OmpPreDetermined, | ||
| preDeterminedSymbols); | ||
| } | ||
| | ||
| void DataSharingProcessor::privatize( | ||
| mlir::omp::PrivateClauseOps *clauseOps, | ||
| llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms) { | ||
| for (const semantics::Symbol *sym : privatizedSymbols) { | ||
| for (const semantics::Symbol *sym : allPrivatizedSymbols) { | ||
| if (const auto *commonDet = | ||
| sym->detailsIf<semantics::CommonBlockDetails>()) { | ||
| for (const auto &mem : commonDet->objects()) | ||
| | @@ -378,7 +430,7 @@ void DataSharingProcessor::privatize( | |
| | ||
| void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) { | ||
| insertLastPrivateCompare(op); | ||
| for (const semantics::Symbol *sym : privatizedSymbols) | ||
| for (const semantics::Symbol *sym : allPrivatizedSymbols) | ||
| if (const auto *commonDet = | ||
| sym->detailsIf<semantics::CommonBlockDetails>()) { | ||
| for (const auto &mem : commonDet->objects()) { | ||
| | @@ -389,20 +441,6 @@ void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) { | |
| } | ||
| } | ||
| | ||
| void DataSharingProcessor::defaultPrivatize( | ||
| mlir::omp::PrivateClauseOps *clauseOps, | ||
| llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms) { | ||
| for (const semantics::Symbol *sym : defaultSymbols) | ||
| doPrivatize(sym, clauseOps, privateSyms); | ||
| } | ||
| | ||
| void DataSharingProcessor::implicitPrivatize( | ||
| mlir::omp::PrivateClauseOps *clauseOps, | ||
| llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms) { | ||
| for (const semantics::Symbol *sym : implicitSymbols) | ||
| doPrivatize(sym, clauseOps, privateSyms); | ||
| } | ||
| | ||
| void DataSharingProcessor::doPrivatize( | ||
| const semantics::Symbol *sym, mlir::omp::PrivateClauseOps *clauseOps, | ||
| llvm::SmallVectorImpl<const semantics::Symbol *> *privateSyms) { | ||
| | ||
Uh oh!
There was an error while loading. Please reload this page.