diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index 06ca12a492d29..9fce67e61ed30 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -483,6 +483,8 @@ struct NodeVisitor { READ_FEATURE(OmpEndCriticalDirective) READ_FEATURE(OmpEndLoopDirective) READ_FEATURE(OmpEndSectionsDirective) + READ_FEATURE(OmpGrainsizeClause) + READ_FEATURE(OmpGrainsizeClause::Prescriptiveness) READ_FEATURE(OmpIfClause) READ_FEATURE(OmpIfClause::DirectiveNameModifier) READ_FEATURE(OmpLinearClause) @@ -494,6 +496,8 @@ struct NodeVisitor { READ_FEATURE(OmpMapClause) READ_FEATURE(OmpMapClause::TypeModifier) READ_FEATURE(OmpMapClause::Type) + READ_FEATURE(OmpNumTasksClause) + READ_FEATURE(OmpNumTasksClause::Prescriptiveness) READ_FEATURE(OmpObject) READ_FEATURE(OmpObjectList) READ_FEATURE(OmpOrderClause) diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 76d2f164fc4bf..ccdfe980f6f38 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -547,6 +547,10 @@ class ParseTreeDumper { NODE_ENUM(OmpOrderClause, Type) NODE(parser, OmpOrderModifier) NODE_ENUM(OmpOrderModifier, Kind) + NODE(parser, OmpGrainsizeClause) + NODE_ENUM(OmpGrainsizeClause, Prescriptiveness) + NODE(parser, OmpNumTasksClause) + NODE_ENUM(OmpNumTasksClause, Prescriptiveness) NODE(parser, OmpProcBindClause) NODE_ENUM(OmpProcBindClause, Type) NODE_ENUM(OmpReductionClause, ReductionModifier) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index c1884f6e88d1e..2a312e29a3a44 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3559,6 +3559,13 @@ struct OmpDependClause { std::variant u; }; +// OMP 5.2 12.6.1 grainsize-clause -> grainsize ([prescriptiveness :] value) +struct OmpGrainsizeClause { + TUPLE_CLASS_BOILERPLATE(OmpGrainsizeClause); + ENUM_CLASS(Prescriptiveness, Strict); + std::tuple, ScalarIntExpr> t; +}; + // 2.12 if-clause -> IF ([ directive-name-modifier :] scalar-logical-expr) struct OmpIfClause { TUPLE_CLASS_BOILERPLATE(OmpIfClause); @@ -3688,6 +3695,13 @@ struct OmpScheduleClause { t; }; +// OMP 5.2 12.6.2 num_tasks-clause -> num_tasks ([prescriptiveness :] value) +struct OmpNumTasksClause { + TUPLE_CLASS_BOILERPLATE(OmpNumTasksClause); + ENUM_CLASS(Prescriptiveness, Strict); + std::tuple, ScalarIntExpr> t; +}; + // OpenMP Clauses struct OmpClause { UNION_CLASS_BOILERPLATE(OmpClause); diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index ee3d74a7c631a..3bd89b5432886 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -721,10 +721,20 @@ From make(const parser::OmpClause::From &inp, // Full: empty Grainsize make(const parser::OmpClause::Grainsize &inp, - semantics::SemanticsContext &semaCtx) { - // inp.v -> parser::ScalarIntExpr - return Grainsize{{/*Prescriptiveness=*/std::nullopt, - /*GrainSize=*/makeExpr(inp.v, semaCtx)}}; + semantics::SemanticsContext &semaCtx) { + // inp.v -> parser::OmpGrainsizeClause + using wrapped = parser::OmpGrainsizeClause; + + CLAUSET_ENUM_CONVERT( // + convert, parser::OmpGrainsizeClause::Prescriptiveness, Grainsize::Prescriptiveness, + // clang-format off + MS(Strict, Strict) + // clang-format on + ); + auto &t0 = std::get>(inp.v.t); + auto &t1 = std::get(inp.v.t); + return Grainsize{{/*Prescriptiveness=*/maybeApply(convert, t0), + /*Grainsize=*/makeExpr(t1, semaCtx)}}; } HasDeviceAddr make(const parser::OmpClause::HasDeviceAddr &inp, @@ -971,9 +981,20 @@ Novariants make(const parser::OmpClause::Novariants &inp, NumTasks make(const parser::OmpClause::NumTasks &inp, semantics::SemanticsContext &semaCtx) { - // inp.v -> parser::ScalarIntExpr - return NumTasks{{/*Prescriptiveness=*/std::nullopt, - /*NumTasks=*/makeExpr(inp.v, semaCtx)}}; + // inp.v -> parser::OmpNumTasksClause + using wrapped = parser::OmpNumTasksClause; + + CLAUSET_ENUM_CONVERT( // + convert, parser::OmpNumTasksClause::Prescriptiveness, + NumTasks::Prescriptiveness, + // clang-format off + MS(Strict, Strict) + // clang-format on + ); + auto &t0 = std::get>(inp.v.t); + auto &t1 = std::get(inp.v.t); + return NumTasks{{/*Prescriptiveness=*/maybeApply(convert, t0), + /*NumTasks=*/makeExpr(t1, semaCtx)}}; } NumTeams make(const parser::OmpClause::NumTeams &inp, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index e740c421ca802..ae0c351fed56d 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -408,6 +408,16 @@ TYPE_PARSER(construct( maybe(Parser{} / ":"), "CONCURRENT" >> pure(OmpOrderClause::Type::Concurrent))) +// OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression) +TYPE_PARSER(construct( + maybe("STRICT" >> pure(OmpGrainsizeClause::Prescriptiveness::Strict) / ":"), + scalarIntExpr)) + +// OMP 5.2 12.6.2 num_tasks([ prescriptiveness :] scalar-integer-expression) +TYPE_PARSER(construct( + maybe("STRICT" >> pure(OmpNumTasksClause::Prescriptiveness::Strict) / ":"), + scalarIntExpr)) + TYPE_PARSER( construct(designator) || construct("/" >> name / "/")) @@ -464,7 +474,7 @@ TYPE_PARSER( "FROM" >> construct(construct( parenthesized(Parser{}))) || "GRAINSIZE" >> construct(construct( - parenthesized(scalarIntExpr))) || + parenthesized(Parser{}))) || "HAS_DEVICE_ADDR" >> construct(construct( parenthesized(Parser{}))) || @@ -491,7 +501,7 @@ TYPE_PARSER( construct(construct()) || "NOWAIT" >> construct(construct()) || "NUM_TASKS" >> construct(construct( - parenthesized(scalarIntExpr))) || + parenthesized(Parser{}))) || "NUM_TEAMS" >> construct(construct( parenthesized(scalarIntExpr))) || "NUM_THREADS" >> construct(construct( diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 19ceb2a3ebc31..ba4155469073e 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2196,6 +2196,16 @@ class UnparseVisitor { Walk(std::get>(x.t), ":"); Walk(std::get(x.t)); } + void Unparse(const OmpGrainsizeClause &x) { + Walk(std::get>(x.t), + ":"); + Walk(std::get(x.t)); + } + void Unparse(const OmpNumTasksClause &x) { + Walk( + std::get>(x.t), ":"); + Walk(std::get(x.t)); + } void Unparse(const OmpDependSinkVecLength &x) { Walk(std::get(x.t)); Walk(std::get(x.t)); @@ -2829,6 +2839,9 @@ class UnparseVisitor { WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type WALK_NESTED_ENUM(OmpOrderClause, Type) // OMP order-type WALK_NESTED_ENUM(OmpOrderModifier, Kind) // OMP order-modifier + WALK_NESTED_ENUM( + OmpGrainsizeClause, Prescriptiveness) // OMP grainsize-modifier + WALK_NESTED_ENUM(OmpNumTasksClause, Prescriptiveness) // OMP numtasks-modifier WALK_NESTED_ENUM(OmpMapClause, Type) // OMP map-type WALK_NESTED_ENUM(OmpMapClause, TypeModifier) // OMP map-type-modifier #undef WALK_NESTED_ENUM diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 1c2cf304d0ee9..455322d610d6c 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -2479,12 +2479,14 @@ CHECK_SIMPLE_CLAUSE(Final, OMPC_final) CHECK_SIMPLE_CLAUSE(Flush, OMPC_flush) CHECK_SIMPLE_CLAUSE(From, OMPC_from) CHECK_SIMPLE_CLAUSE(Full, OMPC_full) +CHECK_SIMPLE_CLAUSE(Grainsize, OMPC_grainsize) CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint) CHECK_SIMPLE_CLAUSE(Holds, OMPC_holds) CHECK_SIMPLE_CLAUSE(InReduction, OMPC_in_reduction) CHECK_SIMPLE_CLAUSE(Inclusive, OMPC_inclusive) CHECK_SIMPLE_CLAUSE(Match, OMPC_match) CHECK_SIMPLE_CLAUSE(Nontemporal, OMPC_nontemporal) +CHECK_SIMPLE_CLAUSE(NumTasks, OMPC_num_tasks) CHECK_SIMPLE_CLAUSE(Order, OMPC_order) CHECK_SIMPLE_CLAUSE(Read, OMPC_read) CHECK_SIMPLE_CLAUSE(Threadprivate, OMPC_threadprivate) @@ -2535,8 +2537,6 @@ CHECK_SIMPLE_CLAUSE(OmpxBare, OMPC_ompx_bare) CHECK_SIMPLE_CLAUSE(Fail, OMPC_fail) CHECK_SIMPLE_CLAUSE(Weak, OMPC_weak) -CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize) -CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks) CHECK_REQ_SCALAR_INT_CLAUSE(NumTeams, OMPC_num_teams) CHECK_REQ_SCALAR_INT_CLAUSE(NumThreads, OMPC_num_threads) CHECK_REQ_SCALAR_INT_CLAUSE(OmpxDynCgroupMem, OMPC_ompx_dyn_cgroup_mem) diff --git a/flang/test/Parser/OpenMP/taskloop.f90 b/flang/test/Parser/OpenMP/taskloop.f90 new file mode 100644 index 0000000000000..a9c361046bd5f --- /dev/null +++ b/flang/test/Parser/OpenMP/taskloop.f90 @@ -0,0 +1,41 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine parallel_work + integer :: i + +!CHECK: !$OMP TASKLOOP GRAINSIZE(STRICT:500_4) +!PARSE-TREE: OmpBeginLoopDirective +!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop +!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Grainsize -> OmpGrainsizeClause +!PARSE-TREE-NEXT: Prescriptiveness = Strict +!PARSE-TREE-NEXT: Scalar -> Integer -> Expr = '500_4' + !$omp taskloop grainsize(strict: 500) + do i=1,10000 + call loop_body(i) + end do + !$omp end taskloop + +!CHECK: !$OMP TASKLOOP GRAINSIZE(500_4) +!PARSE-TREE: OmpBeginLoopDirective +!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop +!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> Grainsize -> OmpGrainsizeClause +!PARSE-TREE-NEXT: Scalar -> Integer -> Expr = '500_4' + !$omp taskloop grainsize(500) + do i=1,10000 + call loop_body(i) + end do + !$omp end taskloop + +!CHECK: !$OMP TASKLOOP NUM_TASKS(STRICT:500_4) +!PARSE-TREE: OmpBeginLoopDirective +!PARSE-TREE-NEXT: OmpLoopDirective -> llvm::omp::Directive = taskloop +!PARSE-TREE-NEXT: OmpClauseList -> OmpClause -> NumTasks -> OmpNumTasksClause +!PARSE-TREE-NEXT: Prescriptiveness = Strict +!PARSE-TREE-NEXT: Scalar -> Integer -> Expr = '500_4' + !$omp taskloop num_tasks(strict: 500) + do i=1,10000 + call loop_body(i) + end do + !$omp end taskloop +end subroutine parallel_work diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index d592f369a17f9..70179bab47577 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -185,10 +185,10 @@ def OMPC_Full: Clause<"full"> { let clangClass = "OMPFullClause"; } def OMP_GRAINSIZE_Strict : ClauseVal<"strict", 1, 1> {} -def OMP_GRAINSIZE_Unknown : ClauseVal<"unkonwn", 2, 0> { let isDefault = 1; } +def OMP_GRAINSIZE_Unknown : ClauseVal<"unknown", 2, 0> { let isDefault = 1; } def OMPC_GrainSize : Clause<"grainsize"> { let clangClass = "OMPGrainsizeClause"; - let flangClass = "ScalarIntExpr"; + let flangClass = "OmpGrainsizeClause"; let enumClauseValue = "GrainsizeType"; let allowedClauseValues = [ OMP_GRAINSIZE_Strict, @@ -301,10 +301,10 @@ def OMPC_NoWait : Clause<"nowait"> { let clangClass = "OMPNowaitClause"; } def OMP_NUMTASKS_Strict : ClauseVal<"strict", 1, 1> {} -def OMP_NUMTASKS_Unknown : ClauseVal<"unkonwn", 2, 0> { let isDefault = 1; } +def OMP_NUMTASKS_Unknown : ClauseVal<"unknown", 2, 0> { let isDefault = 1; } def OMPC_NumTasks : Clause<"num_tasks"> { let clangClass = "OMPNumTasksClause"; - let flangClass = "ScalarIntExpr"; + let flangClass = "OmpNumTasksClause"; let enumClauseValue = "NumTasksType"; let allowedClauseValues = [ OMP_NUMTASKS_Strict,