[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))
----------------
tblah wrote:

This also needs to guard for something like
```
use module_containing_a_reduction, only: not_a_reduction
```

https://github.com/llvm/llvm-project/pull/207494


More information about the flang-commits mailing list