From a5beafebf9c79c9a9e7471821c722025bebf789f Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Tue, 4 Nov 2025 14:52:25 -0600 Subject: [PATCH] [OpenMP] Sort clause-specific application functions, NFC It makes it easier to navigate through this file. The impact should be minimal since it's rarely modified. --- .../Frontend/OpenMP/ConstructDecompositionT.h | 363 +++++++++--------- 1 file changed, 185 insertions(+), 178 deletions(-) diff --git a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h index 6d6eb5cda52de..d702273cec9ec 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ConstructDecompositionT.h @@ -207,40 +207,40 @@ struct ConstructDecompositionT { template bool applyClause(Clause &&clause, const ClauseTy *node); + bool applyClause(const tomp::clause::AllocateT &clause, + const ClauseTy *); bool applyClause(const tomp::clause::CollapseT &clause, const ClauseTy *); - bool applyClause(const tomp::clause::PrivateT &clause, + bool applyClause(const tomp::clause::DefaultT &clause, const ClauseTy *); bool applyClause(const tomp::clause::FirstprivateT &clause, const ClauseTy *); + bool applyClause(const tomp::clause::IfT &clause, + const ClauseTy *); bool applyClause(const tomp::clause::LastprivateT &clause, const ClauseTy *); - bool applyClause(const tomp::clause::SharedT &clause, + bool applyClause(const tomp::clause::LinearT &clause, const ClauseTy *); - bool applyClause(const tomp::clause::DefaultT &clause, + bool applyClause(const tomp::clause::NowaitT &clause, const ClauseTy *); bool - applyClause(const tomp::clause::ThreadLimitT &clause, + applyClause(const tomp::clause::OmpxAttributeT &clause, const ClauseTy *); + bool applyClause(const tomp::clause::OmpxBareT &clause, + const ClauseTy *); bool applyClause(const tomp::clause::OrderT &clause, const ClauseTy *); - bool applyClause(const tomp::clause::AllocateT &clause, + bool applyClause(const tomp::clause::PrivateT &clause, const ClauseTy *); bool applyClause(const tomp::clause::ReductionT &clause, const ClauseTy *); - bool applyClause(const tomp::clause::IfT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::LinearT &clause, - const ClauseTy *); - bool applyClause(const tomp::clause::NowaitT &clause, + bool applyClause(const tomp::clause::SharedT &clause, const ClauseTy *); bool - applyClause(const tomp::clause::OmpxAttributeT &clause, + applyClause(const tomp::clause::ThreadLimitT &clause, const ClauseTy *); - bool applyClause(const tomp::clause::OmpxBareT &clause, - const ClauseTy *); uint32_t version; llvm::omp::Directive construct; @@ -458,6 +458,34 @@ bool ConstructDecompositionT::applyClause(Specific &&specific, return false; } +// --- Specific clauses ----------------------------------------------- + +// ALLOCATE +// [5.2:178:7-9] +// Directives: allocators, distribute, do, for, parallel, scope, sections, +// single, target, task, taskgroup, taskloop, teams +// +// [5.2:340:33-35] +// (33) The effect of the allocate clause is as if it is applied to all leaf +// constructs that permit the clause and to which a data-sharing attribute +// clause that may create a private copy of the same list item is applied. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::AllocateT &clause, + const ClauseTy *node) { + // This one needs to be applied at the end, once we know which clauses are + // assigned to which leaf constructs. + + // [5.2:340:33] + bool applied = applyIf(node, [&](const auto &leaf) { + return llvm::any_of(leaf.clauses, [&](const ClauseTy *n) { + return llvm::omp::isPrivatizingClause(n->id); + }); + }); + + return applied; +} + // COLLAPSE // [5.2:93:20-21] // Directives: distribute, do, for, loop, simd, taskloop @@ -483,19 +511,19 @@ bool ConstructDecompositionT::applyClause( return false; } -// PRIVATE -// [5.2:111:5-7] -// Directives: distribute, do, for, loop, parallel, scope, sections, simd, -// single, target, task, taskloop, teams +// DEFAULT +// [5.2:109:5-6] +// Directives: parallel, task, taskloop, teams // -// [5.2:340:1-2] -// (1) The effect of the 1 private clause is as if it is applied only to the -// innermost leaf construct that permits it. +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. template bool ConstructDecompositionT::applyClause( - const tomp::clause::PrivateT &clause, + const tomp::clause::DefaultT &clause, const ClauseTy *node) { - return applyToInnermost(node); + // [5.2:340:31] + return applyToAll(node); } // FIRSTPRIVATE @@ -626,6 +654,44 @@ bool ConstructDecompositionT::applyClause( return applied; } +// IF +// [5.2:72:7-9] +// Directives: cancel, parallel, simd, target, target data, target enter data, +// target exit data, target update, task, taskloop +// +// [5.2:72:15-18] +// (15) For combined or composite constructs, the if clause only applies to the +// semantics of the construct named in the directive-name-modifier. +// (16) For a combined or composite construct, if no directive-name-modifier is +// specified then the if clause applies to all constituent constructs to which +// an if clause can apply. +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::IfT &clause, + const ClauseTy *node) { + using DirectiveNameModifier = + typename clause::IfT::DirectiveNameModifier; + using IfExpression = typename clause::IfT::IfExpression; + auto &modifier = std::get>(clause.t); + + if (modifier) { + llvm::omp::Directive dirId = *modifier; + auto *unmodified = + makeClause(llvm::omp::Clause::OMPC_if, + tomp::clause::IfT{ + {/*DirectiveNameModifier=*/std::nullopt, + /*IfExpression=*/std::get(clause.t)}}); + + if (auto *hasDir = findDirective(dirId)) { + hasDir->clauses.push_back(unmodified); + return true; + } + return false; + } + + return applyToAll(node); +} + // LASTPRIVATE // [5.2:115:7-8] // Directives: distribute, do, for, loop, sections, simd, taskloop @@ -720,51 +786,94 @@ bool ConstructDecompositionT::applyClause( return applied; } -// SHARED -// [5.2:110:5-6] -// Directives: parallel, task, taskloop, teams +// LINEAR +// [5.2:118:1-2] +// Directives: declare simd, do, for, simd // -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. +// [5.2:341:15-22] +// (15.1) The effect of the linear clause is as if it is applied to the +// innermost leaf construct. +// (15.2) Additionally, if the list item is not the iteration variable of a simd +// or worksharing-loop SIMD construct, the effect on the outer leaf constructs +// is as if the list item was specified in firstprivate and lastprivate clauses +// on the combined or composite construct, with the rules specified above +// applied. +// (19) If a list item of the linear clause is the iteration variable of a simd +// or worksharing-loop SIMD construct and it is not declared in the construct, +// the effect on the outer leaf constructs is as if the list item was specified +// in a lastprivate clause on the combined or composite construct with the rules +// specified above applied. template bool ConstructDecompositionT::applyClause( - const tomp::clause::SharedT &clause, + const tomp::clause::LinearT &clause, const ClauseTy *node) { - // [5.2:340:31] - return applyToAll(node); + // [5.2:341:15.1] + if (!applyToInnermost(node)) + return false; + + // [5.2:341:15.2], [5.2:341:19] + auto dirSimd = findDirective(llvm::omp::Directive::OMPD_simd); + std::optional iterVar = helper.getLoopIterVar(); + const auto &objects = std::get>(clause.t); + + // Lists of objects that will be used to construct "firstprivate" and + // "lastprivate" clauses. + tomp::ObjectListT first, last; + + for (const ObjectTy &object : objects) { + last.push_back(object); + if (!dirSimd || !iterVar || object.id() != iterVar->id()) + first.push_back(object); + } + + if (!first.empty()) { + auto *firstp = makeClause( + llvm::omp::Clause::OMPC_firstprivate, + tomp::clause::FirstprivateT{/*List=*/first}); + nodes.push_back(firstp); // Appending to the main clause list. + } + if (!last.empty()) { + auto *lastp = + makeClause(llvm::omp::Clause::OMPC_lastprivate, + tomp::clause::LastprivateT{ + {/*LastprivateModifier=*/std::nullopt, /*List=*/last}}); + nodes.push_back(lastp); // Appending to the main clause list. + } + return true; } -// DEFAULT -// [5.2:109:5-6] -// Directives: parallel, task, taskloop, teams +// NOWAIT +// [5.2:308:11-13] +// Directives: dispatch, do, for, interop, scope, sections, single, target, +// target enter data, target exit data, target update, taskwait, workshare // -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. +// [5.2:341:23] +// (23) The effect of the nowait clause is as if it is applied to the outermost +// leaf construct that permits it. template bool ConstructDecompositionT::applyClause( - const tomp::clause::DefaultT &clause, + const tomp::clause::NowaitT &clause, const ClauseTy *node) { - // [5.2:340:31] - return applyToAll(node); + return applyToOutermost(node); } -// THREAD_LIMIT -// [5.2:277:14-15] -// Directives: target, teams -// -// [5.2:340:31-32] -// (31) The effect of the shared, default, thread_limit, or order clause is as -// if it is applied to all leaf constructs that permit the clause. +// OMPX_ATTRIBUTE template bool ConstructDecompositionT::applyClause( - const tomp::clause::ThreadLimitT &clause, + const tomp::clause::OmpxAttributeT &clause, const ClauseTy *node) { - // [5.2:340:31] + // ERROR: no leaf that allows clause return applyToAll(node); } +// OMPX_BARE +template +bool ConstructDecompositionT::applyClause( + const tomp::clause::OmpxBareT &clause, + const ClauseTy *node) { + return applyToOutermost(node); +} + // ORDER // [5.2:234:3-4] // Directives: distribute, do, for, loop, simd @@ -780,30 +889,19 @@ bool ConstructDecompositionT::applyClause( return applyToAll(node); } -// ALLOCATE -// [5.2:178:7-9] -// Directives: allocators, distribute, do, for, parallel, scope, sections, -// single, target, task, taskgroup, taskloop, teams +// PRIVATE +// [5.2:111:5-7] +// Directives: distribute, do, for, loop, parallel, scope, sections, simd, +// single, target, task, taskloop, teams // -// [5.2:340:33-35] -// (33) The effect of the allocate clause is as if it is applied to all leaf -// constructs that permit the clause and to which a data-sharing attribute -// clause that may create a private copy of the same list item is applied. +// [5.2:340:1-2] +// (1) The effect of the 1 private clause is as if it is applied only to the +// innermost leaf construct that permits it. template bool ConstructDecompositionT::applyClause( - const tomp::clause::AllocateT &clause, + const tomp::clause::PrivateT &clause, const ClauseTy *node) { - // This one needs to be applied at the end, once we know which clauses are - // assigned to which leaf constructs. - - // [5.2:340:33] - bool applied = applyIf(node, [&](const auto &leaf) { - return llvm::any_of(leaf.clauses, [&](const ClauseTy *n) { - return llvm::omp::isPrivatizingClause(n->id); - }); - }); - - return applied; + return applyToInnermost(node); } // REDUCTION @@ -983,129 +1081,38 @@ bool ConstructDecompositionT::applyClause( return applied; } -// IF -// [5.2:72:7-9] -// Directives: cancel, parallel, simd, target, target data, target enter data, -// target exit data, target update, task, taskloop +// SHARED +// [5.2:110:5-6] +// Directives: parallel, task, taskloop, teams // -// [5.2:72:15-18] -// (15) For combined or composite constructs, the if clause only applies to the -// semantics of the construct named in the directive-name-modifier. -// (16) For a combined or composite construct, if no directive-name-modifier is -// specified then the if clause applies to all constituent constructs to which -// an if clause can apply. +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. template bool ConstructDecompositionT::applyClause( - const tomp::clause::IfT &clause, + const tomp::clause::SharedT &clause, const ClauseTy *node) { - using DirectiveNameModifier = - typename clause::IfT::DirectiveNameModifier; - using IfExpression = typename clause::IfT::IfExpression; - auto &modifier = std::get>(clause.t); - - if (modifier) { - llvm::omp::Directive dirId = *modifier; - auto *unmodified = - makeClause(llvm::omp::Clause::OMPC_if, - tomp::clause::IfT{ - {/*DirectiveNameModifier=*/std::nullopt, - /*IfExpression=*/std::get(clause.t)}}); - - if (auto *hasDir = findDirective(dirId)) { - hasDir->clauses.push_back(unmodified); - return true; - } - return false; - } - + // [5.2:340:31] return applyToAll(node); } -// LINEAR -// [5.2:118:1-2] -// Directives: declare simd, do, for, simd -// -// [5.2:341:15-22] -// (15.1) The effect of the linear clause is as if it is applied to the -// innermost leaf construct. -// (15.2) Additionally, if the list item is not the iteration variable of a simd -// or worksharing-loop SIMD construct, the effect on the outer leaf constructs -// is as if the list item was specified in firstprivate and lastprivate clauses -// on the combined or composite construct, with the rules specified above -// applied. -// (19) If a list item of the linear clause is the iteration variable of a simd -// or worksharing-loop SIMD construct and it is not declared in the construct, -// the effect on the outer leaf constructs is as if the list item was specified -// in a lastprivate clause on the combined or composite construct with the rules -// specified above applied. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::LinearT &clause, - const ClauseTy *node) { - // [5.2:341:15.1] - if (!applyToInnermost(node)) - return false; - - // [5.2:341:15.2], [5.2:341:19] - auto dirSimd = findDirective(llvm::omp::Directive::OMPD_simd); - std::optional iterVar = helper.getLoopIterVar(); - const auto &objects = std::get>(clause.t); - - // Lists of objects that will be used to construct "firstprivate" and - // "lastprivate" clauses. - tomp::ObjectListT first, last; - - for (const ObjectTy &object : objects) { - last.push_back(object); - if (!dirSimd || !iterVar || object.id() != iterVar->id()) - first.push_back(object); - } - - if (!first.empty()) { - auto *firstp = makeClause( - llvm::omp::Clause::OMPC_firstprivate, - tomp::clause::FirstprivateT{/*List=*/first}); - nodes.push_back(firstp); // Appending to the main clause list. - } - if (!last.empty()) { - auto *lastp = - makeClause(llvm::omp::Clause::OMPC_lastprivate, - tomp::clause::LastprivateT{ - {/*LastprivateModifier=*/std::nullopt, /*List=*/last}}); - nodes.push_back(lastp); // Appending to the main clause list. - } - return true; -} - -// NOWAIT -// [5.2:308:11-13] -// Directives: dispatch, do, for, interop, scope, sections, single, target, -// target enter data, target exit data, target update, taskwait, workshare +// THREAD_LIMIT +// [5.2:277:14-15] +// Directives: target, teams // -// [5.2:341:23] -// (23) The effect of the nowait clause is as if it is applied to the outermost -// leaf construct that permits it. -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::NowaitT &clause, - const ClauseTy *node) { - return applyToOutermost(node); -} - -template -bool ConstructDecompositionT::applyClause( - const tomp::clause::OmpxBareT &clause, - const ClauseTy *node) { - return applyToOutermost(node); -} - +// [5.2:340:31-32] +// (31) The effect of the shared, default, thread_limit, or order clause is as +// if it is applied to all leaf constructs that permit the clause. template bool ConstructDecompositionT::applyClause( - const tomp::clause::OmpxAttributeT &clause, + const tomp::clause::ThreadLimitT &clause, const ClauseTy *node) { + // [5.2:340:31] return applyToAll(node); } +// --- Splitting ------------------------------------------------------ + template bool ConstructDecompositionT::split() { bool success = true;