Skip to content

Commit

Permalink
[flang][openacc] Semantic check for cache directive
Browse files Browse the repository at this point in the history
Add semantic check for the cache directive. According to section 2.10 from the specification:
A var in a cache directive must be a single array element or a simple subarray.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D90184
  • Loading branch information
clementval committed Nov 25, 2020
1 parent 0637dfe commit e73d8c7
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 1 deletion.
9 changes: 9 additions & 0 deletions flang/lib/Semantics/check-acc-structure.cpp
Expand Up @@ -238,6 +238,15 @@ void AccStructureChecker::Leave(const parser::OpenACCAtomicConstruct &x) {
dirContext_.pop_back();
}

void AccStructureChecker::Enter(const parser::OpenACCCacheConstruct &x) {
const auto &verbatim = std::get<parser::Verbatim>(x.t);
PushContextAndClauseSets(verbatim.source, llvm::acc::Directive::ACCD_cache);
SetContextDirectiveSource(verbatim.source);
}
void AccStructureChecker::Leave(const parser::OpenACCCacheConstruct &x) {
dirContext_.pop_back();
}

// Clause checkers
CHECK_REQ_SCALAR_INT_CONSTANT_CLAUSE(Collapse, ACCC_collapse)

Expand Down
2 changes: 2 additions & 0 deletions flang/lib/Semantics/check-acc-structure.h
Expand Up @@ -59,6 +59,8 @@ class AccStructureChecker
void Leave(const parser::OpenACCWaitConstruct &);
void Enter(const parser::OpenACCAtomicConstruct &);
void Leave(const parser::OpenACCAtomicConstruct &);
void Enter(const parser::OpenACCCacheConstruct &);
void Leave(const parser::OpenACCCacheConstruct &);

// Clauses
void Leave(const parser::AccClauseList &);
Expand Down
63 changes: 62 additions & 1 deletion flang/lib/Semantics/resolve-directives.cpp
Expand Up @@ -140,6 +140,9 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
GetContext().withinConstruct = true;
}

bool Pre(const parser::OpenACCCacheConstruct &);
void Post(const parser::OpenACCCacheConstruct &) { PopContext(); }

void Post(const parser::AccDefaultClause &);

bool Pre(const parser::AccClause::Copy &x) {
Expand Down Expand Up @@ -209,6 +212,7 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
Symbol *DeclareOrMarkOtherAccessEntity(Symbol &, Symbol::Flag);
void CheckMultipleAppearances(
const parser::Name &, const Symbol &, Symbol::Flag);
void AllowOnlyArrayAndSubArray(const parser::AccObjectList &objectList);
};

// Data-sharing and Data-mapping attributes for data-refs in OpenMP construct
Expand Down Expand Up @@ -450,7 +454,6 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCLoopConstruct &x) {
bool AccAttributeVisitor::Pre(const parser::OpenACCStandaloneConstruct &x) {
const auto &standaloneDir{std::get<parser::AccStandaloneDirective>(x.t)};
switch (standaloneDir.v) {
case llvm::acc::Directive::ACCD_cache:
case llvm::acc::Directive::ACCD_enter_data:
case llvm::acc::Directive::ACCD_exit_data:
case llvm::acc::Directive::ACCD_init:
Expand Down Expand Up @@ -483,6 +486,64 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
return true;
}

static bool IsLastNameArray(const parser::Designator &designator) {
const auto &name{GetLastName(designator)};
const evaluate::DataRef dataRef{*(name.symbol)};
return std::visit(
common::visitors{
[](const evaluate::SymbolRef &ref) { return ref->Rank() > 0; },
[](const evaluate::ArrayRef &aref) {
return aref.base().IsSymbol() ||
aref.base().GetComponent().base().Rank() == 0;
},
[](const auto &) { return false; },
},
dataRef.u);
}

void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
const parser::AccObjectList &objectList) {
for (const auto &accObject : objectList.v) {
std::visit(
common::visitors{
[&](const parser::Designator &designator) {
if (!IsLastNameArray(designator))
context_.Say(designator.source,
"Only array element or subarray are allowed in %s directive"_err_en_US,
parser::ToUpperCaseLetters(
llvm::acc::getOpenACCDirectiveName(
GetContext().directive)
.str()));
},
[&](const auto &name) {
context_.Say(name.source,
"Only array element or subarray are allowed in %s directive"_err_en_US,
parser::ToUpperCaseLetters(
llvm::acc::getOpenACCDirectiveName(GetContext().directive)
.str()));
},
},
accObject.u);
}
}

bool AccAttributeVisitor::Pre(const parser::OpenACCCacheConstruct &x) {
const auto &verbatim{std::get<parser::Verbatim>(x.t)};
PushContext(verbatim.source, llvm::acc::Directive::ACCD_cache);
ClearDataSharingAttributeObjects();

const auto &objectListWithModifier =
std::get<parser::AccObjectListWithModifier>(x.t);
const auto &objectList =
std::get<Fortran::parser::AccObjectList>(objectListWithModifier.t);

// 2.10 Cache directive restriction: A var in a cache directive must be a
// single array element or a simple subarray.
AllowOnlyArrayAndSubArray(objectList);

return true;
}

std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses(
const parser::AccClauseList &x) {
std::int64_t collapseLevel{0};
Expand Down
30 changes: 30 additions & 0 deletions flang/test/Semantics/acc-clause-validity.f90
Expand Up @@ -11,6 +11,7 @@
! 2.14.3 Set
! 2.14.4 Update
! 2.15.1 Routine
! 2.10 Cache
! 2.11 Parallel Loop
! 2.11 Kernels Loop
! 2.11 Serial Loop
Expand All @@ -21,6 +22,11 @@ program openacc_clause_validity

implicit none

type atype
real(8), dimension(10) :: arr
real(8) :: s
end type atype

integer :: i, j, b, gang_size, vector_size, worker_size
integer, parameter :: N = 256
integer, dimension(N) :: c
Expand All @@ -31,6 +37,8 @@ program openacc_clause_validity
logical :: reduction_l
real(8), dimension(N, N) :: aa, bb, cc
logical :: ifCondition = .TRUE.
type(atype) :: t
type(atype), dimension(10) :: ta

!ERROR: At least one clause is required on the DECLARE directive
!$acc declare
Expand Down Expand Up @@ -646,6 +654,28 @@ program openacc_clause_validity
i = i + 1
!$acc end atomic
!$acc end parallel
t%arr(i) = 2.0

!$acc cache(a(i))
!$acc cache(a(1:2,3:4))
!$acc cache(a)
!$acc cache(readonly: a, aa)
!$acc cache(readonly: a(i), aa(i, i))
!$acc cache(t%arr)
!$acc cache(ta(1:2)%arr)
!$acc cache(ta(1:2)%arr(1:4))

!ERROR: Only array element or subarray are allowed in CACHE directive
!$acc cache(ta(1:2)%s)

!ERROR: Only array element or subarray are allowed in CACHE directive
!$acc cache(i)

!ERROR: Only array element or subarray are allowed in CACHE directive
!$acc cache(t%s)

!ERROR: Only array element or subarray are allowed in CACHE directive
!$acc cache(/i/)

contains

Expand Down

0 comments on commit e73d8c7

Please sign in to comment.