Skip to content

[flang][OpenMP]Support for subroutine call for DECLARE REDUCTION init #127889

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

Merged
merged 2 commits into from
Mar 3, 2025

Conversation

Leporacanthicus
Copy link
Contributor

The DECLARE REDUCTION allows the initialization part to be either an expression or a call to a subroutine.

This modifies the parsing and semantic analysis to allow the use of the subroutine, in addition to the simple expression that was already supported.

New tests in parser and semantics sections check that the generated structure is as expected.

DECLARE REDUCTION lowering is not yet implemented, so will end in a TODO. A new test with an init subroutine is added, that checks that this variant also ends with a "Not yet implemented" message.

@llvmbot
Copy link
Member

llvmbot commented Feb 19, 2025

@llvm/pr-subscribers-flang-parser

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

Author: Mats Petersson (Leporacanthicus)

Changes

The DECLARE REDUCTION allows the initialization part to be either an expression or a call to a subroutine.

This modifies the parsing and semantic analysis to allow the use of the subroutine, in addition to the simple expression that was already supported.

New tests in parser and semantics sections check that the generated structure is as expected.

DECLARE REDUCTION lowering is not yet implemented, so will end in a TODO. A new test with an init subroutine is added, that checks that this variant also ends with a "Not yet implemented" message.


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

