diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 10d7840775e88..8f50809599a58 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3544,7 +3544,7 @@ struct OmpDefaultmapClause { TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause); ENUM_CLASS( ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default) - ENUM_CLASS(VariableCategory, Scalar, Aggregate, Allocatable, Pointer) + ENUM_CLASS(VariableCategory, All, Scalar, Aggregate, Allocatable, Pointer) std::tuple> t; }; diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index 3dedd4864bafc..5879fbe619312 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -561,17 +561,20 @@ Defaultmap make(const parser::OmpClause::Defaultmap &inp, CLAUSET_ENUM_CONVERT( // convert2, wrapped::VariableCategory, Defaultmap::VariableCategory, // clang-format off - MS(Scalar, Scalar) MS(Aggregate, Aggregate) - MS(Pointer, Pointer) + MS(All, All) MS(Allocatable, Allocatable) + MS(Pointer, Pointer) + MS(Scalar, Scalar) // clang-format on ); auto &t0 = std::get(inp.v.t); auto &t1 = std::get>(inp.v.t); + + auto category = t1 ? convert2(*t1) : Defaultmap::VariableCategory::All; return Defaultmap{{/*ImplicitBehavior=*/convert1(t0), - /*VariableCategory=*/maybeApply(convert2, t1)}}; + /*VariableCategory=*/category}}; } Doacross makeDoacross(const parser::OmpDoacross &doa, diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 970e0db35c76f..e445bb10a3456 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -30,6 +30,7 @@ #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/HLFIR/HLFIROps.h" +#include "flang/Parser/characters.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/openmp-directive-sets.h" #include "flang/Semantics/tools.h" @@ -2881,7 +2882,9 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, !std::holds_alternative(clause.u) && !std::holds_alternative(clause.u) && !std::holds_alternative(clause.u)) { - TODO(clauseLocation, "OpenMP Block construct clause"); + std::string name = + parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(clause.id)); + TODO(clauseLocation, name + " clause is not implemented yet"); } } diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 0c6bb54e48840..5ead9a48fa896 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -270,7 +270,7 @@ TYPE_PARSER(construct( // 2.19.7.2 defaultmap(implicit-behavior[:variable-category]) // implicit-behavior -> ALLOC | TO | FROM | TOFROM | FIRSRTPRIVATE | NONE | // DEFAULT -// variable-category -> SCALAR | AGGREGATE | ALLOCATABLE | POINTER +// variable-category -> ALL | SCALAR | AGGREGATE | ALLOCATABLE | POINTER TYPE_PARSER(construct( construct( "ALLOC" >> pure(OmpDefaultmapClause::ImplicitBehavior::Alloc) || @@ -283,6 +283,7 @@ TYPE_PARSER(construct( "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)), maybe(":" >> construct( + "ALL"_id >> pure(OmpDefaultmapClause::VariableCategory::All) || "SCALAR" >> pure(OmpDefaultmapClause::VariableCategory::Scalar) || "AGGREGATE" >> pure(OmpDefaultmapClause::VariableCategory::Aggregate) || diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 3b03eab943422..0b64a4a9801cc 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -3333,14 +3333,17 @@ void OmpStructureChecker::Leave(const parser::OmpAtomicRead &) { CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_read, {llvm::omp::Clause::OMPC_release, llvm::omp::Clause::OMPC_acq_rel}); } + void OmpStructureChecker::Leave(const parser::OmpAtomicWrite &) { CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_write, {llvm::omp::Clause::OMPC_acquire, llvm::omp::Clause::OMPC_acq_rel}); } + void OmpStructureChecker::Leave(const parser::OmpAtomicUpdate &) { CheckNotAllowedIfClause(llvm::omp::Clause::OMPC_update, {llvm::omp::Clause::OMPC_acquire, llvm::omp::Clause::OMPC_acq_rel}); } + // OmpAtomic node represents atomic directive without atomic-clause. // atomic-clause - READ,WRITE,UPDATE,CAPTURE. void OmpStructureChecker::Leave(const parser::OmpAtomic &) { @@ -3353,6 +3356,7 @@ void OmpStructureChecker::Leave(const parser::OmpAtomic &) { "Clause ACQ_REL is not allowed on the ATOMIC directive"_err_en_US); } } + // Restrictions specific to each clause are implemented apart from the // generalized restrictions. void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) { @@ -3364,15 +3368,48 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) { } // 2.8.1 TODO: list-item attribute check } + void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_defaultmap); + unsigned version{context_.langOptions().OpenMPVersion}; + using ImplicitBehavior = parser::OmpDefaultmapClause::ImplicitBehavior; + auto behavior{std::get(x.v.t)}; + if (version <= 45) { + if (behavior != ImplicitBehavior::Tofrom) { + context_.Say(GetContext().clauseSource, + "%s is not allowed in %s, %s"_warn_en_US, + parser::ToUpperCaseLetters( + parser::OmpDefaultmapClause::EnumToString(behavior)), + ThisVersion(version), TryVersion(50)); + } + } using VariableCategory = parser::OmpDefaultmapClause::VariableCategory; - if (!std::get>(x.v.t)) { - context_.Say(GetContext().clauseSource, - "The argument TOFROM:SCALAR must be specified on the DEFAULTMAP " - "clause"_err_en_US); + auto maybeCategory{std::get>(x.v.t)}; + if (!maybeCategory) { + if (version <= 45) { + context_.Say(GetContext().clauseSource, + "The DEFAULTMAP clause requires a variable-category SCALAR in %s, %s"_warn_en_US, + ThisVersion(version), TryVersion(50)); + } + } else { + VariableCategory category{*maybeCategory}; + unsigned tryVersion{0}; + if (version <= 45 && category != VariableCategory::Scalar) { + tryVersion = 50; + } + if (version < 52 && category == VariableCategory::All) { + tryVersion = 52; + } + if (tryVersion) { + context_.Say(GetContext().clauseSource, + "%s is not allowed in %s, %s"_warn_en_US, + parser::ToUpperCaseLetters( + parser::OmpDefaultmapClause::EnumToString(category)), + ThisVersion(version), TryVersion(tryVersion)); + } } } + void OmpStructureChecker::Enter(const parser::OmpClause::If &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_if); using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier; diff --git a/flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90 b/flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90 new file mode 100644 index 0000000000000..062399d9a1944 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/defaultmap-clause.f90 @@ -0,0 +1,8 @@ +!RUN: %not_todo_cmd bbc -emit-hlfir -fopenmp -fopenmp-version=45 -o - %s 2>&1 | FileCheck %s +!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=45 -o - %s 2>&1 | FileCheck %s + +!CHECK: not yet implemented: DEFAULTMAP clause is not implemented yet +subroutine f00 + !$omp target defaultmap(tofrom:scalar) + !$omp end target +end diff --git a/flang/test/Lower/OpenMP/Todo/task_detach.f90 b/flang/test/Lower/OpenMP/Todo/task_detach.f90 index 6bc55e9e7cf64..cb6943073d4b3 100644 --- a/flang/test/Lower/OpenMP/Todo/task_detach.f90 +++ b/flang/test/Lower/OpenMP/Todo/task_detach.f90 @@ -6,7 +6,7 @@ ! `detach` clause !=============================================================================== -! CHECK: not yet implemented: OpenMP Block construct clause +! CHECK: not yet implemented: DETACH clause is not implemented yet subroutine omp_task_detach() use omp_lib integer (kind=omp_event_handle_kind) :: event diff --git a/flang/test/Lower/OpenMP/Todo/task_untied.f90 b/flang/test/Lower/OpenMP/Todo/task_untied.f90 index 19621c7aac16d..87d242ba3e9d2 100644 --- a/flang/test/Lower/OpenMP/Todo/task_untied.f90 +++ b/flang/test/Lower/OpenMP/Todo/task_untied.f90 @@ -5,7 +5,7 @@ ! `untied` clause !=============================================================================== -! CHECK: not yet implemented: OpenMP Block construct clause +! CHECK: not yet implemented: UNTIED clause is not implemented yet subroutine omp_task_untied() !$omp task untied call foo() diff --git a/flang/test/Parser/OpenMP/defaultmap-clause.f90 b/flang/test/Parser/OpenMP/defaultmap-clause.f90 new file mode 100644 index 0000000000000..6f018ffe8561c --- /dev/null +++ b/flang/test/Parser/OpenMP/defaultmap-clause.f90 @@ -0,0 +1,84 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=52 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine f00 + !$omp target defaultmap(from) + !$omp end target +end + +!UNPARSE: SUBROUTINE f00 +!UNPARSE: !$OMP TARGET DEFAULTMAP(FROM) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = From +!PARSE-TREE: Block + +subroutine f01 + !$omp target defaultmap(firstprivate: aggregate) + !$omp end target +end + +!UNPARSE: SUBROUTINE f01 +!UNPARSE: !$OMP TARGET DEFAULTMAP(FIRSTPRIVATE:AGGREGATE) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = Firstprivate +!PARSE-TREE: | | VariableCategory = Aggregate + +subroutine f02 + !$omp target defaultmap(alloc: all) + !$omp end target +end + +!UNPARSE: SUBROUTINE f02 +!UNPARSE: !$OMP TARGET DEFAULTMAP(ALLOC:ALL) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = Alloc +!PARSE-TREE: | | VariableCategory = All + +! Both "all" and "allocatable" are valid, and "all" is a prefix of +! "allocatable". Make sure we parse this correctly. +subroutine f03 + !$omp target defaultmap(alloc: allocatable) + !$omp end target +end + +!UNPARSE: SUBROUTINE f03 +!UNPARSE: !$OMP TARGET DEFAULTMAP(ALLOC:ALLOCATABLE) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = Alloc +!PARSE-TREE: | | VariableCategory = Allocatable + +subroutine f04 + !$omp target defaultmap(tofrom: scalar) + !$omp end target +end + +!UNPARSE: SUBROUTINE f04 +!UNPARSE: !$OMP TARGET DEFAULTMAP(TOFROM:SCALAR) +!UNPARSE: !$OMP END TARGET +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OmpBeginBlockDirective +!PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target +!PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause +!PARSE-TREE: | | ImplicitBehavior = Tofrom +!PARSE-TREE: | | VariableCategory = Scalar diff --git a/flang/test/Semantics/OpenMP/combined-constructs.f90 b/flang/test/Semantics/OpenMP/combined-constructs.f90 index b7a3848215930..38b0d090e441d 100644 --- a/flang/test/Semantics/OpenMP/combined-constructs.f90 +++ b/flang/test/Semantics/OpenMP/combined-constructs.f90 @@ -33,7 +33,7 @@ program main enddo !$omp end target parallel - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target parallel defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -80,7 +80,7 @@ program main enddo !$omp end target parallel do - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target parallel do defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -140,7 +140,7 @@ program main enddo !$omp end target teams - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target teams defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -240,7 +240,7 @@ program main enddo !$omp end target teams distribute - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target teams distribute defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -333,7 +333,7 @@ program main enddo !$omp end target teams distribute parallel do - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target teams distribute parallel do defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -433,7 +433,7 @@ program main enddo !$omp end target teams distribute parallel do simd - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause + !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 !$omp target teams distribute parallel do simd defaultmap(tofrom) do i = 1, N a(i) = 3.14 diff --git a/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 b/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 new file mode 100644 index 0000000000000..a30d90ddce029 --- /dev/null +++ b/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 @@ -0,0 +1,34 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror + +subroutine f00 +!WARNING: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v4.5, try -fopenmp-version=50 + !$omp target defaultmap(tofrom) + !$omp end target +end + +subroutine f01 +!WARNING: AGGREGATE is not allowed in OpenMP v4.5, try -fopenmp-version=50 + !$omp target defaultmap(tofrom:aggregate) + !$omp end target +end + +subroutine f02 +!WARNING: FROM is not allowed in OpenMP v4.5, try -fopenmp-version=50 + !$omp target defaultmap(from:scalar) + !$omp end target +end + +subroutine f03 +!WARNING: ALL is not allowed in OpenMP v4.5, try -fopenmp-version=52 + !$omp target defaultmap(tofrom:all) + !$omp end target +end + +subroutine f04 +!WARNING: FROM is not allowed in OpenMP v4.5, try -fopenmp-version=50 +!WARNING: POINTER is not allowed in OpenMP v4.5, try -fopenmp-version=50 + !$omp target defaultmap(from:pointer) + !$omp end target +end + + diff --git a/flang/test/Semantics/OpenMP/defaultmap-clause-v50.f90 b/flang/test/Semantics/OpenMP/defaultmap-clause-v50.f90 new file mode 100644 index 0000000000000..57bb207bb797a --- /dev/null +++ b/flang/test/Semantics/OpenMP/defaultmap-clause-v50.f90 @@ -0,0 +1,23 @@ +!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 -Werror + +subroutine f00 + !$omp target defaultmap(tofrom) + !$omp end target +end + +subroutine f01 + !$omp target defaultmap(tofrom:aggregate) + !$omp end target +end + +subroutine f02 + !$omp target defaultmap(from:scalar) + !$omp end target +end + +subroutine f03 +!WARNING: ALL is not allowed in OpenMP v5.0, try -fopenmp-version=52 + !$omp target defaultmap(tofrom:all) + !$omp end target +end + diff --git a/flang/test/Semantics/OpenMP/device-constructs.f90 b/flang/test/Semantics/OpenMP/device-constructs.f90 index 4047fbf3fa811..6f545b9021966 100644 --- a/flang/test/Semantics/OpenMP/device-constructs.f90 +++ b/flang/test/Semantics/OpenMP/device-constructs.f90 @@ -44,7 +44,6 @@ program main enddo !$omp end target - !ERROR: The argument TOFROM:SCALAR must be specified on the DEFAULTMAP clause !$omp target defaultmap(tofrom) do i = 1, N a = 3.14 diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h index f4e089db0080e..ce09bb5f730a7 100644 --- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h +++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h @@ -490,7 +490,7 @@ template // struct DefaultmapT { ENUM(ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default, Present); - ENUM(VariableCategory, Scalar, Aggregate, Pointer, Allocatable); + ENUM(VariableCategory, All, Scalar, Aggregate, Pointer, Allocatable); using TupleTrait = std::true_type; std::tuple t; };