Skip to content

Commit b4d3af6

Browse files
author
git apple-llvm automerger
committed
Merge commit '8470027f257a' from llvm.org/main into next
2 parents 15b09a3 + 8470027 commit b4d3af6

File tree

3 files changed

+206
-11
lines changed

3 files changed

+206
-11
lines changed

flang/lib/Semantics/check-acc-structure.cpp

Lines changed: 107 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88
#include "check-acc-structure.h"
9+
#include "resolve-names-utils.h"
910
#include "flang/Common/enum-set.h"
1011
#include "flang/Evaluate/tools.h"
1112
#include "flang/Parser/parse-tree.h"
@@ -106,18 +107,25 @@ bool AccStructureChecker::IsComputeConstruct(
106107
directive == llvm::acc::ACCD_kernels_loop;
107108
}
108109

109-
bool AccStructureChecker::IsInsideComputeConstruct() const {
110-
if (dirContext_.size() <= 1) {
111-
return false;
112-
}
110+
bool AccStructureChecker::IsLoopConstruct(
111+
llvm::acc::Directive directive) const {
112+
return directive == llvm::acc::Directive::ACCD_loop ||
113+
directive == llvm::acc::ACCD_parallel_loop ||
114+
directive == llvm::acc::ACCD_serial_loop ||
115+
directive == llvm::acc::ACCD_kernels_loop;
116+
}
113117

118+
std::optional<llvm::acc::Directive>
119+
AccStructureChecker::getParentComputeConstruct() const {
114120
// Check all nested context skipping the first one.
115-
for (std::size_t i = dirContext_.size() - 1; i > 0; --i) {
116-
if (IsComputeConstruct(dirContext_[i - 1].directive)) {
117-
return true;
118-
}
119-
}
120-
return false;
121+
for (std::size_t i = dirContext_.size() - 1; i > 0; --i)
122+
if (IsComputeConstruct(dirContext_[i - 1].directive))
123+
return dirContext_[i - 1].directive;
124+
return std::nullopt;
125+
}
126+
127+
bool AccStructureChecker::IsInsideComputeConstruct() const {
128+
return getParentComputeConstruct().has_value();
121129
}
122130

123131
void AccStructureChecker::CheckNotInComputeConstruct() {
@@ -128,6 +136,14 @@ void AccStructureChecker::CheckNotInComputeConstruct() {
128136
}
129137
}
130138

139+
bool AccStructureChecker::IsInsideParallelConstruct() const {
140+
if (auto directive = getParentComputeConstruct())
141+
if (*directive == llvm::acc::ACCD_parallel ||
142+
*directive == llvm::acc::ACCD_parallel_loop)
143+
return true;
144+
return false;
145+
}
146+
131147
void AccStructureChecker::Enter(const parser::AccClause &x) {
132148
SetContextClause(x);
133149
}
@@ -250,6 +266,85 @@ void AccStructureChecker::Leave(const parser::OpenACCCombinedConstruct &x) {
250266
dirContext_.pop_back();
251267
}
252268

269+
std::optional<std::int64_t> AccStructureChecker::getGangDimensionSize(
270+
DirectiveContext &dirContext) {
271+
for (auto it : dirContext.clauseInfo) {
272+
const auto *clause{it.second};
273+
if (const auto *gangClause{
274+
std::get_if<parser::AccClause::Gang>(&clause->u)})
275+
if (gangClause->v) {
276+
const Fortran::parser::AccGangArgList &x{*gangClause->v};
277+
for (const Fortran::parser::AccGangArg &gangArg : x.v)
278+
if (const auto *dim{
279+
std::get_if<Fortran::parser::AccGangArg::Dim>(&gangArg.u)})
280+
if (const auto v{EvaluateInt64(context_, dim->v)})
281+
return *v;
282+
}
283+
}
284+
return std::nullopt;
285+
}
286+
287+
void AccStructureChecker::CheckNotInSameOrSubLevelLoopConstruct() {
288+
for (std::size_t i = dirContext_.size() - 1; i > 0; --i) {
289+
auto &parent{dirContext_[i - 1]};
290+
if (IsLoopConstruct(parent.directive)) {
291+
for (auto parentClause : parent.actualClauses) {
292+
for (auto cl : GetContext().actualClauses) {
293+
bool invalid{false};
294+
if (parentClause == llvm::acc::Clause::ACCC_gang &&
295+
cl == llvm::acc::Clause::ACCC_gang) {
296+
if (IsInsideParallelConstruct()) {
297+
auto parentDim = getGangDimensionSize(parent);
298+
auto currentDim = getGangDimensionSize(GetContext());
299+
std::int64_t parentDimNum = 1, currentDimNum = 1;
300+
if (parentDim)
301+
parentDimNum = *parentDim;
302+
if (currentDim)
303+
currentDimNum = *currentDim;
304+
if (parentDimNum <= currentDimNum) {
305+
std::string parentDimStr, currentDimStr;
306+
if (parentDim)
307+
parentDimStr = "(dim:" + std::to_string(parentDimNum) + ")";
308+
if (currentDim)
309+
currentDimStr = "(dim:" + std::to_string(currentDimNum) + ")";
310+
context_.Say(GetContext().clauseSource,
311+
"%s%s clause is not allowed in the region of a loop with the %s%s clause"_err_en_US,
312+
parser::ToUpperCaseLetters(
313+
llvm::acc::getOpenACCClauseName(cl).str()),
314+
currentDimStr,
315+
parser::ToUpperCaseLetters(
316+
llvm::acc::getOpenACCClauseName(parentClause).str()),
317+
parentDimStr);
318+
continue;
319+
}
320+
} else {
321+
invalid = true;
322+
}
323+
} else if (parentClause == llvm::acc::Clause::ACCC_worker &&
324+
(cl == llvm::acc::Clause::ACCC_gang ||
325+
cl == llvm::acc::Clause::ACCC_worker)) {
326+
invalid = true;
327+
} else if (parentClause == llvm::acc::Clause::ACCC_vector &&
328+
(cl == llvm::acc::Clause::ACCC_gang ||
329+
cl == llvm::acc::Clause::ACCC_worker ||
330+
cl == llvm::acc::Clause::ACCC_vector)) {
331+
invalid = true;
332+
}
333+
if (invalid)
334+
context_.Say(GetContext().clauseSource,
335+
"%s clause is not allowed in the region of a loop with the %s clause"_err_en_US,
336+
parser::ToUpperCaseLetters(
337+
llvm::acc::getOpenACCClauseName(cl).str()),
338+
parser::ToUpperCaseLetters(
339+
llvm::acc::getOpenACCClauseName(parentClause).str()));
340+
}
341+
}
342+
}
343+
if (IsComputeConstruct(parent.directive))
344+
break;
345+
}
346+
}
347+
253348
void AccStructureChecker::Enter(const parser::OpenACCLoopConstruct &x) {
254349
const auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)};
255350
const auto &loopDir{std::get<parser::AccLoopDirective>(beginDir.t)};
@@ -267,6 +362,8 @@ void AccStructureChecker::Leave(const parser::OpenACCLoopConstruct &x) {
267362
CheckNotAllowedIfClause(llvm::acc::Clause::ACCC_seq,
268363
{llvm::acc::Clause::ACCC_gang, llvm::acc::Clause::ACCC_vector,
269364
llvm::acc::Clause::ACCC_worker});
365+
// Restriction - 2.9.2, 2.9.3, 2.9.4
366+
CheckNotInSameOrSubLevelLoopConstruct();
270367
}
271368
dirContext_.pop_back();
272369
}

