Skip to content

Commit

Permalink
[flang][openacc] Add check for tile clause restriction
Browse files Browse the repository at this point in the history
The tile clause in OpenACC 3.0 imposes some restriction. Element in the tile size list are either * or a
constant positive integer expression. If there are n tile sizes in the list, the loop construct must be immediately
followed by n tightly-nested loops.
This patch implement these restrictions and add some tests.

Reviewed By: klausler

Differential Revision: https://reviews.llvm.org/D86655
  • Loading branch information
clementval committed Aug 28, 2020
1 parent cbea175 commit 4df2a5f
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 3 deletions.
2 changes: 2 additions & 0 deletions flang/include/flang/Parser/dump-parse-tree.h
Expand Up @@ -86,6 +86,8 @@ class ParseTreeDumper {
NODE(parser, AccSizeExpr)
NODE(parser, AccSizeExprList)
NODE(parser, AccStandaloneDirective)
NODE(parser, AccTileExpr)
NODE(parser, AccTileExprList)
NODE(parser, AccLoopDirective)
NODE(parser, AccWaitArgument)
static std::string GetNodeName(const llvm::acc::Directive &x) {
Expand Down
10 changes: 10 additions & 0 deletions flang/include/flang/Parser/parse-tree.h
Expand Up @@ -3857,6 +3857,16 @@ struct AccWaitArgument {
std::tuple<std::optional<ScalarIntExpr>, std::list<ScalarIntExpr>> t;
};

struct AccTileExpr {
TUPLE_CLASS_BOILERPLATE(AccTileExpr);
CharBlock source;
std::tuple<std::optional<ScalarIntConstantExpr>> t; // if null then *
};

struct AccTileExprList {
WRAPPER_CLASS_BOILERPLATE(AccTileExprList, std::list<AccTileExpr>);
};

struct AccSizeExpr {
TUPLE_CLASS_BOILERPLATE(AccSizeExpr);
CharBlock source;
Expand Down
13 changes: 11 additions & 2 deletions flang/lib/Parser/openacc-parsers.cpp
Expand Up @@ -102,7 +102,7 @@ TYPE_PARSER("AUTO" >> construct<AccClause>(construct<AccClause::Auto>()) ||
maybe(parenthesized(scalarLogicalExpr)))) ||
"SEQ" >> construct<AccClause>(construct<AccClause::Seq>()) ||
"TILE" >> construct<AccClause>(construct<AccClause::Tile>(
parenthesized(Parser<AccSizeExprList>{}))) ||
parenthesized(Parser<AccTileExprList>{}))) ||
"USE_DEVICE" >> construct<AccClause>(construct<AccClause::UseDevice>(
parenthesized(Parser<AccObjectList>{}))) ||
"VECTOR_LENGTH" >> construct<AccClause>(construct<AccClause::VectorLength>(
Expand Down Expand Up @@ -131,11 +131,20 @@ TYPE_PARSER(construct<AccWaitArgument>(maybe("DEVNUM:" >> scalarIntExpr / ":"),
"QUEUES:" >> nonemptyList(scalarIntExpr) || nonemptyList(scalarIntExpr)))

// 2.9 (1609) size-expr is one of:
// * (represented as an empty std::optional<ScalarIntExpr>)
// int-expr
TYPE_PARSER(construct<AccSizeExpr>(scalarIntExpr) ||
construct<AccSizeExpr>("*" >> maybe(scalarIntExpr)))
construct<AccSizeExpr>("*" >> construct<std::optional<ScalarIntExpr>>()))
TYPE_PARSER(construct<AccSizeExprList>(nonemptyList(Parser<AccSizeExpr>{})))

// tile size is one of:
// * (represented as an empty std::optional<ScalarIntExpr>)
// constant-int-expr
TYPE_PARSER(construct<AccTileExpr>(scalarIntConstantExpr) ||
construct<AccTileExpr>(
"*" >> construct<std::optional<ScalarIntConstantExpr>>()))
TYPE_PARSER(construct<AccTileExprList>(nonemptyList(Parser<AccTileExpr>{})))

// 2.9 (1607) gang-arg is one of:
// [num:]int-expr
// static:size-expr
Expand Down
38 changes: 38 additions & 0 deletions flang/lib/Semantics/canonicalize-acc.cpp
Expand Up @@ -48,6 +48,40 @@ class CanonicalizationOfAcc {
}

private:
// Check constraint in 2.9.7
// If there are n tile sizes in the list, the loop construct must be
// immediately followed by n tightly-nested loops.
template <typename C, typename D>
void CheckTileClauseRestriction(const C &x) {
const auto &beginLoopDirective = std::get<D>(x.t);
const auto &accClauseList =
std::get<parser::AccClauseList>(beginLoopDirective.t);
for (const auto &clause : accClauseList.v) {
if (const auto *tileClause =
std::get_if<parser::AccClause::Tile>(&clause.u)) {
const parser::AccTileExprList &tileExprList = tileClause->v;
const std::list<parser::AccTileExpr> &listTileExpr = tileExprList.v;
std::size_t tileArgNb = listTileExpr.size();

const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
for (const parser::DoConstruct *loop{&*outer}; loop && tileArgNb > 0;
--tileArgNb) {
const auto &block{std::get<parser::Block>(loop->t)};
const auto it{block.begin()};
loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it)
: nullptr;
}

if (tileArgNb > 0) {
messages_.Say(beginLoopDirective.source,
"The loop construct with the TILE clause must be followed by %d "
"tightly-nested loops"_err_en_US,
listTileExpr.size());
}
}
}
}

