Skip to content

Commit

Permalink
[flang][openacc] Relax rule for end directive on combined construct
Browse files Browse the repository at this point in the history
Make the keyword `loop` optional for the end driective on combined
construct. This done to extend compatibility with other compiler that
allow this.

Reviewed By: razvanlupusoru

Differential Revision: https://reviews.llvm.org/D151856
  • Loading branch information
clementval committed Jun 13, 2023
1 parent 88c2c2e commit 561a369
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 56 deletions.
17 changes: 17 additions & 0 deletions flang/docs/OpenACC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!--===- docs/Extensions.md
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
See https://llvm.org/LICENSE.txt for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-->

# OpenACC in Flang

```eval_rst
.. contents::
:local:
```

## Intentional deviation from the specification
* The end directive for combined construct can omit the `loop` keyword.
3 changes: 1 addition & 2 deletions flang/lib/Parser/executable-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ constexpr auto executableConstruct{first(
construct<ExecutableConstruct>(indirect(forallConstruct)),
construct<ExecutableConstruct>(indirect(ompEndLoopDirective)),
construct<ExecutableConstruct>(indirect(openmpConstruct)),
construct<ExecutableConstruct>(indirect(accEndCombinedDirective)),
construct<ExecutableConstruct>(indirect(openaccConstruct)),
construct<ExecutableConstruct>(indirect(Parser<OpenACCConstruct>{})),
construct<ExecutableConstruct>(indirect(compilerDirective)),
construct<ExecutableConstruct>(indirect(Parser<CUFKernelDoConstruct>{})))};

Expand Down
15 changes: 12 additions & 3 deletions flang/lib/Parser/openacc-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,19 @@ TYPE_CONTEXT_PARSER("OpenACC construct"_en_US,
construct<OpenACCConstruct>(Parser<OpenACCWaitConstruct>{}),
construct<OpenACCConstruct>(Parser<OpenACCAtomicConstruct>{})))

TYPE_PARSER(startAccLine >> sourced(construct<AccEndCombinedDirective>(sourced(
"END"_tok >> Parser<AccCombinedDirective>{}))))
TYPE_PARSER(startAccLine >>
sourced(construct<AccEndCombinedDirective>(sourced("END"_tok >>
construct<AccCombinedDirective>("KERNELS"_tok >> maybe("LOOP"_tok) >>
pure(llvm::acc::Directive::ACCD_kernels_loop) ||
"PARALLEL"_tok >> maybe("LOOP"_tok) >>
pure(llvm::acc::Directive::ACCD_parallel_loop) ||
"SERIAL"_tok >> maybe("LOOP"_tok) >>
pure(llvm::acc::Directive::ACCD_serial_loop))))))

