[FLANG][OpenMP]Add support for ALIGN clause on OMP ALLOCATE (#120791)

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.
This commit is contained in:
Mats Petersson
2025-01-06 11:02:31 +00:00
committed by GitHub
parent 599c739905
commit 4df366cd80
10 changed files with 105 additions and 1 deletions

View File

@@ -486,6 +486,7 @@ public:
NODE(parser, OmpAffinityClause)
NODE(OmpAffinityClause, Modifier)
NODE(parser, OmpAlignment)
NODE(parser, OmpAlignClause)
NODE(parser, OmpAlignedClause)
NODE(OmpAlignedClause, Modifier)
NODE(parser, OmpAtClause)

View File

@@ -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 ->

View File

@@ -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)))
@@ -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>(

View File

@@ -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);
}
@@ -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);
}

View File

@@ -264,6 +264,8 @@ private:
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]; }

View File

@@ -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

View File

@@ -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))

View File

@@ -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 @@ integer :: a, b, m, n, t, x, y, z
!$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))

View File

@@ -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

View File

@@ -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";