void RewriteOpenACCLoopConstruct(parser::OpenACCLoopConstruct &x,
parser::Block &block, parser::Block::iterator it) {
// Check the sequence of DoConstruct in the same iteration
Expand Down Expand Up @@ -78,6 +112,8 @@ class CanonicalizationOfAcc {
"DO loop after the %s directive must have loop control"_err_en_US,
parser::ToUpperCaseLetters(dir.source.ToString()));
}
CheckTileClauseRestriction<parser::OpenACCLoopConstruct,
parser::AccBeginLoopDirective>(x);
return; // found do-loop
}
}
Expand Down Expand Up @@ -127,6 +163,8 @@ class CanonicalizationOfAcc {
"DO loop after the %s directive must have loop control"_err_en_US,
parser::ToUpperCaseLetters(dir.source.ToString()));
}
CheckTileClauseRestriction<parser::OpenACCCombinedConstruct,
parser::AccBeginCombinedDirective>(x);
return; // found do-loop
}
}
Expand Down
14 changes: 14 additions & 0 deletions flang/test/Semantics/acc-canonicalization-validity.f90
Expand Up @@ -92,4 +92,18 @@ program openacc_clause_validity
do
end do

!$acc parallel
!ERROR: The loop construct with the TILE clause must be followed by 2 tightly-nested loops
!$acc loop tile(2, 2)
do i = 1, N
a(i) = 3.14
end do
!$acc end parallel

!ERROR: The loop construct with the TILE clause must be followed by 2 tightly-nested loops
!$acc parallel loop tile(2, 2)
do i = 1, N
a(i) = 3.14
end do

end program openacc_clause_validity
20 changes: 20 additions & 0 deletions flang/test/Semantics/acc-clause-validity.f90
Expand Up @@ -24,6 +24,7 @@ program openacc_clause_validity
logical, dimension(N) :: d, e
real :: reduction_r
logical :: reduction_l
real(8), dimension(N, N) :: aa

!ERROR: At least one clause is required on the DECLARE directive
!$acc declare
Expand Down Expand Up @@ -83,6 +84,25 @@ program openacc_clause_validity
end do
!$acc end parallel

!$acc parallel
!$acc loop tile(2)
do i = 1, N
a(i) = 3.14
end do
!$acc end parallel

!$acc parallel loop tile(2)
do i = 1, N
a(i) = 3.14
end do

!$acc parallel loop tile(2, 2)
do i = 1, N
do j = 1, N
aa(i, j) = 3.14
end do
end do

!$acc parallel device_type(*) num_gangs(2)
!$acc loop
do i = 1, N
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Frontend/OpenACC/ACC.td
Expand Up @@ -192,7 +192,7 @@ def ACCC_Private : Clause<"private"> {

// 2.9.7
def ACCC_Tile : Clause <"tile"> {
let flangClassValue = "AccSizeExprList";
let flangClassValue = "AccTileExprList";
}

// 2.8.1
Expand Down

0 comments on commit 4df2a5f

Please sign in to comment.