[llvm] cb355de - [Flang][OpenMP] Add Parsing support for Indirect Clause (#143505)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 17 01:05:41 PDT 2025
Author: Jack Styles
Date: 2025-06-17T09:05:36+01:00
New Revision: cb355def9561e2d1d4b363f44dcedf5522f0f8a1
URL: https://github.com/llvm/llvm-project/commit/cb355def9561e2d1d4b363f44dcedf5522f0f8a1
DIFF: https://github.com/llvm/llvm-project/commit/cb355def9561e2d1d4b363f44dcedf5522f0f8a1.diff
LOG: [Flang][OpenMP] Add Parsing support for Indirect Clause (#143505)
As part of OpenMP Version 5.1, support for the `indirect` clause was
added for the `declare target` directive. This clause should follow an
`enter` clause, and allows procedure calls to be done indirectly through
OpenMP.
This adds Parsing support for the clause, along with semantics checks.
Currently, lowering for the clause is not supported so a TODO message
will be outputted to the user. It also performs version checking as
`indirect` is only support in OpenMP 5.1 or greater.
See also: #110008
Added:
flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90
flang/test/Parser/OpenMP/declare-target-indirect-tree.f90
flang/test/Semantics/indirect01.f90
flang/test/Semantics/indirect02.f90
Modified:
flang/include/flang/Parser/dump-parse-tree.h
flang/include/flang/Parser/parse-tree.h
flang/lib/Lower/OpenMP/Clauses.cpp
flang/lib/Parser/openmp-parsers.cpp
flang/lib/Semantics/check-omp-structure.cpp
llvm/include/llvm/Frontend/OpenMP/ClauseT.h
llvm/include/llvm/Frontend/OpenMP/OMP.td
Removed:
################################################################################
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index c6a5150a85a4c..e3eed6aed8079 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -565,6 +565,7 @@ class ParseTreeDumper {
NODE_ENUM(OmpDependenceType, Value)
NODE(parser, OmpTaskDependenceType)
NODE_ENUM(OmpTaskDependenceType, Value)
+ NODE(parser, OmpIndirectClause)
NODE(parser, OmpIterationOffset)
NODE(parser, OmpIteration)
NODE(parser, OmpIterationVector)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 67405f88e09f2..61f97b855b0e5 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4300,6 +4300,12 @@ struct OmpHoldsClause {
WRAPPER_CLASS_BOILERPLATE(OmpHoldsClause, common::Indirection<Expr>);
};
+// Ref: [5.2: 209]
+struct OmpIndirectClause {
+ WRAPPER_CLASS_BOILERPLATE(
+ OmpIndirectClause, std::optional<ScalarLogicalExpr>);
+};
+
// Ref: [5.2:72-73], in 4.5-5.1 it's scattered over individual directives
// that allow the IF clause.
//
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 4d0f5c3a127e1..c0c57d1832d4e 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -905,8 +905,8 @@ Inclusive make(const parser::OmpClause::Inclusive &inp,
Indirect make(const parser::OmpClause::Indirect &inp,
semantics::SemanticsContext &semaCtx) {
- // inp -> empty
- llvm_unreachable("Empty: indirect");
+ // inp.v.v -> std::optional<parser::ScalarLogicalExpr>
+ return Indirect{maybeApply(makeExprFn(semaCtx), inp.v.v)};
}
Init make(const parser::OmpClause::Init &inp,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 9b112a2133918..c55642d969503 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1004,6 +1004,8 @@ TYPE_PARSER( //
"IF" >> construct<OmpClause>(construct<OmpClause::If>(
parenthesized(Parser<OmpIfClause>{}))) ||
"INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
+ "INDIRECT" >> construct<OmpClause>(construct<OmpClause::Indirect>(
+ maybe(parenthesized(scalarLogicalExpr)))) ||
"INIT" >> construct<OmpClause>(construct<OmpClause::Init>(
parenthesized(Parser<OmpInitClause>{}))) ||
"INCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Inclusive>(
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 58d28dce7094a..83f4d1edf3c4f 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1820,15 +1820,24 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) {
const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
const parser::OmpClause *linkClause =
FindClause(llvm::omp::Clause::OMPC_link);
+ const parser::OmpClause *indirectClause =
+ FindClause(llvm::omp::Clause::OMPC_indirect);
if (!enterClause && !toClause && !linkClause) {
context_.Say(x.source,
"If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
}
+ if (indirectClause && !enterClause) {
+ context_.Say(x.source,
+ "The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive."_err_en_US);
+ }
unsigned version{context_.langOptions().OpenMPVersion};
if (toClause && version >= 52) {
context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
"The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
}
+ if (indirectClause) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_indirect);
+ }
}
}
diff --git a/flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90 b/flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90
new file mode 100644
index 0000000000000..d441cac47f5da
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90
@@ -0,0 +1,34 @@
+! This test checks the lowering of OpenMP Indirect Clause when used with the Declare Target directive
+
+! RUN: not flang -fc1 -emit-fir -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s
+
+module functions
+ implicit none
+
+ interface
+ function func() result(i)
+ character(1) :: i
+ end function
+ end interface
+
+contains
+ function func1() result(i)
+ !CHECK: not yet implemented: Unhandled clause INDIRECT in DECLARE TARGET construct
+ !$omp declare target enter(func1) indirect(.true.)
+ character(1) :: i
+ i = 'a'
+ return
+ end function
+end module
+
+program main
+ use functions
+ implicit none
+ procedure (func), pointer :: ptr1=>func1
+ character(1) :: val1
+
+ !$omp target map(from: val1)
+ val1 = ptr1()
+ !$omp end target
+
+end program
diff --git a/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 b/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90
new file mode 100644
index 0000000000000..df85942ec15a5
--- /dev/null
+++ b/flang/test/Parser/OpenMP/declare-target-indirect-tree.f90
@@ -0,0 +1,53 @@
+! REQUIRES: openmp_runtime
+
+! RUN: %flang_fc1 %openmp_flags -fopenmp-version=52 -fdebug-dump-parse-tree %s | FileCheck %s
+! RUN: %flang_fc1 %openmp_flags -fdebug-unparse -fopenmp-version=52 %s | FileCheck %s --check-prefix="UNPARSE"
+
+module functions
+ implicit none
+
+ interface
+ function func() result(i)
+ character(1) :: i
+ end function
+ end interface
+
+contains
+ function func1() result(i)
+ !$omp declare target enter(func1) indirect(.true.)
+ !CHECK: | | | | | OmpDeclareTargetSpecifier -> OmpDeclareTargetWithClause -> OmpClauseList -> OmpClause -> Enter -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'func1'
+ !CHECK-NEXT: | | | | | OmpClause -> Indirect -> OmpIndirectClause -> Scalar -> Logical -> Expr = '.true._4'
+ !CHECK-NEXT: | | | | | | LiteralConstant -> LogicalLiteralConstant
+ !CHECK-NEXT: | | | | | | | bool = 'true'
+ character(1) :: i
+ i = 'a'
+ return
+ end function
+
+ function func2() result(i)
+ !$omp declare target enter(func2) indirect
+ !CHECK: | | | | | OmpDeclareTargetSpecifier -> OmpDeclareTargetWithClause -> OmpClauseList -> OmpClause -> Enter -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'func2'
+ !CHECK-NEXT: | | | | | OmpClause -> Indirect -> OmpIndirectClause ->
+ character(1) :: i
+ i = 'b'
+ return
+ end function
+end module
+
+program main
+ use functions
+ implicit none
+ procedure (func), pointer :: ptr1=>func1, ptr2=>func2
+ character(1) :: val1, val2
+
+ !$omp target map(from: val1)
+ val1 = ptr1()
+ !$omp end target
+ !$omp target map(from: val2)
+ val2 = ptr2()
+ !$omp end target
+
+end program
+
+!UNPARSE: !$OMP DECLARE TARGET ENTER(func1) INDIRECT(.true._4)
+!UNPARSE: !$OMP DECLARE TARGET ENTER(func2) INDIRECT()
diff --git a/flang/test/Semantics/indirect01.f90 b/flang/test/Semantics/indirect01.f90
new file mode 100644
index 0000000000000..59850662275d9
--- /dev/null
+++ b/flang/test/Semantics/indirect01.f90
@@ -0,0 +1,34 @@
+! This test checks the lowering of OpenMP Indirect Clause when used with the Declare Target directive
+
+! RUN: not flang -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s
+
+module functions
+ implicit none
+
+ interface
+ function func() result(i)
+ character(1) :: i
+ end function
+ end interface
+
+contains
+ function func1() result(i)
+ !CHECK: The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive.
+ !$omp declare target indirect(.true.)
+ character(1) :: i
+ i = 'a'
+ return
+ end function
+end module
+
+program main
+ use functions
+ implicit none
+ procedure (func), pointer :: ptr1=>func1
+ character(1) :: val1
+
+ !$omp target map(from: val1)
+ val1 = ptr1()
+ !$omp end target
+
+end program
diff --git a/flang/test/Semantics/indirect02.f90 b/flang/test/Semantics/indirect02.f90
new file mode 100644
index 0000000000000..273f8856626b7
--- /dev/null
+++ b/flang/test/Semantics/indirect02.f90
@@ -0,0 +1,36 @@
+! This test checks the lowering of OpenMP Indirect Clause when used with the Declare Target directive
+
+! RUN: not flang -fopenmp -fopenmp-version=50 %s 2>&1 | FileCheck %s --check-prefix="CHECK-50"
+! RUN: not flang -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s --check-prefix="CHECK-52"
+
+module functions
+ implicit none
+
+ interface
+ function func() result(i)
+ character(1) :: i
+ end function
+ end interface
+
+contains
+ function func1() result(i)
+ !CHECK-50: INDIRECT clause is not allowed on directive DECLARE TARGET in OpenMP v5.0, try -fopenmp-version=51
+ !CHECK-52: not yet implemented: Unhandled clause INDIRECT in DECLARE TARGET construct
+ !$omp declare target enter(func1) indirect(.true.)
+ character(1) :: i
+ i = 'a'
+ return
+ end function
+end module
+
+program main
+ use functions
+ implicit none
+ procedure (func), pointer :: ptr1=>func1
+ character(1) :: val1
+
+ !$omp target map(from: val1)
+ val1 = ptr1()
+ !$omp end target
+
+end program
diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
index e0714e812e5cd..de888ff86fe91 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
@@ -701,7 +701,7 @@ template <typename T, typename I, typename E> //
struct IndirectT {
using InvokedByFptr = E;
using WrapperTrait = std::true_type;
- InvokedByFptr v;
+ OPT(InvokedByFptr) v;
};
// V5.2: [14.1.2] `init` clause
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 027692275b63b..a87111cb5a11d 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -246,6 +246,7 @@ def OMPC_Inclusive : Clause<[Spelling<"inclusive">]> {
let flangClass = "OmpObjectList";
}
def OMPC_Indirect : Clause<[Spelling<"indirect">]> {
+ let flangClass = "OmpIndirectClause";
}
def OMPC_Init : Clause<[Spelling<"init">]> {
let clangClass = "OMPInitClause";
@@ -646,7 +647,7 @@ def OMP_EndAssumes : Directive<[Spelling<"end assumes">]> {
def OMP_BeginDeclareTarget : Directive<[Spelling<"begin declare target">]> {
let allowedClauses = [
VersionedClause<OMPC_DeviceType>,
- VersionedClause<OMPC_Indirect>,
+ VersionedClause<OMPC_Indirect, 51>,
VersionedClause<OMPC_Link>,
VersionedClause<OMPC_To>,
];
@@ -724,7 +725,7 @@ def OMP_DeclareSimd : Directive<[Spelling<"declare simd">]> {
def OMP_DeclareTarget : Directive<[Spelling<"declare target">]> {
let allowedClauses = [
VersionedClause<OMPC_Enter, 52>,
- VersionedClause<OMPC_Indirect>,
+ VersionedClause<OMPC_Indirect, 51>,
VersionedClause<OMPC_Link>,
VersionedClause<OMPC_To>,
];
More information about the llvm-commits
mailing list