diff --git a/flang/include/flang/Lower/OpenMP/Clauses.h b/flang/include/flang/Lower/OpenMP/Clauses.h index 638846835094c..18e2f209c2d7a 100644 --- a/flang/include/flang/Lower/OpenMP/Clauses.h +++ b/flang/include/flang/Lower/OpenMP/Clauses.h @@ -277,6 +277,7 @@ using Read = tomp::clause::ReadT; using Reduction = tomp::clause::ReductionT; using Relaxed = tomp::clause::RelaxedT; using Release = tomp::clause::ReleaseT; +using Replayable = tomp::clause::ReplayableT; using ReverseOffload = tomp::clause::ReverseOffloadT; using Safelen = tomp::clause::SafelenT; using Schedule = tomp::clause::ScheduleT; @@ -290,6 +291,7 @@ using Permutation = tomp::clause::PermutationT; using TaskReduction = tomp::clause::TaskReductionT; using ThreadLimit = tomp::clause::ThreadLimitT; using Threads = tomp::clause::ThreadsT; +using Transparent = tomp::clause::TransparentT; using To = tomp::clause::ToT; using UnifiedAddress = tomp::clause::UnifiedAddressT; using UnifiedSharedMemory = diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index d2ab7cbd8fe35..1c9fd7673e06d 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -658,6 +658,7 @@ class ParseTreeDumper { NODE(parser, OmpReductionSpecifier) NODE(parser, OmpRefModifier) NODE_ENUM(OmpRefModifier, Value) + NODE(parser, OmpReplayableClause) NODE(parser, OmpScheduleClause) NODE(OmpScheduleClause, Modifier) NODE_ENUM(OmpScheduleClause, Kind) @@ -686,6 +687,7 @@ class ParseTreeDumper { NODE(parser, OmpTraitSetSelector) NODE(parser, OmpTraitSetSelectorName) NODE_ENUM(OmpTraitSetSelectorName, Value) + NODE(parser, OmpTransparentClause) NODE(parser, OmpTypeNameList) NODE(parser, OmpTypeSpecifier) NODE(parser, OmpUpdateClause) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 622b5f90a9fba..951c96b974141 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4643,6 +4643,14 @@ struct OmpReductionClause { std::tuple t; }; +// Ref: [6.0:440:441] +// +// replayable-clause -> +// REPLAYABLE[(replayable-expression)] // since 6.0 +struct OmpReplayableClause { + WRAPPER_CLASS_BOILERPLATE(OmpReplayableClause, Scalar>); +}; + // Ref: [4.5:56-63], [5.0:101-109], [5.1:126-133], [5.2:252-254] // // schedule-clause -> @@ -4692,6 +4700,14 @@ struct OmpToClause { std::tuple t; }; +// Ref: [6.0:510-511] +// +// transparent-clause -> +// TRANSPARENT[(impex-type)] // since 6.0 +struct OmpTransparentClause { + WRAPPER_CLASS_BOILERPLATE(OmpTransparentClause, ScalarIntExpr); +}; + // Ref: [5.0:254-255], [5.1:287-288], [5.2:321-322] // // In ATOMIC construct diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index cecc1a9395892..78fe5aa031ba1 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -239,11 +239,11 @@ MAKE_EMPTY_CLASS(Relaxed, Relaxed); MAKE_EMPTY_CLASS(Release, Release); MAKE_EMPTY_CLASS(ReverseOffload, ReverseOffload); MAKE_EMPTY_CLASS(SeqCst, SeqCst); +MAKE_EMPTY_CLASS(SelfMaps, SelfMaps); MAKE_EMPTY_CLASS(Simd, Simd); MAKE_EMPTY_CLASS(Threads, Threads); MAKE_EMPTY_CLASS(UnifiedAddress, UnifiedAddress); MAKE_EMPTY_CLASS(UnifiedSharedMemory, UnifiedSharedMemory); -MAKE_EMPTY_CLASS(SelfMaps, SelfMaps); MAKE_EMPTY_CLASS(Unknown, Unknown); MAKE_EMPTY_CLASS(Untied, Untied); MAKE_EMPTY_CLASS(Weak, Weak); @@ -257,6 +257,8 @@ MAKE_EMPTY_CLASS(Threadprivate, Threadprivate); MAKE_INCOMPLETE_CLASS(AdjustArgs, AdjustArgs); MAKE_INCOMPLETE_CLASS(AppendArgs, AppendArgs); +MAKE_INCOMPLETE_CLASS(Replayable, Replayable); +MAKE_INCOMPLETE_CLASS(Transparent, Transparent); List makeIteratorSpecifiers(const parser::OmpIteratorSpecifier &inp, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 78a5746bb0bf8..519bce64321d4 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -36,6 +36,9 @@ using namespace Fortran::parser::omp; constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok; constexpr auto endOmpLine = space >> endOfLine; +constexpr auto logicalConstantExpr{logical(constantExpr)}; +constexpr auto scalarLogicalConstantExpr{scalar(logicalConstantExpr)}; + // Given a parser for a single element, and a parser for a list of elements // of the same type, create a parser that constructs the entire list by having // the single element be the head of the list, and the rest be the tail. @@ -870,6 +873,8 @@ TYPE_PARSER(construct( maybe(nonemptyList(Parser{}) / ":"), Parser{})) +TYPE_PARSER(construct(scalarLogicalConstantExpr)) + // OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list) TYPE_PARSER(construct( maybe(nonemptyList(Parser{}) / ":"), @@ -879,6 +884,8 @@ TYPE_PARSER(construct( maybe(nonemptyList(Parser{}) / ":"), Parser{})) +TYPE_PARSER(construct(scalarIntExpr)) + // OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list) // OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier // [, allocate-modifier] :] @@ -1194,6 +1201,8 @@ TYPE_PARSER( // "READ" >> construct(construct()) || "RELAXED" >> construct(construct()) || "RELEASE" >> construct(construct()) || + "REPLAYABLE" >> construct(construct( + maybe(parenthesized(Parser{})))) || "REVERSE_OFFLOAD" >> construct(construct()) || "SAFELEN" >> construct(construct( @@ -1217,6 +1226,9 @@ TYPE_PARSER( // parenthesized(scalarIntExpr))) || "TO" >> construct(construct( parenthesized(Parser{}))) || + "TRANSPARENT" >> + construct(construct( + maybe(parenthesized(Parser{})))) || "USE" >> construct(construct( parenthesized(Parser{}))) || "USE_DEVICE_PTR" >> construct(construct( diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index b7f72756c9530..6bc9f9955fe24 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2831,6 +2831,8 @@ CHECK_SIMPLE_CLAUSE(AcqRel, OMPC_acq_rel) CHECK_SIMPLE_CLAUSE(Acquire, OMPC_acquire) CHECK_SIMPLE_CLAUSE(Relaxed, OMPC_relaxed) CHECK_SIMPLE_CLAUSE(Release, OMPC_release) +CHECK_SIMPLE_CLAUSE(Replayable, OMPC_replayable) +CHECK_SIMPLE_CLAUSE(Transparent, OMPC_transparent) CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst) CHECK_SIMPLE_CLAUSE(Fail, OMPC_fail) diff --git a/flang/test/Parser/OpenMP/replayable-clause.f90 b/flang/test/Parser/OpenMP/replayable-clause.f90 new file mode 100644 index 0000000000000..c1733449fcb70 --- /dev/null +++ b/flang/test/Parser/OpenMP/replayable-clause.f90 @@ -0,0 +1,60 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f00 + !$omp task replayable + block + end block +end + +!UNPARSE: SUBROUTINE f00 +!UNPARSE: !$OMP TASK REPLAYABLE +!UNPARSE: BLOCK +!UNPARSE: END BLOCK +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct +!PARSE-TREE: | OmpBeginDirective +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = task +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Replayable -> +!PARSE-TREE: | | Flags = None +!PARSE-TREE: | Block + + +subroutine f01(x) + implicit none + integer :: x + !$omp target_update to(x) replayable(.true.) +end + +!UNPARSE: SUBROUTINE f01 (x) +!UNPARSE: IMPLICIT NONE +!UNPARSE: INTEGER x +!UNPARSE: !$OMP TARGET_UPDATE TO(x) REPLAYABLE(.true._4) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = target update +!PARSE-TREE: | OmpClauseList -> OmpClause -> To -> OmpToClause +!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | bool = 'true' +!PARSE-TREE: | OmpClause -> Replayable -> OmpReplayableClause -> Scalar -> Logical -> Constant -> Expr = '.true._4' +!PARSE-TREE: | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | bool = 'true' +!PARSE-TREE: | Flags = None + + +subroutine f02 + !$omp taskwait replayable(.false.) +end + +!UNPARSE: SUBROUTINE f02 +!UNPARSE: !$OMP TASKWAIT REPLAYABLE(.false._4) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPSimpleStandaloneConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = taskwait +!PARSE-TREE: | OmpClauseList -> OmpClause -> Replayable -> OmpReplayableClause -> Scalar -> Logical -> Constant -> Expr = '.false._4' +!PARSE-TREE: | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | bool = 'false' +!PARSE-TREE: | Flags = None diff --git a/flang/test/Parser/OpenMP/transparent-clause.f90 b/flang/test/Parser/OpenMP/transparent-clause.f90 new file mode 100644 index 0000000000000..01f49f5e8a15d --- /dev/null +++ b/flang/test/Parser/OpenMP/transparent-clause.f90 @@ -0,0 +1,76 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f00(x) + implicit none + integer :: x + !$omp target_data map(to: x) transparent + block + end block +end + +!UNPARSE: SUBROUTINE f00 (x) +!UNPARSE: IMPLICIT NONE +!UNPARSE: INTEGER x +!UNPARSE: !$OMP TARGET_DATA MAP(TO: x) TRANSPARENT +!UNPARSE: BLOCK +!UNPARSE: END BLOCK +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct +!PARSE-TREE: | OmpBeginDirective +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = target data +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Map -> OmpMapClause +!PARSE-TREE: | | | Modifier -> OmpMapType -> Value = To +!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | | bool = 'true' +!PARSE-TREE: | | OmpClause -> Transparent -> +!PARSE-TREE: | | Flags = None +!PARSE-TREE: | Block + + +subroutine f01 + !$omp task transparent(0) + !$omp end task +end + +!UNPARSE: SUBROUTINE f01 +!UNPARSE: !$OMP TASK TRANSPARENT(0_4) +!UNPARSE: !$OMP END TASK +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OmpBlockConstruct +!PARSE-TREE: | OmpBeginDirective +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = task +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Transparent -> OmpTransparentClause -> Scalar -> Integer -> Expr = '0_4' +!PARSE-TREE: | | | LiteralConstant -> IntLiteralConstant = '0' +!PARSE-TREE: | | Flags = None +!PARSE-TREE: | Block +!PARSE-TREE: | OmpEndDirective +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = task +!PARSE-TREE: | | OmpClauseList -> +!PARSE-TREE: | | Flags = None + + +subroutine f02 + implicit none + integer :: i + !$omp taskloop transparent(2) + do i = 1, 10 + end do +end + +!UNPARSE: SUBROUTINE f02 +!UNPARSE: IMPLICIT NONE +!UNPARSE: INTEGER i +!UNPARSE: !$OMP TASKLOOP TRANSPARENT(2_4) +!UNPARSE: DO i=1_4,10_4 +!UNPARSE: END DO +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!PARSE-TREE: | OmpBeginLoopDirective +!PARSE-TREE: | | OmpLoopDirective -> llvm::omp::Directive = taskloop +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Transparent -> OmpTransparentClause -> Scalar -> Integer -> Expr = '2_4' +!PARSE-TREE: | | | LiteralConstant -> IntLiteralConstant = '2' +!PARSE-TREE: | DoConstruct diff --git a/flang/test/Semantics/OpenMP/replayable-clause.f90 b/flang/test/Semantics/OpenMP/replayable-clause.f90 new file mode 100644 index 0000000000000..b8fe6cea23a6f --- /dev/null +++ b/flang/test/Semantics/OpenMP/replayable-clause.f90 @@ -0,0 +1,22 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 + +subroutine f00(x) + implicit none + logical :: x + !ERROR: Must be a constant value + !$omp task replayable(x) + !$omp end task +end + +subroutine f01 + !ERROR: Must have LOGICAL type, but is INTEGER(4) + !$omp task replayable(7) + !$omp end task +end + +subroutine f02 + !No diagnostic expected + !$omp task replayable + !$omp end task +end + diff --git a/flang/test/Semantics/OpenMP/transparent-clause.f90 b/flang/test/Semantics/OpenMP/transparent-clause.f90 new file mode 100644 index 0000000000000..4831ba0f7cef6 --- /dev/null +++ b/flang/test/Semantics/OpenMP/transparent-clause.f90 @@ -0,0 +1,19 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 + +subroutine f00(x) + integer :: x(10) + !ERROR: Must be a scalar value, but is a rank-1 array + !$omp task transparent(x) + !$omp end task +end + +subroutine f01 + implicit none + integer :: i + !ERROR: Must have INTEGER type, but is CHARACTER(KIND=1,LEN=5_8) + !$omp taskloop transparent("hello") + do i = 1, 10 + end do + !$omp end taskloop +end + diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index 56905854f9baa..1ed23eed1571d 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -1046,6 +1046,12 @@ struct ReleaseT { using EmptyTrait = std::true_type; }; +// [6.0:440-441] `replayable` clause +template // +struct ReplayableT { + using IncompleteTrait = std::true_type; +}; + // V5.2: [8.2.1] `requirement` clauses template // struct ReverseOffloadT { @@ -1153,6 +1159,12 @@ struct ToT { std::tuple t; }; +// [6.0:440-441] `transparent` clause +template // +struct TransparentT { + using IncompleteTrait = std::true_type; +}; + // V5.2: [8.2.1] `requirement` clauses template // struct UnifiedAddressT { @@ -1279,7 +1291,8 @@ using EmptyClausesT = std::variant< template using IncompleteClausesT = std::variant, AppendArgsT, MatchT, - OtherwiseT, WhenT>; + OtherwiseT, ReplayableT, + TransparentT, WhenT>; template using TupleClausesT = diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index ce136197dd0d7..6a41c24e78149 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -456,6 +456,10 @@ def OMPC_Relaxed : Clause<[Spelling<"relaxed">]> { def OMPC_Release : Clause<[Spelling<"release">]> { let clangClass = "OMPReleaseClause"; } +def OMPC_Replayable : Clause<[Spelling<"replayable">]> { + let flangClass = "OmpReplayableClause"; + let isValueOptional = true; +} def OMPC_ReverseOffload : Clause<[Spelling<"reverse_offload">]> { let clangClass = "OMPReverseOffloadClause"; } @@ -523,6 +527,10 @@ def OMPC_To : Clause<[Spelling<"to">]> { let clangClass = "OMPToClause"; let flangClass = "OmpToClause"; } +def OMPC_Transparent : Clause<[Spelling<"transparent">]> { + let flangClass = "OmpTransparentClause"; + let isValueOptional = true; +} def OMPC_UnifiedAddress : Clause<[Spelling<"unified_address">]> { let clangClass = "OMPUnifiedAddressClause"; } @@ -1128,6 +1136,7 @@ def OMP_Target : Directive<[Spelling<"target">]> { VersionedClause, VersionedClause, VersionedClause, + VersionedClause, VersionedClause, ]; let association = AS_Block; @@ -1139,6 +1148,7 @@ def OMP_TargetData : Directive<[Spelling<"target data", 1, 52>, VersionedClause, VersionedClause, VersionedClause, + VersionedClause, ]; let requiredClauses = [ VersionedClause, @@ -1157,6 +1167,7 @@ def OMP_TargetEnterData : Directive<[Spelling<"target enter data", 1, 52>, VersionedClause, VersionedClause, VersionedClause, + VersionedClause, ]; let requiredClauses = [ VersionedClause, @@ -1173,6 +1184,7 @@ def OMP_TargetExitData : Directive<[Spelling<"target exit data", 1, 52>, VersionedClause, VersionedClause, VersionedClause, + VersionedClause, ]; let requiredClauses = [ VersionedClause, @@ -1191,6 +1203,7 @@ def OMP_TargetUpdate : Directive<[Spelling<"target update", 1, 52>, VersionedClause, VersionedClause, VersionedClause, + VersionedClause, ]; let association = AS_None; let category = CA_Executable; @@ -1213,6 +1226,8 @@ def OMP_Task : Directive<[Spelling<"task">]> { VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, ]; let association = AS_Block; let category = CA_Executable; @@ -1254,6 +1269,8 @@ def OMP_TaskLoop : Directive<[Spelling<"taskloop">]> { VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, ]; let allowedExclusiveClauses = [ VersionedClause, @@ -1267,6 +1284,9 @@ def OMP_TaskWait : Directive<[Spelling<"taskwait">]> { VersionedClause, VersionedClause, ]; + let allowedOnceClauses = [ + VersionedClause, + ]; let association = AS_None; let category = CA_Executable; }