[flang] [llvm] [flang][OpenMP] Use StylizedInstance in converted clauses (PR #171907)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 11 13:17:07 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Krzysztof Parzyszek (kparzysz)

<details>
<summary>Changes</summary>

Invent `StylizedInstance` class to store special variables together with the instantiated expression in omp::clause::Initializer. This will eliminate the need for visiting the original AST nodes in lowering to MLIR.

---
Full diff: https://github.com/llvm/llvm-project/pull/171907.diff


8 Files Affected:

- (modified) flang/include/flang/Lower/OpenMP/Clauses.h (+3) 
- (modified) flang/include/flang/Semantics/openmp-utils.h (+2) 
- (modified) flang/lib/Lower/OpenMP/ClauseProcessor.cpp (+16-16) 
- (modified) flang/lib/Lower/OpenMP/ClauseProcessor.h (+2-2) 
- (modified) flang/lib/Lower/OpenMP/Clauses.cpp (+28-19) 
- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+1-3) 
- (modified) flang/lib/Semantics/openmp-utils.cpp (+20) 
- (modified) llvm/include/llvm/Frontend/OpenMP/ClauseT.h (+9-2) 


``````````diff
diff --git a/flang/include/flang/Lower/OpenMP/Clauses.h b/flang/include/flang/Lower/OpenMP/Clauses.h
index 737b535d604d6..455eda2738e6d 100644
--- a/flang/include/flang/Lower/OpenMP/Clauses.h
+++ b/flang/include/flang/Lower/OpenMP/Clauses.h
@@ -113,6 +113,8 @@ Object makeObject(const parser::Designator &dsg,
                   semantics::SemanticsContext &semaCtx);
 Object makeObject(const parser::StructureComponent &comp,
                   semantics::SemanticsContext &semaCtx);