TYPE_PARSER(construct<OpenACCCombinedConstruct>(
sourced(Parser<AccBeginCombinedDirective>{} / endAccLine)))
sourced(Parser<AccBeginCombinedDirective>{} / endAccLine),
withMessage("A DO loop must follow the combined construct"_err_en_US,
Parser<DoConstruct>{}),
maybe(Parser<AccEndCombinedDirective>{} / endAccLine)))

} // namespace Fortran::parser
1 change: 0 additions & 1 deletion flang/lib/Parser/type-parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ constexpr Parser<EntryStmt> entryStmt; // R1541
constexpr Parser<ContainsStmt> containsStmt; // R1543
constexpr Parser<CompilerDirective> compilerDirective;
constexpr Parser<OpenACCConstruct> openaccConstruct;
constexpr Parser<AccEndCombinedDirective> accEndCombinedDirective;
constexpr Parser<OpenACCDeclarativeConstruct> openaccDeclarativeConstruct;
constexpr Parser<OpenMPConstruct> openmpConstruct;
constexpr Parser<OpenMPDeclarativeConstruct> openmpDeclarativeConstruct;
Expand Down
42 changes: 13 additions & 29 deletions flang/lib/Semantics/canonicalize-acc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,36 +169,20 @@ class CanonicalizationOfAcc {
parser::Block::iterator nextIt;
auto &beginDir{std::get<parser::AccBeginCombinedDirective>(x.t)};
auto &dir{std::get<parser::AccCombinedDirective>(beginDir.t)};

nextIt = it;
if (++nextIt != block.end()) {
if (auto *doCons{parser::Unwrap<parser::DoConstruct>(*nextIt)}) {
if (!doCons->GetLoopControl()) {
messages_.Say(dir.source,
"DO loop after the %s directive must have loop control"_err_en_US,
parser::ToUpperCaseLetters(dir.source.ToString()));
return;
}
// move DoConstruct
std::get<std::optional<parser::DoConstruct>>(x.t) = std::move(*doCons);
nextIt = block.erase(nextIt);
// try to match AccEndCombinedDirective
if (nextIt != block.end()) {
if (auto *endDir{
parser::Unwrap<parser::AccEndCombinedDirective>(*nextIt)}) {
std::get<std::optional<parser::AccEndCombinedDirective>>(x.t) =
std::move(*endDir);
block.erase(nextIt);
}
}

CheckDoConcurrentClauseRestriction<parser::OpenACCCombinedConstruct,
parser::AccBeginCombinedDirective>(x);
CheckTileClauseRestriction<parser::OpenACCCombinedConstruct,
parser::AccBeginCombinedDirective>(x);

return; // found do-loop
auto &doConstruct{std::get<std::optional<parser::DoConstruct>>(x.t)};

if (doConstruct) {
CheckDoConcurrentClauseRestriction<parser::OpenACCCombinedConstruct,
parser::AccBeginCombinedDirective>(x);
CheckTileClauseRestriction<parser::OpenACCCombinedConstruct,
parser::AccBeginCombinedDirective>(x);
if (!doConstruct->GetLoopControl()) {
messages_.Say(dir.source,
"DO loop after the %s directive must have loop control"_err_en_US,
parser::ToUpperCaseLetters(dir.source.ToString()));
return;
}
return;
}
messages_.Say(dir.source,
"A DO loop must follow the %s directive"_err_en_US,
Expand Down
21 changes: 0 additions & 21 deletions flang/test/Semantics/OpenACC/acc-canonicalization-validity.f90
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,6 @@ program openacc_clause_validity
do
end do

!ERROR: A DO loop must follow the PARALLEL LOOP directive
!$acc parallel loop
i = 1

!ERROR: A DO loop must follow the KERNELS LOOP directive
!$acc kernels loop
i = 1

!ERROR: A DO loop must follow the SERIAL LOOP directive
!$acc serial loop
i = 1

!ERROR: The END PARALLEL LOOP directive must follow the DO loop associated with the loop construct
!$acc end parallel loop

!ERROR: The END KERNELS LOOP directive must follow the DO loop associated with the loop construct
!$acc end kernels loop

!ERROR: The END SERIAL LOOP directive must follow the DO loop associated with the loop construct
!$acc end serial loop

!$acc parallel loop
do i = 1, N
a(i) = 3.14
Expand Down
21 changes: 21 additions & 0 deletions flang/test/Semantics/OpenACC/acc-combined-loop.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
! RUN: %python %S/../test_errors.py %s %flang -fopenacc

program openacc_combined_loop
implicit none
integer :: i

i = 1

!$acc parallel loop
!ERROR: A DO loop must follow the combined construct
i = 1

!$acc kernels loop
!ERROR: A DO loop must follow the combined construct
i = 1

!$acc serial loop
!ERROR: A DO loop must follow the combined construct
i = 1

end
12 changes: 12 additions & 0 deletions flang/test/Semantics/OpenACC/acc-kernels-loop.f90
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ program openacc_kernels_loop_validity
a(i) = 3.14
end do

!$acc kernels loop
do i = 1, N
a(i) = 3.14
end do
!$acc end kernels loop

!$acc kernels loop
do i = 1, N
a(i) = 3.14
end do
!$acc end kernels loop

!$acc kernels loop num_gangs(8)
do i = 1, N
a(i) = 3.14
Expand Down
17 changes: 17 additions & 0 deletions flang/test/Semantics/OpenACC/acc-parallel-loop-validity.f90
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,23 @@ program openacc_parallel_loop_validity
real(8), dimension(N) :: a, f, g, h
real(8), dimension(N, N) :: aa, bb, cc

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

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

!$acc parallel loop
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
Expand Down
12 changes: 12 additions & 0 deletions flang/test/Semantics/OpenACC/acc-serial-loop.f90
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,16 @@ program openacc_serial_loop_validity
!ERROR: Unmatched END PARALLEL LOOP directive
!$acc end parallel loop

!$acc serial loop
do i = 1, N
a(i) = 3.14
end do
!$acc end serial loop

!$acc serial loop
do i = 1, N
a(i) = 3.14
end do
!$acc end serial

end program openacc_serial_loop_validity

0 comments on commit 561a369

Please sign in to comment.