diff --git a/flang/docs/OpenACC.md b/flang/docs/OpenACC.md new file mode 100644 --- /dev/null +++ b/flang/docs/OpenACC.md @@ -0,0 +1,17 @@ + + +# OpenACC in Flang + +```eval_rst +.. contents:: + :local: +``` + +## Intentional deviation from the specification +* The end directive for combined construct can omit the `loop` keyword. diff --git a/flang/lib/Parser/executable-parsers.cpp b/flang/lib/Parser/executable-parsers.cpp --- a/flang/lib/Parser/executable-parsers.cpp +++ b/flang/lib/Parser/executable-parsers.cpp @@ -52,8 +52,7 @@ construct(indirect(forallConstruct)), construct(indirect(ompEndLoopDirective)), construct(indirect(openmpConstruct)), - construct(indirect(accEndCombinedDirective)), - construct(indirect(openaccConstruct)), + construct(indirect(Parser{})), construct(indirect(compilerDirective)), construct(indirect(Parser{})))}; diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp --- a/flang/lib/Parser/openacc-parsers.cpp +++ b/flang/lib/Parser/openacc-parsers.cpp @@ -232,10 +232,19 @@ construct(Parser{}), construct(Parser{}))) -TYPE_PARSER(startAccLine >> sourced(construct(sourced( - "END"_tok >> Parser{})))) +TYPE_PARSER(startAccLine >> + sourced(construct(sourced("END"_tok >> + construct("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( - sourced(Parser{} / endAccLine))) + sourced(Parser{} / endAccLine), + withMessage("A DO loop must follow the combined construct"_err_en_US, + Parser{}), + maybe(Parser{} / endAccLine))) } // namespace Fortran::parser diff --git a/flang/lib/Parser/type-parsers.h b/flang/lib/Parser/type-parsers.h --- a/flang/lib/Parser/type-parsers.h +++ b/flang/lib/Parser/type-parsers.h @@ -132,7 +132,6 @@ constexpr Parser containsStmt; // R1543 constexpr Parser compilerDirective; constexpr Parser openaccConstruct; -constexpr Parser accEndCombinedDirective; constexpr Parser openaccDeclarativeConstruct; constexpr Parser openmpConstruct; constexpr Parser openmpDeclarativeConstruct; diff --git a/flang/lib/Semantics/canonicalize-acc.cpp b/flang/lib/Semantics/canonicalize-acc.cpp --- a/flang/lib/Semantics/canonicalize-acc.cpp +++ b/flang/lib/Semantics/canonicalize-acc.cpp @@ -169,36 +169,20 @@ parser::Block::iterator nextIt; auto &beginDir{std::get(x.t)}; auto &dir{std::get(beginDir.t)}; - - nextIt = it; - if (++nextIt != block.end()) { - if (auto *doCons{parser::Unwrap(*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>(x.t) = std::move(*doCons); - nextIt = block.erase(nextIt); - // try to match AccEndCombinedDirective - if (nextIt != block.end()) { - if (auto *endDir{ - parser::Unwrap(*nextIt)}) { - std::get>(x.t) = - std::move(*endDir); - block.erase(nextIt); - } - } - - CheckDoConcurrentClauseRestriction(x); - CheckTileClauseRestriction(x); - - return; // found do-loop + auto &doConstruct{std::get>(x.t)}; + + if (doConstruct) { + CheckDoConcurrentClauseRestriction(x); + CheckTileClauseRestriction(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, diff --git a/flang/test/Semantics/OpenACC/acc-canonicalization-validity.f90 b/flang/test/Semantics/OpenACC/acc-canonicalization-validity.f90 --- a/flang/test/Semantics/OpenACC/acc-canonicalization-validity.f90 +++ b/flang/test/Semantics/OpenACC/acc-canonicalization-validity.f90 @@ -24,27 +24,6 @@ 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 diff --git a/flang/test/Semantics/OpenACC/acc-combined-loop.f90 b/flang/test/Semantics/OpenACC/acc-combined-loop.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-combined-loop.f90 @@ -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 diff --git a/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 b/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 --- a/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 +++ b/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 @@ -34,6 +34,18 @@ 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 diff --git a/flang/test/Semantics/OpenACC/acc-parallel-loop-validity.f90 b/flang/test/Semantics/OpenACC/acc-parallel-loop-validity.f90 --- a/flang/test/Semantics/OpenACC/acc-parallel-loop-validity.f90 +++ b/flang/test/Semantics/OpenACC/acc-parallel-loop-validity.f90 @@ -17,6 +17,23 @@ 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 diff --git a/flang/test/Semantics/OpenACC/acc-serial-loop.f90 b/flang/test/Semantics/OpenACC/acc-serial-loop.f90 --- a/flang/test/Semantics/OpenACC/acc-serial-loop.f90 +++ b/flang/test/Semantics/OpenACC/acc-serial-loop.f90 @@ -94,4 +94,16 @@ !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