Skip to content

Commit

Permalink
[FLANG][OpenMP]Add support for ALIGN clause on OMP ALLOCATE (llvm#120791
Browse files Browse the repository at this point in the history
)

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.
  • Loading branch information
Leporacanthicus authored Jan 6, 2025
1 parent 599c739 commit 4df366c
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 1 deletion.
1 change: 1 addition & 0 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3760,6 +3760,11 @@ struct OmpAffinityClause {
std::tuple<MODIFIERS(), OmpObjectList> 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 ->
Expand Down
4 changes: 4 additions & 0 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,8 @@ TYPE_PARSER(construct<OmpBindClause>(
"TEAMS" >> pure(OmpBindClause::Binding::Teams) ||
"THREAD" >> pure(OmpBindClause::Binding::Thread)))

TYPE_PARSER(construct<OmpAlignClause>(scalarIntExpr))

TYPE_PARSER(construct<OmpAtClause>(
"EXECUTION" >> pure(OmpAtClause::ActionTime::Execution) ||
"COMPILATION" >> pure(OmpAtClause::ActionTime::Compilation)))
Expand All @@ -582,6 +584,8 @@ TYPE_PARSER(
"ACQ_REL" >> construct<OmpClause>(construct<OmpClause::AcqRel>()) ||
"AFFINITY" >> construct<OmpClause>(construct<OmpClause::Affinity>(
parenthesized(Parser<OmpAffinityClause>{}))) ||
"ALIGN" >> construct<OmpClause>(construct<OmpClause::Align>(
parenthesized(Parser<OmpAlignClause>{}))) ||
"ALIGNED" >> construct<OmpClause>(construct<OmpClause::Aligned>(
parenthesized(Parser<OmpAlignedClause>{}))) ||
"ALLOCATE" >> construct<OmpClause>(construct<OmpClause::Allocate>(
Expand Down
17 changes: 17 additions & 0 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1489,11 +1489,24 @@ void OmpStructureChecker::Leave(const parser::OpenMPRequiresConstruct &) {
dirContext_.pop_back();
}

void OmpStructureChecker::CheckAlignValue(const parser::OmpClause &clause) {
if (auto *align{std::get_if<parser::OmpClause::Align>(&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<parser::Verbatim>(x.t)};
const auto &objectList{std::get<parser::OmpObjectList>(x.t)};
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate);
const auto &clauseList{std::get<parser::OmpClauseList>(x.t)};
for (const auto &clause : clauseList.v) {
CheckAlignValue(clause);
}
CheckIsVarPartOfAnotherVar(dir.source, objectList);
}

Expand Down Expand Up @@ -1720,6 +1733,10 @@ void OmpStructureChecker::Enter(const parser::OpenMPExecutableAllocate &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
const auto &objectList{std::get<std::optional<parser::OmpObjectList>>(x.t)};
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate);
const auto &clauseList{std::get<parser::OmpClauseList>(x.t)};
for (const auto &clause : clauseList.v) {
CheckAlignValue(clause);
}
if (objectList) {
CheckIsVarPartOfAnotherVar(dir.source, *objectList);
}
Expand Down
2 changes: 2 additions & 0 deletions flang/lib/Semantics/check-omp-structure.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,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]; }
Expand Down
10 changes: 10 additions & 0 deletions flang/test/Lower/OpenMP/Todo/omp-declarative-allocate-align.f90
Original file line number Diff line number Diff line change
@@ -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
42 changes: 42 additions & 0 deletions flang/test/Parser/OpenMP/allocate-align-tree.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
! 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_align_tree
use omp_lib
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 ->
!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 = '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: !$OMP ALLOCATE (xarray) ALIGN(32_4) ALLOCATOR(2_8)
!UNPARSE-NEXT: ALLOCATE(j(z), xarray(t))
4 changes: 3 additions & 1 deletion flang/test/Parser/OpenMP/allocate-unparse.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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))
20 changes: 20 additions & 0 deletions flang/test/Semantics/OpenMP/allocate-align01.f90
Original file line number Diff line number Diff line change
@@ -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

1 change: 1 addition & 0 deletions llvm/include/llvm/Frontend/OpenMP/OMP.td
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down

0 comments on commit 4df366c

Please sign in to comment.