From ec1e0c5ecd53e415b23d5bd40b8e44e3ef4b4d92 Mon Sep 17 00:00:00 2001 From: Mats Petersson Date: Thu, 14 Nov 2024 09:35:34 +0000 Subject: [PATCH] [Flang][OMP]Add support for DECLARE MAPPER parsing and semantics (#115160) Will hit a TODO in the lowering, which there are tests added to check for this happening. --- flang/include/flang/Parser/dump-parse-tree.h | 2 + flang/include/flang/Parser/parse-tree.h | 20 ++++++-- flang/lib/Lower/OpenMP/OpenMP.cpp | 7 +++ flang/lib/Parser/openmp-parsers.cpp | 11 +++++ flang/lib/Parser/unparse.cpp | 16 +++++++ flang/lib/Semantics/check-omp-structure.cpp | 15 ++++++ flang/lib/Semantics/check-omp-structure.h | 2 + flang/lib/Semantics/resolve-directives.cpp | 8 ++++ flang/lib/Semantics/resolve-names.cpp | 34 ++++++++++++++ flang/lib/Semantics/unparse-with-symbols.cpp | 8 ++++ .../Lower/OpenMP/Todo/omp-declare-mapper.f90 | 47 +++++++++++++++++++ .../Parser/OpenMP/declare-mapper-unparse.f90 | 42 +++++++++++++++++ .../OpenMP/declare-mapper-symbols.f90 | 24 ++++++++++ .../Semantics/OpenMP/declare-mapper01.f90 | 8 ++++ .../Semantics/OpenMP/declare-mapper02.f90 | 10 ++++ .../Semantics/OpenMP/declare-mapper03.f90 | 16 +++++++ llvm/include/llvm/Frontend/OpenMP/OMP.td | 4 +- 17 files changed, 269 insertions(+), 5 deletions(-) create mode 100644 flang/test/Lower/OpenMP/Todo/omp-declare-mapper.f90 create mode 100644 flang/test/Parser/OpenMP/declare-mapper-unparse.f90 create mode 100644 flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 create mode 100644 flang/test/Semantics/OpenMP/declare-mapper01.f90 create mode 100644 flang/test/Semantics/OpenMP/declare-mapper02.f90 create mode 100644 flang/test/Semantics/OpenMP/declare-mapper03.f90 diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 2fb863738d62..5886e384b986 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -506,6 +506,7 @@ public: NODE(parser, OmpDeclareTargetSpecifier) NODE(parser, OmpDeclareTargetWithClause) NODE(parser, OmpDeclareTargetWithList) + NODE(parser, OmpDeclareMapperSpecifier) NODE(parser, OmpDefaultClause) NODE_ENUM(OmpDefaultClause, Type) NODE(parser, OmpDefaultmapClause) @@ -621,6 +622,7 @@ public: NODE(parser, OpenMPDeclareReductionConstruct) NODE(parser, OpenMPDeclareSimdConstruct) NODE(parser, OpenMPDeclareTargetConstruct) + NODE(parser, OpenMPDeclareMapperConstruct) NODE(parser, OmpMemoryOrderClause) NODE(parser, OmpAtomicClause) NODE(parser, OmpAtomicClauseList) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index c5963e920651..10d7840775e8 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3916,6 +3916,19 @@ struct OpenMPDeclareTargetConstruct { std::tuple t; }; +struct OmpDeclareMapperSpecifier { + TUPLE_CLASS_BOILERPLATE(OmpDeclareMapperSpecifier); + std::tuple, TypeSpec, Name> t; +}; + +// OMP v5.2: 5.8.8 +// declare-mapper -> DECLARE MAPPER ([mapper-name :] type :: var) map-clauses +struct OpenMPDeclareMapperConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPDeclareMapperConstruct); + CharBlock source; + std::tuple t; +}; + // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list // : combiner) [initializer-clause] struct OmpReductionCombiner { @@ -3966,9 +3979,10 @@ struct OpenMPDeclarativeAllocate { struct OpenMPDeclarativeConstruct { UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct); CharBlock source; - std::variant + std::variant u; }; diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 91f99ba4b0ca..d70b0f315269 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -2623,6 +2623,13 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct"); } +static void +genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, + const parser::OpenMPDeclareMapperConstruct &declareMapperConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPDeclareMapperConstruct"); +} + static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index ee6f8feb6657..c2c730edacc0 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -860,6 +860,15 @@ TYPE_PARSER( TYPE_PARSER(sourced(construct( verbatim("DECLARE TARGET"_tok), Parser{}))) +// declare-mapper-specifier +TYPE_PARSER(construct( + maybe(name / ":" / !":"_tok), typeSpec / "::", name)) + +// OpenMP 5.2: 5.8.8 Declare Mapper Construct +TYPE_PARSER(sourced(construct( + verbatim("DECLARE MAPPER"_tok), + "(" >> Parser{} / ")", Parser{}))) + TYPE_PARSER(construct(Parser{}) || construct( construct( @@ -968,6 +977,8 @@ TYPE_PARSER(startOmpLine >> withMessage("expected OpenMP construct"_err_en_US, sourced(construct( Parser{}) || + construct( + Parser{}) || construct( Parser{}) || construct( diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 4b511da69832..158d3a1f14e4 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2652,6 +2652,22 @@ public: EndOpenMP(); return false; }, + [&](const OpenMPDeclareMapperConstruct &z) { + Word("DECLARE MAPPER ("); + const auto &spec{std::get(z.t)}; + if (auto mapname{std::get>(spec.t)}) { + Walk(mapname); + Put(":"); + } + Walk(std::get(spec.t)); + Put("::"); + Walk(std::get(spec.t)); + Put(")"); + + Walk(std::get(z.t)); + Put("\n"); + return false; + }, [&](const OpenMPDeclareReductionConstruct &) { Word("DECLARE REDUCTION "); return true; diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 5fe72e6fd4fd..4414aec57688 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1472,6 +1472,21 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) { } } +void OmpStructureChecker::Enter(const parser::OpenMPDeclareMapperConstruct &x) { + const auto &dir{std::get(x.t)}; + PushContextAndClauseSets( + dir.source, llvm::omp::Directive::OMPD_declare_mapper); + const auto &spec{std::get(x.t)}; + const auto &type = std::get(spec.t); + if (!std::get_if(&type.u)) { + context_.Say(dir.source, "Type is not a derived type"_err_en_US); + } +} + +void OmpStructureChecker::Leave(const parser::OpenMPDeclareMapperConstruct &) { + dirContext_.pop_back(); +} + void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) { const auto &dir{std::get(x.t)}; PushContext(dir.source, llvm::omp::Directive::OMPD_declare_target); diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 0c5f97f743e2..eefa6f0eb650 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -93,6 +93,8 @@ public: void Leave(const parser::OpenMPDeclareSimdConstruct &); void Enter(const parser::OpenMPDeclarativeAllocate &); void Leave(const parser::OpenMPDeclarativeAllocate &); + void Enter(const parser::OpenMPDeclareMapperConstruct &); + void Leave(const parser::OpenMPDeclareMapperConstruct &); void Enter(const parser::OpenMPDeclareTargetConstruct &); void Leave(const parser::OpenMPDeclareTargetConstruct &); void Enter(const parser::OpenMPDepobjConstruct &); diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 83d666283a48..fa92ccc8e3a7 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -431,6 +431,9 @@ public: bool Pre(const parser::OpenMPDeclareTargetConstruct &); void Post(const parser::OpenMPDeclareTargetConstruct &) { PopContext(); } + bool Pre(const parser::OpenMPDeclareMapperConstruct &); + void Post(const parser::OpenMPDeclareMapperConstruct &) { PopContext(); } + bool Pre(const parser::OpenMPThreadprivate &); void Post(const parser::OpenMPThreadprivate &) { PopContext(); } @@ -1953,6 +1956,11 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) { return true; } +bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareMapperConstruct &x) { + PushContext(x.source, llvm::omp::Directive::OMPD_declare_mapper); + return true; +} + bool OmpAttributeVisitor::Pre(const parser::OpenMPThreadprivate &x) { PushContext(x.source, llvm::omp::Directive::OMPD_threadprivate); const auto &list{std::get(x.t)}; diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index e0a8246ebc75..9b0e204ac4e9 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1468,6 +1468,9 @@ public: AddOmpSourceRange(x.source); return true; } + + bool Pre(const parser::OpenMPDeclareMapperConstruct &); + void Post(const parser::OmpBeginLoopDirective &) { messageHandler().set_currStmtSource(std::nullopt); } @@ -1605,6 +1608,37 @@ void OmpVisitor::Post(const parser::OpenMPBlockConstruct &x) { } } +// This "manually" walks the tree of the construct, because we need +// to resolve the type before the map clauses are processed - when +// just following the natural flow, the map clauses gets processed before +// the type has been fully processed. +bool OmpVisitor::Pre(const parser::OpenMPDeclareMapperConstruct &x) { + AddOmpSourceRange(x.source); + BeginDeclTypeSpec(); + const auto &spec{std::get(x.t)}; + Symbol *mapperSym{nullptr}; + if (const auto &mapperName{std::get>(spec.t)}) { + mapperSym = + &MakeSymbol(*mapperName, MiscDetails{MiscDetails::Kind::ConstructName}); + mapperName->symbol = mapperSym; + } else { + const parser::CharBlock defaultName{"default", 7}; + mapperSym = &MakeSymbol( + defaultName, Attrs{}, MiscDetails{MiscDetails::Kind::ConstructName}); + } + + PushScope(Scope::Kind::OtherConstruct, nullptr); + Walk(std::get(spec.t)); + const auto &varName{std::get(spec.t)}; + DeclareObjectEntity(varName); + + Walk(std::get(x.t)); + + EndDeclTypeSpec(); + PopScope(); + return false; +} + // Walk the parse tree and resolve names to symbols. class ResolveNamesVisitor : public virtual ScopeHandler, public ModuleVisitor, diff --git a/flang/lib/Semantics/unparse-with-symbols.cpp b/flang/lib/Semantics/unparse-with-symbols.cpp index c451f885c062..02afb89ae57f 100644 --- a/flang/lib/Semantics/unparse-with-symbols.cpp +++ b/flang/lib/Semantics/unparse-with-symbols.cpp @@ -53,6 +53,14 @@ public: void Post(const parser::OpenMPThreadprivate &) { currStmt_ = std::nullopt; } void Post(const parser::Name &name); + bool Pre(const parser::OpenMPDeclareMapperConstruct &x) { + currStmt_ = x.source; + return true; + } + void Post(const parser::OpenMPDeclareMapperConstruct &) { + currStmt_ = std::nullopt; + } + private: std::optional currStmt_; // current statement we are processing std::multimap symbols_; // location to symbol diff --git a/flang/test/Lower/OpenMP/Todo/omp-declare-mapper.f90 b/flang/test/Lower/OpenMP/Todo/omp-declare-mapper.f90 new file mode 100644 index 000000000000..5ae48ff73604 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/omp-declare-mapper.f90 @@ -0,0 +1,47 @@ +! This test checks lowering of OpenMP declare mapper Directive. + +! RUN: split-file %s %t +! RUN: not %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-1.f90 2>&1 | FileCheck %t/omp-declare-mapper-1.f90 +! RUN not %flang_fc1 -emit-fir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-2.f90 2>&1 | FileCheck %t/omp-declare-mapper-2.f90 + +!--- omp-declare-mapper-1.f90 +subroutine declare_mapper_1 + integer,parameter :: nvals = 250 + type my_type + integer :: num_vals + integer, allocatable :: values(:) + end type + + type my_type2 + type (my_type) :: my_type_var + type (my_type) :: temp + real,dimension(nvals) :: unmapped + real,dimension(nvals) :: arr + end type + type (my_type2) :: t + real :: x, y(nvals) + !$omp declare mapper (my_type :: var) map (var, var%values (1:var%num_vals)) +!CHECK: not yet implemented: OpenMPDeclareMapperConstruct +end subroutine declare_mapper_1 + + +!--- omp-declare-mapper-2.f90 +subroutine declare_mapper_2 + integer,parameter :: nvals = 250 + type my_type + integer :: num_vals + integer, allocatable :: values(:) + end type + + type my_type2 + type (my_type) :: my_type_var + type (my_type) :: temp + real,dimension(nvals) :: unmapped + real,dimension(nvals) :: arr + end type + type (my_type2) :: t + real :: x, y(nvals) + !$omp declare mapper (my_mapper : my_type2 :: v) map (v%arr, x, y(:)) & + !$omp& map (alloc : v%temp) +!CHECK: not yet implemented: OpenMPDeclareMapperConstruct +end subroutine declare_mapper_2 diff --git a/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 new file mode 100644 index 000000000000..5ba147d20955 --- /dev/null +++ b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 @@ -0,0 +1,42 @@ +! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s +program main +!CHECK-LABEL: program main + implicit none + + type ty + integer :: x + end type ty + + +!CHECK: !$OMP DECLARE MAPPER (mymapper:ty::mapped) MAP(mapped,mapped%x) + !$omp declare mapper(mymapper : ty :: mapped) map(mapped, mapped%x) + +!PARSE-TREE: OpenMPDeclareMapperConstruct +!PARSE-TREE: OmpDeclareMapperSpecifier +!PARSE-TREE: Name = 'mymapper' +!PARSE-TREE: TypeSpec -> DerivedTypeSpec +!PARSE-TREE: Name = 'ty' +!PARSE-TREE: Name = 'mapped' +!PARSE-TREE: OmpMapClause +!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'mapped' +!PARSE-TREE: OmpObject -> Designator -> DataRef -> StructureComponent +!PARSE-TREE: DataRef -> Name = 'mapped' +!PARSE-TREE: Name = 'x' + +!CHECK: !$OMP DECLARE MAPPER (ty::mapped) MAP(mapped,mapped%x) + !$omp declare mapper(ty :: mapped) map(mapped, mapped%x) + +!PARSE-TREE: OpenMPDeclareMapperConstruct +!PARSE-TREE: OmpDeclareMapperSpecifier +!PARSE-TREE: TypeSpec -> DerivedTypeSpec +!PARSE-TREE: Name = 'ty' +!PARSE-TREE: Name = 'mapped' +!PARSE-TREE: OmpMapClause +!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'mapped' +!PARSE-TREE: OmpObject -> Designator -> DataRef -> StructureComponent +!PARSE-TREE: DataRef -> Name = 'mapped' +!PARSE-TREE: Name = 'x' + +end program main +!CHECK-LABEL: end program main diff --git a/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 new file mode 100644 index 000000000000..b4e03bd1632e --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper-symbols.f90 @@ -0,0 +1,24 @@ +! RUN: %flang_fc1 -fdebug-dump-symbols -fopenmp -fopenmp-version=50 %s | FileCheck %s + +program main +!CHECK-LABEL: MainProgram scope: main + implicit none + + type ty + integer :: x + end type ty + !$omp declare mapper(mymapper : ty :: mapped) map(mapped, mapped%x) + !$omp declare mapper(ty :: maptwo) map(maptwo, maptwo%x) + +!! Note, symbols come out in their respective scope, but not in declaration order. +!CHECK: default: Misc ConstructName +!CHECK: mymapper: Misc ConstructName +!CHECK: ty: DerivedType components: x +!CHECK: DerivedType scope: ty +!CHECK: OtherConstruct scope: +!CHECK: mapped (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty) +!CHECK: OtherConstruct scope: +!CHECK: maptwo (OmpMapToFrom) {{.*}} ObjectEntity type: TYPE(ty) + +end program main + diff --git a/flang/test/Semantics/OpenMP/declare-mapper01.f90 b/flang/test/Semantics/OpenMP/declare-mapper01.f90 new file mode 100644 index 000000000000..0712b80769a4 --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper01.f90 @@ -0,0 +1,8 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 +! Test the declare mapper with non-derived type. + +integer :: y + +!ERROR: Type is not a derived type +!$omp declare mapper(mm : integer::x) map(x, y) +end diff --git a/flang/test/Semantics/OpenMP/declare-mapper02.f90 b/flang/test/Semantics/OpenMP/declare-mapper02.f90 new file mode 100644 index 000000000000..a62a7f8d0a39 --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper02.f90 @@ -0,0 +1,10 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 +! Test the declare mapper construct with abstract type. + +type, abstract :: t1 + integer :: y +end type t1 + +!ERROR: ABSTRACT derived type may not be used here +!$omp declare mapper(mm : t1::x) map(x, x%y) +end diff --git a/flang/test/Semantics/OpenMP/declare-mapper03.f90 b/flang/test/Semantics/OpenMP/declare-mapper03.f90 new file mode 100644 index 000000000000..b70b8a67f33e --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper03.f90 @@ -0,0 +1,16 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=50 +! Test the declare mapper construct with two default mappers. + +type :: t1 + integer :: y +end type t1 + +type :: t2 + real :: y, z +end type t2 + +!error: 'default' is already declared in this scoping unit + +!$omp declare mapper(t1::x) map(x, x%y) +!$omp declare mapper(t2::w) map(w, w%y, w%z) +end diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index fa96c3f367f0..12f51035656a 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -625,8 +625,8 @@ def OMP_Critical : Directive<"critical"> { let category = CA_Executable; } def OMP_DeclareMapper : Directive<"declare mapper"> { - let allowedClauses = [ - VersionedClause, + let requiredClauses = [ + VersionedClause, ]; let association = AS_None; let category = CA_Declarative;