From 203270a0a9fbe53d97a589d89bc5dd28d687bd45 Mon Sep 17 00:00:00 2001 From: Mats Petersson Date: Fri, 20 Dec 2024 19:42:14 +0000 Subject: [PATCH 1/2] [FLANG][OpenMP]Add support for ALIGN clause on OMP ALLOCATE This is trivially additional support for the existing ALLOCATE directive, which allows an ALIGN clause. The ALLOCATE directive is currently not implemented, so this is just addding the necessary parser parts to allow the compiler to not say "Huh? I don't get this" [or "Expected OpenMP construct"] when it encounters the ALIGN clause. Some parser testing is updated and a new todo test, just in case the feature of align clause is not supported by the initial support for ALLOCATE. --- flang/include/flang/Parser/dump-parse-tree.h | 1 + flang/include/flang/Parser/parse-tree.h | 5 ++++ flang/lib/Parser/openmp-parsers.cpp | 4 +++ .../Todo/omp-declarative-allocate-align.f90 | 10 +++++++ .../Parser/OpenMP/allocate-align-tree.f90 | 30 +++++++++++++++++++ flang/test/Parser/OpenMP/allocate-unparse.f90 | 4 ++- llvm/include/llvm/Frontend/OpenMP/OMP.td | 1 + 7 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 flang/test/Lower/OpenMP/Todo/omp-declarative-allocate-align.f90 create mode 100644 flang/test/Parser/OpenMP/allocate-align-tree.f90 diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 940caaeea9c3b..485e021ac39e9 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -486,6 +486,7 @@ class ParseTreeDumper { NODE(parser, OmpAffinityClause) NODE(OmpAffinityClause, Modifier) NODE(parser, OmpAlignment) + NODE(parser, OmpAlignClause) NODE(parser, OmpAlignedClause) NODE(OmpAlignedClause, Modifier) NODE(parser, OmpAtClause) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 1d97126d17dbc..3c494fa5290a9 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3752,6 +3752,11 @@ struct OmpAffinityClause { std::tuple t; }; +// Ref: 5.2: [174] +struct OmpAlignClause { + WRAPPER_CLASS_BOILERPLATE(OmpAlignClause, ScalarIntExpr); +}; + // Ref: [4.5:72-81], [5.0:110-119], [5.1:134-143], [5.2:169-170] // // aligned-clause -> diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 67385c03f66c8..2c739378989dc 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -567,6 +567,8 @@ TYPE_PARSER(construct( "TEAMS" >> pure(OmpBindClause::Binding::Teams) || "THREAD" >> pure(OmpBindClause::Binding::Thread))) +TYPE_PARSER(construct(scalarIntExpr)) + TYPE_PARSER(construct( "EXECUTION" >> pure(OmpAtClause::ActionTime::Execution) || "COMPILATION" >> pure(OmpAtClause::ActionTime::Compilation))) @@ -582,6 +584,8 @@ TYPE_PARSER( "ACQ_REL" >> construct(construct()) || "AFFINITY" >> construct(construct( parenthesized(Parser{}))) || + "ALIGN" >> construct(construct( + parenthesized(Parser{}))) || "ALIGNED" >> construct(construct( parenthesized(Parser{}))) || "ALLOCATE" >> construct(construct( diff --git a/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate-align.f90 b/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate-align.f90 new file mode 100644 index 0000000000000..d0ed0cbb4c831 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/omp-declarative-allocate-align.f90 @@ -0,0 +1,10 @@ +! This test checks lowering of OpenMP allocate Directive with align clause. + +// RUN: not flang -fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s + +program main + integer :: x + + // CHECK: not yet implemented: OpenMPDeclarativeAllocate + !$omp allocate(x) align(32) +end diff --git a/flang/test/Parser/OpenMP/allocate-align-tree.f90 b/flang/test/Parser/OpenMP/allocate-align-tree.f90 new file mode 100644 index 0000000000000..7ff76ea30e2f2 --- /dev/null +++ b/flang/test/Parser/OpenMP/allocate-align-tree.f90 @@ -0,0 +1,30 @@ +! REQUIRES: openmp_runtime + +! RUN: %flang_fc1 %openmp_flags -fopenmp-version=51 -fdebug-dump-parse-tree %s | FileCheck %s +! RUN: %flang_fc1 %openmp_flags -fdebug-unparse -fopenmp-version=51 %s | FileCheck %s --check-prefix="UNPARSE" +! Ensures associated declarative OMP allocations are nested in their +! corresponding executable allocate directive + +program allocate_tree + use omp_lib + integer, allocatable :: j +!$omp allocate(j) align(16) + allocate(j) +end program allocate_tree + +!CHECK: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt +!CHECK-NEXT: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!CHECK-NEXT: | | | AttrSpec -> Allocatable +!CHECK-NEXT: | | | EntityDecl +!CHECK-NEXT: | | | | Name = 'j' + + +!CHECK: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPExecutableAllocate +!CHECK-NEXT: | | | Verbatim +!CHECK-NEXT: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j' +!CHECK-NEXT: | | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Expr = '16_4' +!CHECK-NEXT: | | | | LiteralConstant -> IntLiteralConstant = '16' +!CHECK-NEXT: | | | AllocateStmt + +!UNPARSE: !$OMP ALLOCATE (j) ALIGN(16_4) +!UNPARSE-NEXT: ALLOCATE(j) diff --git a/flang/test/Parser/OpenMP/allocate-unparse.f90 b/flang/test/Parser/OpenMP/allocate-unparse.f90 index 81b3677ad954b..94bc2adf35ea9 100644 --- a/flang/test/Parser/OpenMP/allocate-unparse.f90 +++ b/flang/test/Parser/OpenMP/allocate-unparse.f90 @@ -5,7 +5,7 @@ program allocate_unparse use omp_lib real, dimension (:,:), allocatable :: darray -integer :: a, b, m, n, t, x, y, z +integer :: a, b, j, m, n, t, x, y, z ! 2.11.3 declarative allocate @@ -25,6 +25,7 @@ program allocate_unparse !$omp allocate(z) allocator(omp_default_mem_alloc) !$omp allocate(m) allocator(omp_default_mem_alloc) !$omp allocate(n) +!$omp allocate(j) align(16) allocate ( darray(z, t) ) end program allocate_unparse @@ -41,4 +42,5 @@ end program allocate_unparse !CHECK:!$OMP ALLOCATE (z) ALLOCATOR(omp_default_mem_alloc) !CHECK:!$OMP ALLOCATE (m) ALLOCATOR(omp_default_mem_alloc) !CHECK:!$OMP ALLOCATE (n) +!CHECK:!$OMP ALLOCATE (j) ALIGN(16) !CHECK:ALLOCATE(darray(z,t)) diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index e36eb77cefe7e..a4c1964c3e88f 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -49,6 +49,7 @@ def OMPC_Affinity : Clause<"affinity"> { } def OMPC_Align : Clause<"align"> { let clangClass = "OMPAlignClause"; + let flangClass = "OmpAlignClause"; } def OMPC_Aligned : Clause<"aligned"> { let clangClass = "OMPAlignedClause"; From 8e758086b3ae0d3cd83045b936903d52f48c58b6 Mon Sep 17 00:00:00 2001 From: Mats Petersson Date: Fri, 3 Jan 2025 18:37:20 +0000 Subject: [PATCH 2/2] Add semantic check for align clause --- flang/lib/Semantics/check-omp-structure.cpp | 17 +++++++++++ flang/lib/Semantics/check-omp-structure.h | 2 ++ .../Parser/OpenMP/allocate-align-tree.f90 | 30 +++++++++++++------ .../Semantics/OpenMP/allocate-align01.f90 | 20 +++++++++++++ 4 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 flang/test/Semantics/OpenMP/allocate-align01.f90 diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 414753305a6e3..8fc4fe8103706 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1483,11 +1483,24 @@ void OmpStructureChecker::Leave(const parser::OpenMPRequiresConstruct &) { dirContext_.pop_back(); } +void OmpStructureChecker::CheckAlignValue(const parser::OmpClause &clause) { + if (auto *align{std::get_if(&clause.u)}) { + if (const auto &v{GetIntValue(align->v)}; !v || *v <= 0) { + context_.Say(clause.source, + "The alignment value should be a constant positive integer"_err_en_US); + } + } +} + void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) { isPredefinedAllocator = true; const auto &dir{std::get(x.t)}; const auto &objectList{std::get(x.t)}; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate); + const auto &clauseList{std::get(x.t)}; + for (const auto &clause : clauseList.v) { + CheckAlignValue(clause); + } CheckIsVarPartOfAnotherVar(dir.source, objectList); } @@ -1704,6 +1717,10 @@ void OmpStructureChecker::Enter(const parser::OpenMPExecutableAllocate &x) { const auto &dir{std::get(x.t)}; const auto &objectList{std::get>(x.t)}; PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate); + const auto &clauseList{std::get(x.t)}; + for (const auto &clause : clauseList.v) { + CheckAlignValue(clause); + } if (objectList) { CheckIsVarPartOfAnotherVar(dir.source, *objectList); } diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 346a7bed9138f..adbd9ab73c205 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -261,6 +261,8 @@ class OmpStructureChecker void CheckAllowedRequiresClause(llvmOmpClause clause); bool deviceConstructFound_{false}; + void CheckAlignValue(const parser::OmpClause &); + void EnterDirectiveNest(const int index) { directiveNest_[index]++; } void ExitDirectiveNest(const int index) { directiveNest_[index]--; } int GetDirectiveNest(const int index) { return directiveNest_[index]; } diff --git a/flang/test/Parser/OpenMP/allocate-align-tree.f90 b/flang/test/Parser/OpenMP/allocate-align-tree.f90 index 7ff76ea30e2f2..8cb009dfe46c8 100644 --- a/flang/test/Parser/OpenMP/allocate-align-tree.f90 +++ b/flang/test/Parser/OpenMP/allocate-align-tree.f90 @@ -5,12 +5,16 @@ ! Ensures associated declarative OMP allocations are nested in their ! corresponding executable allocate directive -program allocate_tree +program allocate_align_tree use omp_lib - integer, allocatable :: j -!$omp allocate(j) align(16) - allocate(j) -end program allocate_tree + integer, allocatable :: j(:), xarray(:) + integer :: z, t + t = 2 + z = 3 +!$omp allocate(j) align(16) +!$omp allocate(xarray) align(32) allocator(omp_large_cap_mem_alloc) + allocate(j(z), xarray(t)) +end program allocate_align_tree !CHECK: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt !CHECK-NEXT: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> @@ -21,10 +25,18 @@ end program allocate_tree !CHECK: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPExecutableAllocate !CHECK-NEXT: | | | Verbatim -!CHECK-NEXT: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j' -!CHECK-NEXT: | | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Expr = '16_4' -!CHECK-NEXT: | | | | LiteralConstant -> IntLiteralConstant = '16' +!CHECK-NEXT: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'xarray' +!CHECK-NEXT: | | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Expr = '32_4' +!CHECK-NEXT: | | | | LiteralConstant -> IntLiteralConstant = '32' +!CHECK-NEXT: | | | OmpClause -> Allocator -> Scalar -> Integer -> Expr = '2_8' +!CHECK-NEXT: | | | | Designator -> DataRef -> Name = 'omp_large_cap_mem_alloc' +!CHECK-NEXT: | | | OpenMPDeclarativeAllocate +!CHECK-NEXT: | | | | Verbatim +!CHECK-NEXT: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j' +!CHECK-NEXT: | | | | OmpClauseList -> OmpClause -> Align -> OmpAlignClause -> Scalar -> Integer -> Expr = '16_4' +!CHECK-NEXT: | | | | | LiteralConstant -> IntLiteralConstant = '16' !CHECK-NEXT: | | | AllocateStmt !UNPARSE: !$OMP ALLOCATE (j) ALIGN(16_4) -!UNPARSE-NEXT: ALLOCATE(j) +!UNPARSE: !$OMP ALLOCATE (xarray) ALIGN(32_4) ALLOCATOR(2_8) +!UNPARSE-NEXT: ALLOCATE(j(z), xarray(t)) diff --git a/flang/test/Semantics/OpenMP/allocate-align01.f90 b/flang/test/Semantics/OpenMP/allocate-align01.f90 new file mode 100644 index 0000000000000..ba0776cf46a6d --- /dev/null +++ b/flang/test/Semantics/OpenMP/allocate-align01.f90 @@ -0,0 +1,20 @@ +! REQUIRES: openmp_runtime + +! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=51 +! OpenMP Version 5.2 +! The allocate clause's allocator modifier must be of type allocator_handle +! and the align modifier must be constant, positive integer expression + +program allocate_align_tree + use omp_lib + integer, allocatable :: j(:), xarray(:) + integer :: z, t, xx + t = 2 + z = 3 + !ERROR: The alignment value should be a constant positive integer +!$omp allocate(j) align(xx) + !ERROR: The alignment value should be a constant positive integer +!$omp allocate(xarray) align(-32) allocator(omp_large_cap_mem_alloc) + allocate(j(z), xarray(t)) +end program allocate_align_tree +