[flang][OpenMP] Parser support for Target directive and Device clause
This patch adds support for the device clause on `Target` directive. Device clause was added in OpenMP specification version 4.5 to create a device data environment for the extent of a region. On target construct, the device expression be either be `ancestor` (taking after the parent) or assign a new `device_num`. Reviewed By: kiranchandramohan Differential Revision: https://reviews.llvm.org/D126441
This commit is contained in:
parent
7ff2a9f250
commit
d9ff670330
|
@ -525,6 +525,8 @@ public:
|
|||
NODE(OmpAllocateClause, Allocator)
|
||||
NODE(parser, OmpScheduleClause)
|
||||
NODE_ENUM(OmpScheduleClause, ScheduleType)
|
||||
NODE(parser, OmpDeviceClause)
|
||||
NODE_ENUM(OmpDeviceClause, DeviceModifier)
|
||||
NODE(parser, OmpScheduleModifier)
|
||||
NODE(OmpScheduleModifier, Modifier1)
|
||||
NODE(OmpScheduleModifier, Modifier2)
|
||||
|
|
|
@ -3385,6 +3385,13 @@ struct OmpScheduleClause {
|
|||
t;
|
||||
};
|
||||
|
||||
// device([ device-modifier :] scalar-integer-expression)
|
||||
struct OmpDeviceClause {
|
||||
TUPLE_CLASS_BOILERPLATE(OmpDeviceClause);
|
||||
ENUM_CLASS(DeviceModifier, Ancestor, Device_Num)
|
||||
std::tuple<std::optional<DeviceModifier>, ScalarIntExpr> t;
|
||||
};
|
||||
|
||||
// 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr)
|
||||
struct OmpIfClause {
|
||||
TUPLE_CLASS_BOILERPLATE(OmpIfClause);
|
||||
|
|
|
@ -97,6 +97,14 @@ TYPE_PARSER(construct<OmpScheduleClause>(maybe(Parser<OmpScheduleModifier>{}),
|
|||
"RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime),
|
||||
maybe("," >> scalarIntExpr)))
|
||||
|
||||
// device([ device-modifier :] scalar-integer-expression)
|
||||
TYPE_PARSER(construct<OmpDeviceClause>(
|
||||
maybe(
|
||||
("ANCESTOR" >> pure(OmpDeviceClause::DeviceModifier::Ancestor) ||
|
||||
"DEVICE_NUM" >> pure(OmpDeviceClause::DeviceModifier::Device_Num)) /
|
||||
":"),
|
||||
scalarIntExpr))
|
||||
|
||||
// 2.12 IF (directive-name-modifier: scalar-logical-expr)
|
||||
TYPE_PARSER(construct<OmpIfClause>(
|
||||
maybe(
|
||||
|
@ -196,7 +204,7 @@ TYPE_PARSER(
|
|||
"DEPEND" >> construct<OmpClause>(construct<OmpClause::Depend>(
|
||||
parenthesized(Parser<OmpDependClause>{}))) ||
|
||||
"DEVICE" >> construct<OmpClause>(construct<OmpClause::Device>(
|
||||
parenthesized(scalarIntExpr))) ||
|
||||
parenthesized(Parser<OmpDeviceClause>{}))) ||
|
||||
"DIST_SCHEDULE" >>
|
||||
construct<OmpClause>(construct<OmpClause::DistSchedule>(
|
||||
parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) ||
|
||||
|
|
|
@ -2008,6 +2008,10 @@ public:
|
|||
Walk(std::get<OmpScheduleClause::ScheduleType>(x.t));
|
||||
Walk(",", std::get<std::optional<ScalarIntExpr>>(x.t));
|
||||
}
|
||||
void Unparse(const OmpDeviceClause &x) {
|
||||
Walk(std::get<std::optional<OmpDeviceClause::DeviceModifier>>(x.t), ":");
|
||||
Walk(std::get<ScalarIntExpr>(x.t));
|
||||
}
|
||||
void Unparse(const OmpAlignedClause &x) {
|
||||
Walk(std::get<std::list<Name>>(x.t), ",");
|
||||
Walk(std::get<std::optional<ScalarIntConstantExpr>>(x.t));
|
||||
|
@ -2580,6 +2584,7 @@ public:
|
|||
WALK_NESTED_ENUM(OmpDependenceType, Type) // OMP dependence-type
|
||||
WALK_NESTED_ENUM(OmpMapType, Type) // OMP map-type
|
||||
WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type
|
||||
WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier
|
||||
WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier
|
||||
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
|
||||
#undef WALK_NESTED_ENUM
|
||||
|
|
|
@ -1874,7 +1874,6 @@ CHECK_REQ_SCALAR_INT_CLAUSE(NumTeams, OMPC_num_teams)
|
|||
CHECK_REQ_SCALAR_INT_CLAUSE(NumThreads, OMPC_num_threads)
|
||||
CHECK_REQ_SCALAR_INT_CLAUSE(Priority, OMPC_priority)
|
||||
CHECK_REQ_SCALAR_INT_CLAUSE(ThreadLimit, OMPC_thread_limit)
|
||||
CHECK_REQ_SCALAR_INT_CLAUSE(Device, OMPC_device)
|
||||
|
||||
CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Collapse, OMPC_collapse)
|
||||
CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Safelen, OMPC_safelen)
|
||||
|
@ -2373,6 +2372,14 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
|
|||
}
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
|
||||
CheckAllowed(llvm::omp::Clause::OMPC_device);
|
||||
const parser::OmpDeviceClause &deviceClause = x.v;
|
||||
const auto &device{std::get<1>(deviceClause.t)};
|
||||
RequiresPositiveParameter(
|
||||
llvm::omp::Clause::OMPC_device, device, "device expression");
|
||||
}
|
||||
|
||||
void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
|
||||
CheckAllowed(llvm::omp::Clause::OMPC_depend);
|
||||
if (const auto *inOut{std::get_if<parser::OmpDependClause::InOut>(&x.v.u)}) {
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck --ignore-case %s
|
||||
! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
|
||||
! Checks the parsing of Openmp 5.0 Target Device constructs
|
||||
!
|
||||
PROGRAM main
|
||||
USE OMP_LIB
|
||||
IMPLICIT NONE
|
||||
INTEGER :: X, Y
|
||||
INTEGER :: M = 1
|
||||
|
||||
|
||||
!------------------------------------------------------
|
||||
! Check Device clause with a constant argument
|
||||
!------------------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(1)
|
||||
!$OMP TARGET DEVICE(1)
|
||||
M = M + 1
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP END TARGET
|
||||
|
||||
!PARSE-TREE: OmpBeginBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
|
||||
!PARSE-TREE: Scalar -> Integer -> Expr = '1_4'
|
||||
!PARSE-TREE: LiteralConstant -> IntLiteralConstant = '1'
|
||||
!PARSE-TREE: OmpEndBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList ->
|
||||
|
||||
!------------------------------------------------------
|
||||
! Check Device clause with a constant integer expression argument
|
||||
!------------------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(2-1)
|
||||
!$OMP TARGET DEVICE(2-1)
|
||||
M = M + 1
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP END TARGET
|
||||
|
||||
!PARSE-TREE: OmpBeginBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
|
||||
!PARSE-TREE: Scalar -> Integer -> Expr = '1_4'
|
||||
!PARSE-TREE: Subtract
|
||||
!PARSE-TREE: Expr = '2_4'
|
||||
!PARSE-TREE: LiteralConstant -> IntLiteralConstant = '2'
|
||||
!PARSE-TREE: Expr = '1_4'
|
||||
!PARSE-TREE: LiteralConstant -> IntLiteralConstant = '1'
|
||||
!PARSE-TREE: OmpEndBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList ->
|
||||
|
||||
|
||||
!------------------------------------------------------
|
||||
! Check Device clause with a variable argument
|
||||
!------------------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(X)
|
||||
!$OMP TARGET DEVICE(X)
|
||||
M = M + 1
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP END TARGET
|
||||
|
||||
!PARSE-TREE: OmpBeginBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
|
||||
!PARSE-TREE: Scalar -> Integer -> Expr = 'x'
|
||||
!PARSE-TREE: Designator -> DataRef -> Name = 'x'
|
||||
!PARSE-TREE: OmpEndBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList ->
|
||||
|
||||
|
||||
!------------------------------------------------------
|
||||
! Check Device clause with an variable integer expression
|
||||
!------------------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(X+Y)
|
||||
!$OMP TARGET DEVICE(X+Y)
|
||||
M = M + 1
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP END TARGET
|
||||
|
||||
!PARSE-TREE: OmpBeginBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
|
||||
!PARSE-TREE: Scalar -> Integer -> Expr = 'x+y'
|
||||
!PARSE-TREE: Add
|
||||
!PARSE-TREE: Expr = 'x'
|
||||
!PARSE-TREE: Designator -> DataRef -> Name = 'x'
|
||||
!PARSE-TREE: Expr = 'y'
|
||||
!PARSE-TREE: Designator -> DataRef -> Name = 'y'
|
||||
!PARSE-TREE: OmpEndBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList ->
|
||||
|
||||
!------------------------------------------------------
|
||||
! Check Device Ancestor clause with a constant argument
|
||||
!------------------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(ANCESTOR:1)
|
||||
!$OMP TARGET DEVICE(ANCESTOR: 1)
|
||||
M = M + 1
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP END TARGET
|
||||
|
||||
!PARSE-TREE: OmpBeginBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
|
||||
!PARSE-TREE: DeviceModifier = Ancestor
|
||||
!PARSE-TREE: Scalar -> Integer -> Expr = '1_4'
|
||||
!PARSE-TREE: LiteralConstant -> IntLiteralConstant = '1'
|
||||
!PARSE-TREE: OmpEndBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList ->
|
||||
|
||||
|
||||
!--------------------------------------------------------
|
||||
! Check Device Devive-Num clause with a constant argument
|
||||
!--------------------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(DEVICE_NUM:2)
|
||||
!$OMP TARGET DEVICE(DEVICE_NUM: 2)
|
||||
M = M + 1
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP END TARGET
|
||||
|
||||
!PARSE-TREE: OmpBeginBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
|
||||
!PARSE-TREE: DeviceModifier = Device_Num
|
||||
!PARSE-TREE: Scalar -> Integer -> Expr = '2_4'
|
||||
!PARSE-TREE: LiteralConstant -> IntLiteralConstant = '2'
|
||||
!PARSE-TREE: OmpEndBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList ->
|
||||
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
! Check Device Ancestor clause with a variable expression argument
|
||||
!-------------------------------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(ANCESTOR:X+Y)
|
||||
!$OMP TARGET DEVICE(ANCESTOR: X + Y)
|
||||
M = M + 1
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP END TARGET
|
||||
|
||||
!PARSE-TREE: OmpBeginBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
|
||||
!PARSE-TREE: DeviceModifier = Ancestor
|
||||
!PARSE-TREE: Scalar -> Integer -> Expr = 'x+y'
|
||||
!PARSE-TREE: Add
|
||||
!PARSE-TREE: Expr = 'x'
|
||||
!PARSE-TREE: Designator -> DataRef -> Name = 'x'
|
||||
!PARSE-TREE: Expr = 'y'
|
||||
!PARSE-TREE: Designator -> DataRef -> Name = 'y'
|
||||
!PARSE-TREE: OmpEndBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList ->
|
||||
|
||||
|
||||
!-------------------------------------------------------------------
|
||||
! Check Device Devive-Num clause with a variable expression argument
|
||||
!-------------------------------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(DEVICE_NUM:X-Y)
|
||||
!$OMP TARGET DEVICE(DEVICE_NUM: X - Y)
|
||||
M = M + 1
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP END TARGET
|
||||
|
||||
!PARSE-TREE: OmpBeginBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
!PARSE-TREE: OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
|
||||
!PARSE-TREE: DeviceModifier = Device_Num
|
||||
!PARSE-TREE: Scalar -> Integer -> Expr = 'x-y'
|
||||
!PARSE-TREE: Subtract
|
||||
!PARSE-TREE: Expr = 'x'
|
||||
!PARSE-TREE: Designator -> DataRef -> Name = 'x'
|
||||
!PARSE-TREE: Expr = 'y'
|
||||
!PARSE-TREE: Designator -> DataRef -> Name = 'y'
|
||||
!PARSE-TREE: OmpEndBlockDirective
|
||||
!PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target
|
||||
END PROGRAM
|
|
@ -0,0 +1,80 @@
|
|||
! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck --ignore-case %s
|
||||
! Verifies the unparsing of the Openmp Target Device constructs
|
||||
PROGRAM main
|
||||
USE OMP_LIB
|
||||
IMPLICIT NONE
|
||||
INTEGER:: X, Y
|
||||
INTEGER:: M = 1
|
||||
|
||||
!--------------------------------------------
|
||||
! constant argument
|
||||
!--------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(0)
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP TARGET DEVICE(0)
|
||||
M = M + 1
|
||||
!$OMP END TARGET
|
||||
|
||||
!--------------------------------------------
|
||||
! constant expression argument
|
||||
!--------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(2+1)
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP TARGET DEVICE(2+1)
|
||||
M = M + 1
|
||||
!$OMP END TARGET
|
||||
|
||||
!--------------------------------------------
|
||||
! variable argument
|
||||
!--------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(X)
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP TARGET DEVICE(X)
|
||||
M = M + 1
|
||||
!$OMP END TARGET
|
||||
|
||||
!--------------------------------------------
|
||||
! variable expression argument
|
||||
!--------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(X-Y)
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP TARGET DEVICE(X-Y)
|
||||
M = M + 1
|
||||
!$OMP END TARGET
|
||||
|
||||
!--------------------------------------------
|
||||
! Ancestor followed by constant argument
|
||||
!--------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(ANCESTOR:0)
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP TARGET DEVICE(ANCESTOR: 0)
|
||||
M = M + 1
|
||||
!$OMP END TARGET
|
||||
|
||||
!--------------------------------------------
|
||||
! Device_Num followed by constant argument
|
||||
!--------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(DEVICE_NUM:1)
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP TARGET DEVICE(DEVICE_NUM: 1)
|
||||
M = M + 1
|
||||
!$OMP END TARGET
|
||||
|
||||
!--------------------------------------------
|
||||
! Ancestor followed by variable expression argument
|
||||
!--------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(ANCESTOR:X+Y)
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP TARGET DEVICE(ANCESTOR: X + Y)
|
||||
M = M + 1
|
||||
!$OMP END TARGET
|
||||
|
||||
!--------------------------------------------
|
||||
! Device_Num followed by variable expression argument
|
||||
!--------------------------------------------
|
||||
!CHECK: !$OMP TARGET DEVICE(DEVICE_NUM:X-Y)
|
||||
!CHECK: !$OMP END TARGET
|
||||
!$OMP TARGET DEVICE(DEVICE_NUM: X - Y)
|
||||
M = M + 1
|
||||
!$OMP END TARGET
|
||||
END PROGRAM
|
|
@ -129,10 +129,10 @@ program main
|
|||
enddo
|
||||
!$omp end target data
|
||||
|
||||
!ERROR: The parameter of the DEVICE clause must be a positive integer expression
|
||||
!ERROR: The device expression of the DEVICE clause must be a positive integer expression
|
||||
!$omp target enter data map(alloc:A) device(-2)
|
||||
|
||||
!ERROR: The parameter of the DEVICE clause must be a positive integer expression
|
||||
!ERROR: The device expression of the DEVICE clause must be a positive integer expression
|
||||
!$omp target exit data map(delete:A) device(-2)
|
||||
|
||||
!ERROR: At most one IF clause can appear on the TARGET ENTER DATA directive
|
||||
|
|
|
@ -210,7 +210,7 @@ def OMPC_Depend : Clause<"depend"> {
|
|||
}
|
||||
def OMPC_Device : Clause<"device"> {
|
||||
let clangClass = "OMPDeviceClause";
|
||||
let flangClass = "ScalarIntExpr";
|
||||
let flangClass = "OmpDeviceClause";
|
||||
}
|
||||
def OMPC_Threads : Clause<"threads"> { let clangClass = "OMPThreadsClause"; }
|
||||
def OMPC_Simd : Clause<"simd"> { let clangClass = "OMPSIMDClause"; }
|
||||
|
|
Loading…
Reference in New Issue