diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -525,6 +525,8 @@ 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) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3385,6 +3385,13 @@ t; }; +// device([ device-modifier :] scalar-integer-expression) +struct OmpDeviceClause { + TUPLE_CLASS_BOILERPLATE(OmpDeviceClause); + ENUM_CLASS(DeviceModifier, Ancestor, Device_Num) + std::tuple, ScalarIntExpr> t; +}; + // 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr) struct OmpIfClause { TUPLE_CLASS_BOILERPLATE(OmpIfClause); diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -97,6 +97,14 @@ "RUNTIME" >> pure(OmpScheduleClause::ScheduleType::Runtime), maybe("," >> scalarIntExpr))) +// device([ device-modifier :] scalar-integer-expression) +TYPE_PARSER(construct( + 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( maybe( @@ -196,7 +204,7 @@ "DEPEND" >> construct(construct( parenthesized(Parser{}))) || "DEVICE" >> construct(construct( - parenthesized(scalarIntExpr))) || + parenthesized(Parser{}))) || "DIST_SCHEDULE" >> construct(construct( parenthesized("STATIC" >> maybe("," >> scalarIntExpr)))) || diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2008,6 +2008,10 @@ Walk(std::get(x.t)); Walk(",", std::get>(x.t)); } + void Unparse(const OmpDeviceClause &x) { + Walk(std::get>(x.t), ":"); + Walk(std::get(x.t)); + } void Unparse(const OmpAlignedClause &x) { Walk(std::get>(x.t), ","); Walk(std::get>(x.t)); @@ -2580,6 +2584,7 @@ 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 diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1874,7 +1874,6 @@ 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::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(&x.v.u)}) { diff --git a/flang/test/Parser/omp_target_device_parse.f90 b/flang/test/Parser/omp_target_device_parse.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Parser/omp_target_device_parse.f90 @@ -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 diff --git a/flang/test/Parser/omp_target_device_unparse.f90 b/flang/test/Parser/omp_target_device_unparse.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Parser/omp_target_device_unparse.f90 @@ -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 diff --git a/flang/test/Semantics/OpenMP/omp-device-constructs.f90 b/flang/test/Semantics/OpenMP/omp-device-constructs.f90 --- a/flang/test/Semantics/OpenMP/omp-device-constructs.f90 +++ b/flang/test/Semantics/OpenMP/omp-device-constructs.f90 @@ -129,10 +129,10 @@ 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 diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -210,7 +210,7 @@ } 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"; }