flang/lib/Semantics/check-acc-structure.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,14 @@ class AccStructureChecker
9898

9999
bool CheckAllowedModifier(llvm::acc::Clause clause);
100100
bool IsComputeConstruct(llvm::acc::Directive directive) const;
101+
bool IsLoopConstruct(llvm::acc::Directive directive) const;
102+
std::optional<llvm::acc::Directive> getParentComputeConstruct() const;
101103
bool IsInsideComputeConstruct() const;
104+
bool IsInsideParallelConstruct() const;
102105
void CheckNotInComputeConstruct();
106+
std::optional<std::int64_t> getGangDimensionSize(
107+
DirectiveContext &dirContext);
108+
void CheckNotInSameOrSubLevelLoopConstruct();
103109
void CheckMultipleOccurrenceInDeclare(
104110
const parser::AccObjectList &, llvm::acc::Clause);
105111
void CheckMultipleOccurrenceInDeclare(

flang/test/Semantics/OpenACC/acc-loop.f90

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ program openacc_loop_validity
1313
integer :: n
1414
end type atype
1515

16-
integer :: i, j, k, b, gang_size, vector_size, worker_size
16+
integer :: i, j, k, l, m, b, gang_size, vector_size, worker_size
1717
integer, parameter :: N = 256
1818
integer, dimension(N) :: c
1919
logical, dimension(N) :: d, e
@@ -259,6 +259,98 @@ program openacc_loop_validity
259259
end do
260260
!$acc end parallel
261261

262+
!$acc parallel
263+
!$acc loop gang
264+
do i = 1, n
265+
!$acc loop worker
266+
do j = 1, n
267+
!ERROR: GANG clause is not allowed in the region of a loop with the WORKER clause
268+
!ERROR: GANG clause is not allowed in the region of a loop with the GANG clause
269+
!$acc loop gang vector
270+
do k = 1, i
271+
end do
272+
end do
273+
end do
274+
!$acc end parallel
275+
276+
!$acc parallel loop vector
277+
do i = 1, n
278+
!ERROR: GANG clause is not allowed in the region of a loop with the VECTOR clause
279+
!$acc loop gang
280+
do j = 1, n
281+
!ERROR: WORKER clause is not allowed in the region of a loop with the VECTOR clause
282+
!$acc loop worker
283+
do k = 1, i
284+
!ERROR: VECTOR clause is not allowed in the region of a loop with the VECTOR clause
285+
!$acc loop vector
286+
do l = 1, 1
287+
end do
288+
end do
289+
end do
290+
end do
291+
!$acc end parallel loop
292+
293+
!$acc kernels
294+
do i = 1, n
295+
!$acc loop gang worker
296+
do j = 1, n
297+
!ERROR: WORKER clause is not allowed in the region of a loop with the WORKER clause
298+
!$acc loop worker vector
299+
do k = 1, i
300+
end do
301+
end do
302+
end do
303+
!$acc end kernels
304+
305+
!$acc parallel
306+
!$acc loop gang(dim:1)
307+
do i = 1, n
308+
!ERROR: GANG(dim:1) clause is not allowed in the region of a loop with the GANG(dim:1) clause
309+
!$acc loop gang(dim:1)
310+
do j = 1, n
311+
!ERROR: GANG(dim:2) clause is not allowed in the region of a loop with the GANG(dim:1) clause
312+
!$acc loop gang(dim:2)
313+
do k = 1, i
314+
!ERROR: GANG(dim:3) clause is not allowed in the region of a loop with the GANG(dim:2) clause
315+
!ERROR: GANG(dim:3) clause is not allowed in the region of a loop with the GANG(dim:1) clause
316+
!$acc loop gang(dim:3)
317+
do l = 1, 1
318+
!ERROR: GANG(dim:3) clause is not allowed in the region of a loop with the GANG(dim:3) clause
319+
!ERROR: GANG(dim:3) clause is not allowed in the region of a loop with the GANG(dim:2) clause
320+
!ERROR: GANG(dim:3) clause is not allowed in the region of a loop with the GANG(dim:1) clause
321+
!$acc loop gang(dim:3)
322+
do m = 1, 1
323+
end do
324+
end do
325+
end do
326+
end do
327+
end do
328+
!$acc end parallel
329+
330+
!$acc parallel loop gang(dim:3)
331+
do i = 1, n
332+
!$acc loop gang(dim:2)
333+
do j = 1, n
334+
!$acc loop gang(dim:1) worker vector
335+
do k = 1, i
336+
end do
337+
end do
338+
end do
339+
!$acc end parallel loop
340+
341+
!$acc kernels loop gang(dim:3)
342+
do i = 1, n
343+
!ERROR: GANG clause is not allowed in the region of a loop with the GANG clause
344+
!$acc loop gang(dim:2)
345+
do j = 1, n
346+
!ERROR: GANG clause is not allowed in the region of a loop with the GANG clause
347+
!$acc loop gang(dim:1) worker vector
348+
do k = 1, i
349+
end do
350+
end do
351+
end do
352+
!$acc end kernels loop
353+
262354
!ERROR: Clause IF is not allowed after clause DEVICE_TYPE on the PARALLEL directive
263355
!$acc parallel device_type(*) if(.TRUE.)
264356
!$acc loop

0 commit comments

Comments
 (0)