[flang-commits] [flang] [flang][OpenMP] Lower multi-type user-defined declare reduction (PR #207494)
Tom Eccles via flang-commits
flang-commits at lists.llvm.org
Mon Jul 13 03:55:15 PDT 2026
================
@@ -6078,3 +6129,105 @@ void Fortran::lower::materializeOpenMPDeclareMappers(
}
}
}
+
+// Walk scopes and materialize omp.declare_reduction ops for user-defined
+// operator reductions imported from modules. If scope is null, start from the
+// global scope. Mirrors materializeOpenMPDeclareMappers: gating on mod-file
+// module scopes restricts this to separate compilation (a same-file module's op
+// is emitted by the primary translation pass).
+void Fortran::lower::materializeOpenMPDeclareReductions(
+ Fortran::lower::AbstractConverter &converter,
+ semantics::SemanticsContext &semaCtx, const semantics::Scope *scope) {
+ const semantics::Scope &root = scope ? *scope : semaCtx.globalScope();
+
+ // Recurse into child scopes first (modules, submodules, etc.).
+ for (const semantics::Scope &child : root.children())
+ materializeOpenMPDeclareReductions(converter, semaCtx, &child);
+
+ // Only consider module scopes to avoid duplicating local constructs.
+ if (!root.IsModule())
+ return;
+
+ // Only materialize for modules coming from mod files to avoid duplicates.
+ if (!root.symbol() || !root.symbol()->test(semantics::Symbol::Flag::ModFile))
+ return;
+
+ // Scan symbols in this module scope for UserReductionDetails.
+ for (auto &it : root) {
+ const semantics::Symbol &sym = *it.second;
+ const semantics::Symbol &ultimate = sym.GetUltimate();
+ const auto *userDetails =
+ ultimate.detailsIf<semantics::UserReductionDetails>();
+ if (!userDetails)
+ continue;
+ // Skip without calling the impl: a consumer that merely uses this module
+ // must compile even when the reduction is out of the clause-side resolver's
+ // reach. Eagerly lowering a private-ultimate reduction would trip the
+ // impl's
+ // TODO and abort an unused import; a program that references it still gets
+ // the clause-side TODO. The impl's typeNameList loop materializes multiple
+ // declarations and types (one op per type); the per-declaration skips below
+ // guard the remaining unsupported shapes (combiner-in-clause and
+ // unsupported element types).
+ if (ultimate.attrs().test(semantics::Attr::PRIVATE))
+ continue;
+ for (const auto *decl : userDetails->GetDeclList()) {
+ if (const auto *reductionDecl =
+ std::get_if<parser::OmpDeclareReductionDirective>(&decl->u)) {
+ // An unused import must not abort the consumer, so skip a shape the
+ // impl cannot lower (a program that references it still gets the
+ // clause-side
+ // TODO), completing the mandatory skip above (which covers only
+ // private).
+ const auto &specifier =
+ DEREF(parser::omp::GetFirstArgument<parser::OmpReductionSpecifier>(
+ reductionDecl->v));
+ // The combiner-in-clause form (declare reduction(id:type)
+ // combiner(...), OpenMP 6.0) is not yet lowered even in the same-file
+ // path; computeReductionType and the impl both read the combiner from
+ // the specifier.
+ if (!std::get<std::optional<parser::OmpCombinerExpression>>(specifier.t)
+ .has_value())
+ continue;
+ // A reduction type lowering does not yet support: mirror the impl's
+ // getReductionType check with the shared predicate. A single
+ // declaration may list several types (Form A), each with its own
+ // combiner instance; the impl emits one op per type in a single call,
+ // so skip the whole declaration if any listed type is unsupported
+ // (materializing only a subset is not expressible through the impl's
+ // all-types loop).
+ const parser::OmpCombinerExpression &combinerExpr =
+ std::get<std::optional<parser::OmpCombinerExpression>>(specifier.t)
+ .value();
+ bool anyUnsupportedType = false;
+ for (const parser::OmpStylizedInstance &combinerInst : combinerExpr.v) {
+ if (!isSimpleReductionType(
+ computeReductionType(converter, combinerInst))) {
+ anyUnsupportedType = true;
----------------
tblah wrote:
Why not just generate the TODO? I'm worried that having this new interface that doesn't display the TODO is error-prone
https://github.com/llvm/llvm-project/pull/207494
More information about the flang-commits
mailing list