+Object makeObject(const parser::EntityDecl &decl,
+                  semantics::SemanticsContext &semaCtx);
 
 inline auto makeObjectFn(semantics::SemanticsContext &semaCtx) {
   return [&](auto &&s) { return makeObject(s, semaCtx); };
@@ -172,6 +174,7 @@ std::optional<Object> getBaseObject(const Object &object,
                                     semantics::SemanticsContext &semaCtx);
 
 namespace clause {
+using StylizedInstance = tomp::type::StylizedInstanceT<IdTy, ExprTy>;
 using Range = tomp::type::RangeT<ExprTy>;
 using Mapper = tomp::type::MapperT<IdTy, ExprTy>;
 using Iterator = tomp::type::IteratorT<TypeTy, IdTy, ExprTy>;
diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index f5739ab16d643..639f7224ddf6b 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -97,6 +97,8 @@ const SomeExpr *HasStorageOverlap(
     const SomeExpr &base, llvm::ArrayRef<SomeExpr> exprs);
 bool IsAssignment(const parser::ActionStmt *x);
 bool IsPointerAssignment(const evaluate::Assignment &x);
+
+MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp);
 } // namespace omp
 } // namespace Fortran::semantics
 
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 451b53e71b31b..3c31b3a07f57f 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -383,36 +383,36 @@ bool ClauseProcessor::processInclusive(
 }
 
 bool ClauseProcessor::processInitializer(
-    lower::SymMap &symMap, const parser::OmpClause::Initializer &inp,
+    lower::SymMap &symMap,
     ReductionProcessor::GenInitValueCBTy &genInitValueCB) const {
   if (auto *clause = findUniqueClause<omp::clause::Initializer>()) {
     genInitValueCB = [&, clause](fir::FirOpBuilder &builder, mlir::Location loc,
                                  mlir::Type type, mlir::Value ompOrig) {
       lower::SymMapScope scope(symMap);
-      const parser::OmpInitializerExpression &iexpr = inp.v.v;
-      const parser::OmpStylizedInstance &styleInstance = iexpr.v.front();
-      const std::list<parser::OmpStylizedDeclaration> &declList =
-          std::get<std::list<parser::OmpStylizedDeclaration>>(styleInstance.t);
       mlir::Value ompPrivVar;
-      for (const parser::OmpStylizedDeclaration &decl : declList) {
-        auto &name = std::get<parser::ObjectName>(decl.var.t);
-        assert(name.symbol && "Name does not have a symbol");
+      const clause::StylizedInstance &inst = clause->v.front();
+
+      for (const Object &object :
+           std::get<clause::StylizedInstance::Variables>(inst.t)) {
         mlir::Value addr = builder.createTemporary(loc, ompOrig.getType());
         fir::StoreOp::create(builder, loc, ompOrig, addr);
         fir::FortranVariableFlagsEnum extraFlags = {};
         fir::FortranVariableFlagsAttr attributes =
-            Fortran::lower::translateSymbolAttributes(builder.getContext(),
-                                                      *name.symbol, extraFlags);
-        auto declareOp = hlfir::DeclareOp::create(
-            builder, loc, addr, name.ToString(), nullptr, {}, nullptr, nullptr,
-            0, attributes);
-        if (name.ToString() == "omp_priv")
+            Fortran::lower::translateSymbolAttributes(
+                builder.getContext(), *object.sym(), extraFlags);
+        std::string name = object.sym()->name().ToString();
+        auto declareOp =
+            hlfir::DeclareOp::create(builder, loc, addr, name, nullptr, {},
+                                     nullptr, nullptr, 0, attributes);
+        if (name == "omp_priv")
           ompPrivVar = declareOp.getResult(0);
-        symMap.addVariableDefinition(*name.symbol, declareOp);
+        symMap.addVariableDefinition(*object.sym(), declareOp);
       }
+
       // Lower the expression/function call
       lower::StatementContext stmtCtx;
-      const semantics::SomeExpr &initExpr = clause->v.front();
+      const semantics::SomeExpr &initExpr =
+          std::get<clause::StylizedInstance::Instance>(inst.t);
       mlir::Value result = common::visit(
           common::visitors{
               [&](const evaluate::ProcedureRef &procRef) -> mlir::Value {
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h
index 3485a4ed1581f..a04cd4b79dd24 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.h
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h
@@ -20,7 +20,7 @@
 #include "flang/Lower/OpenMP/Clauses.h"
 #include "flang/Lower/Support/ReductionProcessor.h"
 #include "flang/Optimizer/Builder/Todo.h"
-#include "flang/Parser/parse-tree.h"
+#include "flang/Parser/char-block.h"
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
 
 namespace fir {
@@ -89,7 +89,7 @@ class ClauseProcessor {
   bool processInclusive(mlir::Location currentLocation,
                         mlir::omp::InclusiveClauseOps &result) const;
   bool processInitializer(
-      lower::SymMap &symMap, const parser::OmpClause::Initializer &inp,
+      lower::SymMap &symMap,
       ReductionProcessor::GenInitValueCBTy &genInitValueCB) const;
   bool processMergeable(mlir::omp::MergeableClauseOps &result) const;
   bool processNogroup(mlir::omp::NogroupClauseOps &result) const;
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 11f558e6cc8ca..9ea4e8fcd6c0e 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -13,6 +13,7 @@
 #include "flang/Parser/parse-tree.h"
 #include "flang/Semantics/expression.h"
 #include "flang/Semantics/openmp-modifiers.h"
+#include "flang/Semantics/openmp-utils.h"
 #include "flang/Semantics/symbol.h"
 
 #include <list>
@@ -128,6 +129,11 @@ Object makeObject(const parser::OmpObject &object,
   return makeObject(std::get<parser::Designator>(object.u), semaCtx);
 }
 
+Object makeObject(const parser::EntityDecl &decl,
+                  semantics::SemanticsContext &semaCtx) {
+  return makeObject(std::get<parser::ObjectName>(decl.t), semaCtx);
+}
+
 ObjectList makeObjects(const parser::OmpArgumentList &objects,
                        semantics::SemanticsContext &semaCtx) {
   return makeList(objects.v, [&](const parser::OmpArgument &arg) {
@@ -275,12 +281,10 @@ makeIteratorSpecifiers(const parser::OmpIteratorSpecifier &inp,
   auto &tds = std::get<parser::TypeDeclarationStmt>(inp.t);
   auto &entities = std::get<std::list<parser::EntityDecl>>(tds.t);
   for (const parser::EntityDecl &ed : entities) {
-    auto &name = std::get<parser::ObjectName>(ed.t);
-    assert(name.symbol && "Expecting symbol for iterator variable");
-    auto *stype = name.symbol->GetType();
-    assert(stype && "Expecting symbol type");
-    IteratorSpecifier spec{{evaluate::DynamicType::From(*stype),
-                            makeObject(name, semaCtx), range}};
+    auto *symbol = std::get<parser::ObjectName>(ed.t).symbol;
+    auto *type = DEREF(symbol).GetType();
+    IteratorSpecifier spec{{evaluate::DynamicType::From(DEREF(type)),
+                            makeObject(ed, semaCtx), range}};
     specifiers.emplace_back(std::move(spec));
   }
 
@@ -983,19 +987,24 @@ Initializer make(const parser::OmpClause::Initializer &inp,
                  semantics::SemanticsContext &semaCtx) {
   const parser::OmpInitializerExpression &iexpr = inp.v.v;
   Initializer initializer;
-  for (const parser::OmpStylizedInstance &styleInstance : iexpr.v) {
-    auto &instance =
-        std::get<parser::OmpStylizedInstance::Instance>(styleInstance.t);
-    if (const auto *as = std::get_if<parser::AssignmentStmt>(&instance.u)) {
-      auto &expr = std::get<parser::Expr>(as->t);
-      initializer.v.push_back(makeExpr(expr, semaCtx));
-    } else if (const auto *call = std::get_if<parser::CallStmt>(&instance.u)) {
-      assert(call->typedCall && "Expecting typedCall");
-      const auto &procRef = *call->typedCall;
-      initializer.v.push_back(semantics::SomeExpr(procRef));
-    } else {
-      llvm_unreachable("Unexpected initializer");
-    }
+
+  for (const parser::OmpStylizedInstance &sinst : iexpr.v) {
+    ObjectList variables;
+    llvm::transform(
+        std::get<std::list<parser::OmpStylizedDeclaration>>(sinst.t),
+        std::back_inserter(variables),
+        [&](const parser::OmpStylizedDeclaration &s) {
+          return makeObject(s.var, semaCtx);
+        });
+
+    SomeExpr instance = [&]() {
+      if (auto &&expr = semantics::omp::MakeEvaluateExpr(sinst))
+        return std::move(*expr);
+      llvm_unreachable("Expecting expression instance");
+    }();
+
+    initializer.v.push_back(
+        StylizedInstance{{std::move(variables), std::move(instance)}});
   }
 
   return initializer;
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 582e684442dfc..38ab42076f559 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -3764,9 +3764,7 @@ static void genOMP(
     List<Clause> clauses = makeClauses(initializer, semaCtx);
     ReductionProcessor::GenInitValueCBTy genInitValueCB;
     ClauseProcessor cp(converter, semaCtx, clauses);
-    const parser::OmpClause::Initializer &iclause{
-        std::get<parser::OmpClause::Initializer>(initializer.v.front().u)};
-    cp.processInitializer(symTable, iclause, genInitValueCB);
+    cp.processInitializer(symTable, genInitValueCB);
     const auto &identifier =
         std::get<parser::OmpReductionIdentifier>(specifier.t);
     const auto &designator =
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 18a37d64a3b5a..a3912f31b4452 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -496,4 +496,24 @@ bool IsPointerAssignment(const evaluate::Assignment &x) {
   return std::holds_alternative<evaluate::Assignment::BoundsSpec>(x.u) ||
       std::holds_alternative<evaluate::Assignment::BoundsRemapping>(x.u);
 }
+
+MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp) {
+  auto &instance = std::get<parser::OmpStylizedInstance::Instance>(inp.t);
+
+  return common::visit( //
+      common::visitors{
+          [&](const parser::AssignmentStmt &s) -> MaybeExpr {
+            return GetEvaluateExpr(std::get<parser::Expr>(s.t));
+          },
+          [&](const parser::CallStmt &s) -> MaybeExpr {
+            assert(s.typedCall && "Expecting typedCall");
+            const auto &procRef = *s.typedCall;
+            return SomeExpr(procRef);
+          },
+          [&](const common::Indirection<parser::Expr> &s) -> MaybeExpr {
+            return GetEvaluateExpr(s.value());
+          },
+      },
+      instance.u);
+}
 } // namespace Fortran::semantics::omp
diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
index cf401711173e7..0a0323559eb27 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
@@ -189,6 +189,14 @@ template <typename I, typename E> using ObjectListT = ListT<ObjectT<I, E>>;
 
 using DirectiveName = llvm::omp::Directive;
 
+template <typename I, typename E> //
+struct StylizedInstanceT {
+  using Variables = ObjectListT<I, E>;
+  using Instance = E;
+  using TupleTrait = std::true_type;
+  std::tuple<Variables, Instance> t;
+};
+
 template <typename I, typename E> //
 struct DefinedOperatorT {
   struct DefinedOpName {
@@ -762,8 +770,7 @@ struct InitT {
 // V5.2: [5.5.4] `initializer` clause
 template <typename T, typename I, typename E> //
 struct InitializerT {
-  using InitializerExpr = E;
-  using List = ListT<InitializerExpr>;
+  using List = ListT<type::StylizedInstanceT<I, E>>;
   using WrapperTrait = std::true_type;
   List v;
 };

``````````

</details>


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


More information about the llvm-commits mailing list