[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
This commit is contained in:
@@ -565,6 +565,7 @@ public:
|
||||
NODE_ENUM(OmpDependenceType, Value)
|
||||
NODE(parser, OmpTaskDependenceType)
|
||||
NODE_ENUM(OmpTaskDependenceType, Value)
|
||||
NODE(parser, OmpIndirectClause)
|
||||
NODE(parser, OmpIterationOffset)
|
||||
NODE(parser, OmpIteration)
|
||||
NODE(parser, OmpIterationVector)
|
||||
|
||||
@@ -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.
|
||||
//
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
34
flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90
Normal file
34
flang/test/Lower/OpenMP/Todo/omp-clause-indirect.f90
Normal file
@@ -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
|
||||
53
flang/test/Parser/OpenMP/declare-target-indirect-tree.f90
Normal file
53
flang/test/Parser/OpenMP/declare-target-indirect-tree.f90
Normal file
@@ -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()
|
||||
34
flang/test/Semantics/indirect01.f90
Normal file
34
flang/test/Semantics/indirect01.f90
Normal file
@@ -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
|
||||
36
flang/test/Semantics/indirect02.f90
Normal file
36
flang/test/Semantics/indirect02.f90
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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>,
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user