8 Files Affected:

  • (modified) flang/include/flang/Parser/dump-parse-tree.h (+2)
  • (modified) flang/include/flang/Parser/parse-tree.h (+10-1)
  • (modified) flang/lib/Parser/openmp-parsers.cpp (+9-1)
  • (modified) flang/lib/Parser/unparse.cpp (+12-2)
  • (modified) flang/lib/Semantics/resolve-names.cpp (+14-3)
  • (added) flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90 (+28)
  • (modified) flang/test/Parser/OpenMP/declare-reduction-unparse.f90 (+44-4)
  • (modified) flang/test/Semantics/OpenMP/declare-reduction.f90 (+26)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 21ee1d0517840..5b11a26439927 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -631,6 +631,8 @@ class ParseTreeDumper {
   NODE(parser, OmpReductionCombiner)
   NODE(parser, OmpTaskReductionClause)
   NODE(OmpTaskReductionClause, Modifier)
+  NODE(parser, OmpReductionInitializerProc)
+  NODE(parser, OmpReductionInitializerExpr)
   NODE(parser, OmpReductionInitializerClause)
   NODE(parser, OmpReductionIdentifier)
   NODE(parser, OmpAllocateClause)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 6ba43f6688c25..5505c2fd1ed8a 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4548,7 +4548,16 @@ struct OpenMPDeclareMapperConstruct {
 
 // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
 //                                              : combiner) [initializer-clause]
-WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
+struct OmpReductionInitializerProc {
+  TUPLE_CLASS_BOILERPLATE(OmpReductionInitializerProc);
+  std::tuple<ProcedureDesignator, std::list<ActualArgSpec>> t;
+};
+WRAPPER_CLASS(OmpReductionInitializerExpr, Expr);
+
+struct OmpReductionInitializerClause {
+  UNION_CLASS_BOILERPLATE(OmpReductionInitializerClause);
+  std::variant<OmpReductionInitializerProc, OmpReductionInitializerExpr> u;
+};
 
 struct OpenMPDeclareReductionConstruct {
   TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index b39b8737b70c0..81b730e96b3c4 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1142,8 +1142,16 @@ TYPE_PARSER(construct<OmpBlockDirective>(first(
 TYPE_PARSER(sourced(construct<OmpBeginBlockDirective>(
     sourced(Parser<OmpBlockDirective>{}), Parser<OmpClauseList>{})))
 
+TYPE_PARSER(construct<OmpReductionInitializerExpr>("OMP_PRIV =" >> expr))
+TYPE_PARSER(
+    construct<OmpReductionInitializerProc>(Parser<ProcedureDesignator>{},
+        parenthesized(many(maybe(","_tok) >> Parser<ActualArgSpec>{}))))
+
 TYPE_PARSER(construct<OmpReductionInitializerClause>(
-    "INITIALIZER" >> parenthesized("OMP_PRIV =" >> expr)))
+    "INITIALIZER" >> parenthesized(construct<OmpReductionInitializerClause>(
+                                       Parser<OmpReductionInitializerExpr>{}) ||
+                         construct<OmpReductionInitializerClause>(
+                             Parser<OmpReductionInitializerProc>{}))))
 
 // 2.16 Declare Reduction Construct
 TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 3d00979d7b7a6..c9e65d2258b52 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2681,9 +2681,19 @@ class UnparseVisitor {
   void Unparse(const OmpDeclareTargetWithList &x) {
     Put("("), Walk(x.v), Put(")");
   }
-  void Unparse(const OmpReductionInitializerClause &x) {
-    Word(" INITIALIZER(OMP_PRIV = ");
+  void Unparse(const OmpReductionInitializerProc &x) {
+    Walk(std::get<ProcedureDesignator>(x.t));
+    Put("(");
+    Walk(std::get<std::list<ActualArgSpec>>(x.t));
+    Put(")");
+  }
+  void Unparse(const OmpReductionInitializerExpr &x) {
+    Word("OMP_PRIV = ");
     Walk(x.v);
+  }
+  void Unparse(const OmpReductionInitializerClause &x) {
+    Word(" INITIALIZER(");
+    Walk(x.u);
     Put(")");
   }
   void Unparse(const OpenMPDeclareReductionConstruct &x) {
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index ff793658f1e06..1edf770e0fc5f 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1482,13 +1482,26 @@ class OmpVisitor : public virtual DeclarationVisitor {
     return false;
   }
 
+  bool Pre(const parser::OmpReductionInitializerProc &x) {
+    auto &procDes = std::get<parser::ProcedureDesignator>(x.t);
+    auto &name = std::get<parser::Name>(procDes.u);
+    auto *symbol{FindSymbol(NonDerivedTypeScope(), name)};
+    if (!symbol) {
+      symbol = &MakeSymbol(context().globalScope(), name.source, Attrs{});
+      Resolve(name, *symbol);
+    }
+    return true;
+  }
+
   bool Pre(const parser::OpenMPDeclareReductionConstruct &x) {
     AddOmpSourceRange(x.source);
     parser::OmpClauseList emptyList{std::list<parser::OmpClause>{}};
     ProcessReductionSpecifier(
         std::get<Indirection<parser::OmpReductionSpecifier>>(x.t).value(),
         emptyList);
-    Walk(std::get<std::optional<parser::OmpReductionInitializerClause>>(x.t));
+    auto &init =
+        std::get<std::optional<parser::OmpReductionInitializerClause>>(x.t);
+    Walk(init);
     return false;
   }
   bool Pre(const parser::OmpMapClause &);
@@ -1741,7 +1754,6 @@ void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
 void OmpVisitor::ProcessReductionSpecifier(
     const parser::OmpReductionSpecifier &spec,
     const parser::OmpClauseList &clauses) {
-  BeginDeclTypeSpec();
   const auto &id{std::get<parser::OmpReductionIdentifier>(spec.t)};
   if (auto procDes{std::get_if<parser::ProcedureDesignator>(&id.u)}) {
     if (auto *name{std::get_if<parser::Name>(&procDes->u)}) {
@@ -1749,7 +1761,6 @@ void OmpVisitor::ProcessReductionSpecifier(
           &MakeSymbol(*name, MiscDetails{MiscDetails::Kind::ConstructName});
     }
   }
-  EndDeclTypeSpec();
   // Creating a new scope in case the combiner expression (or clauses) use
   // reerved identifiers, like "omp_in". This is a temporary solution until
   // we deal with these in a more thorough way.
diff --git a/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90 b/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90
new file mode 100644
index 0000000000000..30630465490b2
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90
@@ -0,0 +1,28 @@
+! This test checks lowering of OpenMP declare reduction Directive, with initialization
+! via a subroutine. This functionality is currently not implemented.
+
+! RUN: not flang -fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s
+
+!CHECK: not yet implemented: OpenMPDeclareReductionConstruct
+subroutine initme(x,n)
+  integer x,n
+  x=n
+end subroutine initme
+
+function func(x, n, init)
+  integer func
+  integer x(n)
+  integer res
+  interface
+     subroutine initme(x,n)
+       integer x,n
+     end subroutine initme
+  end interface
+!$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,0))
+  res=init
+!$omp simd reduction(red_add:res)
+  do i=1,n
+     res=res+x(i)
+  enddo
+  func=res
+end function func
diff --git a/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 b/flang/test/Parser/OpenMP/declare-reduction-unparse.f90
index a2a3ef9f630ab..e7b15fb3e9d2c 100644
--- a/flang/test/Parser/OpenMP/declare-reduction-unparse.f90
+++ b/flang/test/Parser/OpenMP/declare-reduction-unparse.f90
@@ -1,11 +1,51 @@
 ! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
 ! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+!CHECK-LABEL: SUBROUTINE initme (x, n)
+subroutine initme(x,n)
+  integer x,n
+  x=n
+end subroutine initme
+!CHECK: END SUBROUTINE initme
+
+!CHECK: FUNCTION func(x, n, init)
+function func(x, n, init)
+  integer func
+  integer x(n)
+  integer res
+  interface
+     subroutine initme(x,n)
+       integer x,n
+     end subroutine initme
+  end interface
+!CHECK: !$OMP DECLARE REDUCTION (red_add:INTEGER(KIND=4_4): omp_out=omp_out+omp_in
+!CHECK: ) INITIALIZER(initme(omp_priv, 0_4))  
+!$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,0))
+!PARSE-TREE:  DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct
+!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out=omp_out+omp_in'
+!PARSE-TREE:    OmpReductionInitializerClause -> OmpReductionInitializerProc
+!PARSE-TREE-NEXT: ProcedureDesignator -> Name = 'initme'
+  res=init
+!$omp simd reduction(red_add:res)
+!CHECK: !$OMP SIMD REDUCTION(red_add: res)
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
+!PARSE-TREE:  OmpBeginLoopDirective
+!PARSE-TREE:  OmpLoopDirective -> llvm::omp::Directive = simd
+!PARSE-TREE:  OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
+!PARSE-TREE:  Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'red_add
+  do i=1,n
+     res=res+x(i)
+  enddo
+  func=res
+end function func
+!CHECK: END FUNCTION func
+
 !CHECK-LABEL: program main
 program main
   integer :: my_var
-  !CHECK: !$OMP DECLARE REDUCTION (my_add_red:INTEGER: omp_out=omp_out+omp_in
-  !CHECK-NEXT: ) INITIALIZER(OMP_PRIV = 0_4)
-  
+!CHECK: !$OMP DECLARE REDUCTION (my_add_red:INTEGER: omp_out=omp_out+omp_in
+!CHECK-NEXT: ) INITIALIZER(OMP_PRIV = 0_4)
+
   !$omp declare reduction (my_add_red : integer : omp_out = omp_out + omp_in) initializer (omp_priv=0)
   my_var = 0
   !$omp parallel reduction (my_add_red : my_var) num_threads(4)
@@ -18,4 +58,4 @@ end program main
 !PARSE-TREE:        OmpReductionIdentifier -> ProcedureDesignator -> Name = 'my_add_red'
 !PARSE-TREE:        DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec
 !PARSE-TREE:        OmpReductionCombiner -> AssignmentStmt = 'omp_out=omp_out+omp_in'
-!PARSE-TREE:        OmpReductionInitializerClause -> Expr = '0_4'
+!PARSE-TREE:        OmpReductionInitializerClause -> OmpReductionInitializerExpr -> Expr = '0_4'
diff --git a/flang/test/Semantics/OpenMP/declare-reduction.f90 b/flang/test/Semantics/OpenMP/declare-reduction.f90
index 8fee79dfc0b7b..e61af0430575f 100644
--- a/flang/test/Semantics/OpenMP/declare-reduction.f90
+++ b/flang/test/Semantics/OpenMP/declare-reduction.f90
@@ -1,5 +1,31 @@
 ! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=50 %s | FileCheck %s
 
+!CHECK-LABEL: Subprogram scope: initme
+subroutine initme(x,n)
+  integer x,n
+  x=n
+end subroutine initme
+
+!CHECK-LABEL: Subprogram scope: func
+function func(x, n, init)
+  integer func
+  integer x(n)
+  integer res
+  interface
+     subroutine initme(x,n)
+       integer x,n
+     end subroutine initme
+  end interface
+  !$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,0))
+!CHECK: red_add: Misc ConstructName
+!CHECK: Subprogram scope: initme  
+!$omp simd reduction(red_add:res)
+  do i=1,n
+     res=res+x(i)
+  enddo
+  func=res
+end function func
+
 program main
 !CHECK-LABEL: MainProgram scope: main
 

@llvmbot
Copy link
Member

llvmbot commented Feb 19, 2025

@llvm/pr-subscribers-flang-openmp

Author: Mats Petersson (Leporacanthicus)

Changes

The DECLARE REDUCTION allows the initialization part to be either an expression or a call to a subroutine.

This modifies the parsing and semantic analysis to allow the use of the subroutine, in addition to the simple expression that was already supported.

New tests in parser and semantics sections check that the generated structure is as expected.

DECLARE REDUCTION lowering is not yet implemented, so will end in a TODO. A new test with an init subroutine is added, that checks that this variant also ends with a "Not yet implemented" message.


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

8 Files Affected:

  • (modified) flang/include/flang/Parser/dump-parse-tree.h (+2)
  • (modified) flang/include/flang/Parser/parse-tree.h (+10-1)
  • (modified) flang/lib/Parser/openmp-parsers.cpp (+9-1)
  • (modified) flang/lib/Parser/unparse.cpp (+12-2)
  • (modified) flang/lib/Semantics/resolve-names.cpp (+14-3)
  • (added) flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90 (+28)
  • (modified) flang/test/Parser/OpenMP/declare-reduction-unparse.f90 (+44-4)
  • (modified) flang/test/Semantics/OpenMP/declare-reduction.f90 (+26)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 21ee1d0517840..5b11a26439927 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -631,6 +631,8 @@ class ParseTreeDumper {
   NODE(parser, OmpReductionCombiner)
   NODE(parser, OmpTaskReductionClause)
   NODE(OmpTaskReductionClause, Modifier)
+  NODE(parser, OmpReductionInitializerProc)
+  NODE(parser, OmpReductionInitializerExpr)
   NODE(parser, OmpReductionInitializerClause)
   NODE(parser, OmpReductionIdentifier)
   NODE(parser, OmpAllocateClause)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 6ba43f6688c25..5505c2fd1ed8a 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4548,7 +4548,16 @@ struct OpenMPDeclareMapperConstruct {
 
 // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
 //                                              : combiner) [initializer-clause]
-WRAPPER_CLASS(OmpReductionInitializerClause, Expr);
+struct OmpReductionInitializerProc {
+  TUPLE_CLASS_BOILERPLATE(OmpReductionInitializerProc);
+  std::tuple<ProcedureDesignator, std::list<ActualArgSpec>> t;
+};
+WRAPPER_CLASS(OmpReductionInitializerExpr, Expr);
+
+struct OmpReductionInitializerClause {
+  UNION_CLASS_BOILERPLATE(OmpReductionInitializerClause);
+  std::variant<OmpReductionInitializerProc, OmpReductionInitializerExpr> u;
+};
 
 struct OpenMPDeclareReductionConstruct {
   TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index b39b8737b70c0..81b730e96b3c4 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1142,8 +1142,16 @@ TYPE_PARSER(construct<OmpBlockDirective>(first(
 TYPE_PARSER(sourced(construct<OmpBeginBlockDirective>(
     sourced(Parser<OmpBlockDirective>{}), Parser<OmpClauseList>{})))
 
+TYPE_PARSER(construct<OmpReductionInitializerExpr>("OMP_PRIV =" >> expr))
+TYPE_PARSER(
+    construct<OmpReductionInitializerProc>(Parser<ProcedureDesignator>{},
+        parenthesized(many(maybe(","_tok) >> Parser<ActualArgSpec>{}))))
+
 TYPE_PARSER(construct<OmpReductionInitializerClause>(
-    "INITIALIZER" >> parenthesized("OMP_PRIV =" >> expr)))
+    "INITIALIZER" >> parenthesized(construct<OmpReductionInitializerClause>(
+                                       Parser<OmpReductionInitializerExpr>{}) ||
+                         construct<OmpReductionInitializerClause>(
+                             Parser<OmpReductionInitializerProc>{}))))
 
 // 2.16 Declare Reduction Construct
 TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 3d00979d7b7a6..c9e65d2258b52 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2681,9 +2681,19 @@ class UnparseVisitor {
   void Unparse(const OmpDeclareTargetWithList &x) {
     Put("("), Walk(x.v), Put(")");
   }
-  void Unparse(const OmpReductionInitializerClause &x) {
-    Word(" INITIALIZER(OMP_PRIV = ");
+  void Unparse(const OmpReductionInitializerProc &x) {
+    Walk(std::get<ProcedureDesignator>(x.t));
+    Put("(");
+    Walk(std::get<std::list<ActualArgSpec>>(x.t));
+    Put(")");
+  }
+  void Unparse(const OmpReductionInitializerExpr &x) {
+    Word("OMP_PRIV = ");
     Walk(x.v);
+  }
+  void Unparse(const OmpReductionInitializerClause &x) {
+    Word(" INITIALIZER(");
+    Walk(x.u);
     Put(")");
   }
   void Unparse(const OpenMPDeclareReductionConstruct &x) {
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index ff793658f1e06..1edf770e0fc5f 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1482,13 +1482,26 @@ class OmpVisitor : public virtual DeclarationVisitor {
     return false;
   }
 
+  bool Pre(const parser::OmpReductionInitializerProc &x) {
+    auto &procDes = std::get<parser::ProcedureDesignator>(x.t);
+    auto &name = std::get<parser::Name>(procDes.u);
+    auto *symbol{FindSymbol(NonDerivedTypeScope(), name)};
+    if (!symbol) {
+      symbol = &MakeSymbol(context().globalScope(), name.source, Attrs{});
+      Resolve(name, *symbol);
+    }
+    return true;
+  }
+
   bool Pre(const parser::OpenMPDeclareReductionConstruct &x) {
     AddOmpSourceRange(x.source);
     parser::OmpClauseList emptyList{std::list<parser::OmpClause>{}};
     ProcessReductionSpecifier(
         std::get<Indirection<parser::OmpReductionSpecifier>>(x.t).value(),
         emptyList);
-    Walk(std::get<std::optional<parser::OmpReductionInitializerClause>>(x.t));
+    auto &init =
+        std::get<std::optional<parser::OmpReductionInitializerClause>>(x.t);
+    Walk(init);
     return false;
   }
   bool Pre(const parser::OmpMapClause &);
@@ -1741,7 +1754,6 @@ void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
 void OmpVisitor::ProcessReductionSpecifier(
     const parser::OmpReductionSpecifier &spec,
     const parser::OmpClauseList &clauses) {
-  BeginDeclTypeSpec();
   const auto &id{std::get<parser::OmpReductionIdentifier>(spec.t)};
   if (auto procDes{std::get_if<parser::ProcedureDesignator>(&id.u)}) {
     if (auto *name{std::get_if<parser::Name>(&procDes->u)}) {
@@ -1749,7 +1761,6 @@ void OmpVisitor::ProcessReductionSpecifier(
           &MakeSymbol(*name, MiscDetails{MiscDetails::Kind::ConstructName});
     }
   }
-  EndDeclTypeSpec();
   // Creating a new scope in case the combiner expression (or clauses) use
   // reerved identifiers, like "omp_in". This is a temporary solution until
   // we deal with these in a more thorough way.
diff --git a/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90 b/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90
new file mode 100644
index 0000000000000..30630465490b2
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/omp-declare-reduction-initsub.f90
@@ -0,0 +1,28 @@
+! This test checks lowering of OpenMP declare reduction Directive, with initialization
+! via a subroutine. This functionality is currently not implemented.
+
+! RUN: not flang -fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s
+
+!CHECK: not yet implemented: OpenMPDeclareReductionConstruct
+subroutine initme(x,n)
+  integer x,n
+  x=n
+end subroutine initme
+
+function func(x, n, init)
+  integer func
+  integer x(n)
+  integer res
+  interface
+     subroutine initme(x,n)
+       integer x,n
+     end subroutine initme
+  end interface
+!$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,0))
+  res=init
+!$omp simd reduction(red_add:res)
+  do i=1,n
+     res=res+x(i)
+  enddo
+  func=res
+end function func
diff --git a/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 b/flang/test/Parser/OpenMP/declare-reduction-unparse.f90
index a2a3ef9f630ab..e7b15fb3e9d2c 100644
--- a/flang/test/Parser/OpenMP/declare-reduction-unparse.f90
+++ b/flang/test/Parser/OpenMP/declare-reduction-unparse.f90
@@ -1,11 +1,51 @@
 ! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s
 ! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+!CHECK-LABEL: SUBROUTINE initme (x, n)
+subroutine initme(x,n)
+  integer x,n
+  x=n
+end subroutine initme
+!CHECK: END SUBROUTINE initme
+
+!CHECK: FUNCTION func(x, n, init)
+function func(x, n, init)
+  integer func
+  integer x(n)
+  integer res
+  interface
+     subroutine initme(x,n)
+       integer x,n
+     end subroutine initme
+  end interface
+!CHECK: !$OMP DECLARE REDUCTION (red_add:INTEGER(KIND=4_4): omp_out=omp_out+omp_in
+!CHECK: ) INITIALIZER(initme(omp_priv, 0_4))  
+!$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,0))
+!PARSE-TREE:  DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct
+!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out=omp_out+omp_in'
+!PARSE-TREE:    OmpReductionInitializerClause -> OmpReductionInitializerProc
+!PARSE-TREE-NEXT: ProcedureDesignator -> Name = 'initme'
+  res=init
+!$omp simd reduction(red_add:res)
+!CHECK: !$OMP SIMD REDUCTION(red_add: res)
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
+!PARSE-TREE:  OmpBeginLoopDirective
+!PARSE-TREE:  OmpLoopDirective -> llvm::omp::Directive = simd
+!PARSE-TREE:  OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
+!PARSE-TREE:  Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'red_add
+  do i=1,n
+     res=res+x(i)
+  enddo
+  func=res
+end function func
+!CHECK: END FUNCTION func
+
 !CHECK-LABEL: program main
 program main
   integer :: my_var
-  !CHECK: !$OMP DECLARE REDUCTION (my_add_red:INTEGER: omp_out=omp_out+omp_in
-  !CHECK-NEXT: ) INITIALIZER(OMP_PRIV = 0_4)
-  
+!CHECK: !$OMP DECLARE REDUCTION (my_add_red:INTEGER: omp_out=omp_out+omp_in
+!CHECK-NEXT: ) INITIALIZER(OMP_PRIV = 0_4)
+
   !$omp declare reduction (my_add_red : integer : omp_out = omp_out + omp_in) initializer (omp_priv=0)
   my_var = 0
   !$omp parallel reduction (my_add_red : my_var) num_threads(4)
@@ -18,4 +58,4 @@ end program main
 !PARSE-TREE:        OmpReductionIdentifier -> ProcedureDesignator -> Name = 'my_add_red'
 !PARSE-TREE:        DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec
 !PARSE-TREE:        OmpReductionCombiner -> AssignmentStmt = 'omp_out=omp_out+omp_in'
-!PARSE-TREE:        OmpReductionInitializerClause -> Expr = '0_4'
+!PARSE-TREE:        OmpReductionInitializerClause -> OmpReductionInitializerExpr -> Expr = '0_4'
diff --git a/flang/test/Semantics/OpenMP/declare-reduction.f90 b/flang/test/Semantics/OpenMP/declare-reduction.f90
index 8fee79dfc0b7b..e61af0430575f 100644
--- a/flang/test/Semantics/OpenMP/declare-reduction.f90
+++ b/flang/test/Semantics/OpenMP/declare-reduction.f90
@@ -1,5 +1,31 @@
 ! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=50 %s | FileCheck %s
 
+!CHECK-LABEL: Subprogram scope: initme
+subroutine initme(x,n)
+  integer x,n
+  x=n
+end subroutine initme
+
+!CHECK-LABEL: Subprogram scope: func
+function func(x, n, init)
+  integer func
+  integer x(n)
+  integer res
+  interface
+     subroutine initme(x,n)
+       integer x,n
+     end subroutine initme
+  end interface
+  !$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,0))
+!CHECK: red_add: Misc ConstructName
+!CHECK: Subprogram scope: initme  
+!$omp simd reduction(red_add:res)
+  do i=1,n
+     res=res+x(i)
+  enddo
+  func=res
+end function func
+
 program main
 !CHECK-LABEL: MainProgram scope: main
 

Copy link
Contributor

@kiranchandramohan kiranchandramohan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG.

Comment on lines 1489 to 1493
if (!symbol) {
symbol = &MakeSymbol(context().globalScope(), name.source, Attrs{});
Resolve(name, *symbol);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a test for this if condition? Should it be an error if the Subroutine is not found?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should be an error. I've added a test, and an error message to say that the subroutine must not be implicitly declared.

integer x,n
end subroutine initme
end interface
!$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,0))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this patch. But I assume we would want to create symbols for omp_priv, omp_out, omp_in in their respective scopes to identify them due to their special meanings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in progress.

The DECLARE REDUCTION allows the initialization part to be either
an expression or a call to a subroutine.

This modifies the parsing and semantic analysis to allow the
use of the subroutine, in addition to the simple expression that
was already supported.

New tests in parser and semantics sections check that the generated
structure is as expected.

DECLARE REDUCTION lowering is not yet implemented, so will end
in a TODO. A new test with an init subroutine is added, that checks
that this variant also ends with a "Not yet implemented" message.
@Leporacanthicus Leporacanthicus merged commit 5030105 into llvm:main Mar 3, 2025
11 checks passed
jph-13 pushed a commit to jph-13/llvm-project that referenced this pull request Mar 21, 2025
…llvm#127889)

The DECLARE REDUCTION allows the initialization part to be either an
expression or a call to a subroutine.

This modifies the parsing and semantic analysis to allow the use of the
subroutine, in addition to the simple expression that was already
supported.

New tests in parser and semantics sections check that the generated
structure is as expected.

DECLARE REDUCTION lowering is not yet implemented, so will end in a
TODO. A new test with an init subroutine is added, that checks that this
variant also ends with a "Not yet implemented" message.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants