[flang][OpenACC] Reject valued gang/worker/vector outside kernels - #218695
Conversation
`gang(num:)`, `worker(n)`, and `vector(n)` are only valid on a loop associated with kernels, and then only if that kernels construct does not already specify `num_gangs`, `num_workers`, or `vector_length`.
|
@llvm/pr-subscribers-flang-semantics @llvm/pr-subscribers-flang-fir-hlfir Author: Delaram Talaashrafi (delaram-talaashrafi) Changes
Patch is 30.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/218695.diff 5 Files Affected:
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 2e4b36178748b..cb85b63ad327c 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -46,6 +46,7 @@
#include "mlir/IR/MLIRContext.h"
#include "mlir/Support/LLVM.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/Frontend/OpenACC/ACC.h.inc"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -2353,6 +2354,61 @@ getAccLoopDoStmtEval(Fortran::lower::pft::Evaluation &eval) {
return nullptr;
}
+/// Reject a valued gang/worker/vector clause on a loop that is not associated
+/// with a kernels construct.
+static void checkLoopLevelClauseValueInKernels(
+ fir::FirOpBuilder &builder, mlir::Operation *parentCompute,
+ mlir::Location loc,
+ std::optional<mlir::acc::CombinedConstructsType> combinedConstructs,
+ llvm::StringRef clauseName) {
+ llvm::acc::Directive parentDir = llvm::acc::Directive::ACCD_loop;
+ if (combinedConstructs == mlir::acc::CombinedConstructsType::ParallelLoop)
+ parentDir = llvm::acc::Directive::ACCD_parallel_loop;
+ else if (combinedConstructs == mlir::acc::CombinedConstructsType::SerialLoop)
+ parentDir = llvm::acc::Directive::ACCD_serial_loop;
+ else if (mlir::isa_and_present<mlir::acc::ParallelOp>(parentCompute))
+ parentDir = llvm::acc::Directive::ACCD_parallel_loop;
+ else if (mlir::isa_and_present<mlir::acc::SerialOp>(parentCompute))
+ parentDir = llvm::acc::Directive::ACCD_serial_loop;
+ else if (mlir::acc::isAccRoutine(builder.getFunction().getOperation()))
+ parentDir = llvm::acc::Directive::ACCD_routine;
+
+ llvm::StringRef notAllowed =
+ parentDir == llvm::acc::Directive::ACCD_routine
+ ? "' not allowed in subprogram compiled with "
+ : "' not allowed in ";
+ fir::emitFatalError(
+ loc,
+ llvm::Twine("'") + clauseName + "(value)" + notAllowed +
+ Fortran::parser::ToUpperCaseLetters(
+ llvm::acc::getOpenACCDirectiveName(parentDir).str()) +
+ " directive",
+ /*genCrashDiag=*/false);
+}
+
+/// Reject a valued gang/worker/vector clause when the enclosing kernels
+/// construct already specifies the corresponding size clause.
+static void checkLoopLevelClauseConflictsWithKernels(
+ mlir::Operation *parentCompute, mlir::Location loc,
+ std::optional<mlir::acc::CombinedConstructsType> combinedConstructs,
+ llvm::StringRef loopClauseName, llvm::StringRef kernelsClauseName,
+ llvm::function_ref<bool(mlir::acc::KernelsOp)> hasKernelsClause) {
+ auto kernelsOp =
+ mlir::dyn_cast_if_present<mlir::acc::KernelsOp>(parentCompute);
+ if (!kernelsOp || !hasKernelsClause(kernelsOp))
+ return;
+
+ llvm::StringRef dirName =
+ combinedConstructs == mlir::acc::CombinedConstructsType::KernelsLoop
+ ? "KERNELS LOOP"
+ : "KERNELS";
+ fir::emitFatalError(loc,
+ llvm::Twine("'") + loopClauseName +
+ "(value)' not allowed in " + dirName +
+ " region that has a " + kernelsClauseName + " clause",
+ /*genCrashDiag=*/false);
+}
+
static mlir::acc::LoopOp createLoopOp(
Fortran::lower::AbstractConverter &converter,
mlir::Location currentLocation,
@@ -2384,12 +2440,40 @@ static mlir::acc::LoopOp createLoopOp(
crtDeviceTypes.push_back(mlir::acc::DeviceTypeAttr::get(
builder.getContext(), mlir::acc::DeviceType::None));
+ // A valued gang/worker/vector clause is only allowed when the loop is
+ // associated with a kernels construct, and then only when the kernels
+ // construct does not already specify the corresponding size clause.
+ mlir::Operation *parentCompute =
+ mlir::acc::getEnclosingComputeOp(*builder.getBlock()->getParent());
+ bool isKernels =
+ mlir::isa_and_present<mlir::acc::KernelsOp>(parentCompute) ||
+ combinedConstructs == mlir::acc::CombinedConstructsType::KernelsLoop;
+
for (const Fortran::parser::AccClause &clause : accClauseList.v) {
mlir::Location clauseLocation = converter.genLocation(clause.source);
if (const auto *gangClause =
std::get_if<Fortran::parser::AccClause::Gang>(&clause.u)) {
if (gangClause->v) {
const Fortran::parser::AccGangArgList &x = *gangClause->v;
+ // Only the num argument is restricted to kernels. The static and dim
+ // arguments are allowed on any loop.
+ bool hasNumArg =
+ llvm::any_of(x.v, [](const Fortran::parser::AccGangArg &gangArg) {
+ return std::holds_alternative<Fortran::parser::AccGangArg::Num>(
+ gangArg.u);
+ });
+ if (hasNumArg) {
+ if (!isKernels)
+ checkLoopLevelClauseValueInKernels(builder, parentCompute,
+ clauseLocation,
+ combinedConstructs, "Gang");
+ else
+ checkLoopLevelClauseConflictsWithKernels(
+ parentCompute, clauseLocation, combinedConstructs, "Gang",
+ "NUM_GANGS", [](mlir::acc::KernelsOp op) {
+ return !op.getNumGangs().empty();
+ });
+ }
mlir::SmallVector<mlir::Value> gangValues;
mlir::SmallVector<mlir::Attribute> gangArgs;
for (const Fortran::parser::AccGangArg &gangArg : x.v) {
@@ -2438,6 +2522,16 @@ static mlir::acc::LoopOp createLoopOp(
} else if (const auto *workerClause =
std::get_if<Fortran::parser::AccClause::Worker>(&clause.u)) {
if (workerClause->v) {
+ if (!isKernels)
+ checkLoopLevelClauseValueInKernels(builder, parentCompute,
+ clauseLocation, combinedConstructs,
+ "Worker");
+ else
+ checkLoopLevelClauseConflictsWithKernels(
+ parentCompute, clauseLocation, combinedConstructs, "Worker",
+ "NUM_WORKERS", [](mlir::acc::KernelsOp op) {
+ return !op.getNumWorkers().empty();
+ });
mlir::Value workerNumValue = fir::getBase(converter.genExprValue(
*Fortran::semantics::GetExpr(*workerClause->v), stmtCtx));
for (auto crtDeviceTypeAttr : crtDeviceTypes) {
@@ -2451,6 +2545,16 @@ static mlir::acc::LoopOp createLoopOp(
} else if (const auto *vectorClause =
std::get_if<Fortran::parser::AccClause::Vector>(&clause.u)) {
if (vectorClause->v) {
+ if (!isKernels)
+ checkLoopLevelClauseValueInKernels(builder, parentCompute,
+ clauseLocation, combinedConstructs,
+ "Vector");
+ else
+ checkLoopLevelClauseConflictsWithKernels(
+ parentCompute, clauseLocation, combinedConstructs, "Vector",
+ "VECTOR_LENGTH", [](mlir::acc::KernelsOp op) {
+ return !op.getVectorLength().empty();
+ });
mlir::Value vectorValue = fir::getBase(converter.genExprValue(
*Fortran::semantics::GetExpr(*vectorClause->v), stmtCtx));
for (auto crtDeviceTypeAttr : crtDeviceTypes) {
diff --git a/flang/test/Lower/OpenACC/acc-loop-level-clause-value.f90 b/flang/test/Lower/OpenACC/acc-loop-level-clause-value.f90
new file mode 100644
index 0000000000000..2c817e1ab308b
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-loop-level-clause-value.f90
@@ -0,0 +1,395 @@
+! Valued gang/worker/vector on a loop are only allowed when the loop is
+! associated with kernels, and then only when that kernels construct does not
+! already specify the matching size clause.
+
+! RUN: split-file %s %t
+
+! Non-kernels: standalone loop
+! RUN: not bbc -fopenacc -emit-hlfir %t/loop-gang.f90 -o - 2>&1 | FileCheck %s --check-prefix=LOOP-GANG
+! RUN: not bbc -fopenacc -emit-hlfir %t/loop-worker.f90 -o - 2>&1 | FileCheck %s --check-prefix=LOOP-WORKER
+! RUN: not bbc -fopenacc -emit-hlfir %t/loop-vector.f90 -o - 2>&1 | FileCheck %s --check-prefix=LOOP-VECTOR
+
+! Non-kernels: combined constructs
+! RUN: not bbc -fopenacc -emit-hlfir %t/parallel-loop-gang.f90 -o - 2>&1 | FileCheck %s --check-prefix=PLOOP-GANG
+! RUN: not bbc -fopenacc -emit-hlfir %t/parallel-loop-worker.f90 -o - 2>&1 | FileCheck %s --check-prefix=PLOOP-WORKER
+! RUN: not bbc -fopenacc -emit-hlfir %t/parallel-loop-vector.f90 -o - 2>&1 | FileCheck %s --check-prefix=PLOOP-VECTOR
+! RUN: not bbc -fopenacc -emit-hlfir %t/serial-loop-gang.f90 -o - 2>&1 | FileCheck %s --check-prefix=SLOOP-GANG
+! RUN: not bbc -fopenacc -emit-hlfir %t/serial-loop-worker.f90 -o - 2>&1 | FileCheck %s --check-prefix=SLOOP-WORKER
+! RUN: not bbc -fopenacc -emit-hlfir %t/serial-loop-vector.f90 -o - 2>&1 | FileCheck %s --check-prefix=SLOOP-VECTOR
+
+! Non-kernels: nested loop inside a compute construct
+! RUN: not bbc -fopenacc -emit-hlfir %t/parallel-nested-gang.f90 -o - 2>&1 | FileCheck %s --check-prefix=PAR-GANG
+! RUN: not bbc -fopenacc -emit-hlfir %t/parallel-nested-worker.f90 -o - 2>&1 | FileCheck %s --check-prefix=PAR-WORKER
+! RUN: not bbc -fopenacc -emit-hlfir %t/parallel-nested-vector.f90 -o - 2>&1 | FileCheck %s --check-prefix=PAR-VECTOR
+! RUN: not bbc -fopenacc -emit-hlfir %t/serial-nested-gang.f90 -o - 2>&1 | FileCheck %s --check-prefix=SER-GANG
+! RUN: not bbc -fopenacc -emit-hlfir %t/serial-nested-worker.f90 -o - 2>&1 | FileCheck %s --check-prefix=SER-WORKER
+! RUN: not bbc -fopenacc -emit-hlfir %t/serial-nested-vector.f90 -o - 2>&1 | FileCheck %s --check-prefix=SER-VECTOR
+
+! Non-kernels: orphan loop in an acc routine
+! RUN: not bbc -fopenacc -emit-hlfir %t/routine-gang.f90 -o - 2>&1 | FileCheck %s --check-prefix=RTN-GANG
+! RUN: not bbc -fopenacc -emit-hlfir %t/routine-worker.f90 -o - 2>&1 | FileCheck %s --check-prefix=RTN-WORKER
+! RUN: not bbc -fopenacc -emit-hlfir %t/routine-vector.f90 -o - 2>&1 | FileCheck %s --check-prefix=RTN-VECTOR
+
+! Kernels with a conflicting size clause
+! RUN: not bbc -fopenacc -emit-hlfir %t/kernels-num-gangs.f90 -o - 2>&1 | FileCheck %s --check-prefix=K-NG
+! RUN: not bbc -fopenacc -emit-hlfir %t/kernels-num-workers.f90 -o - 2>&1 | FileCheck %s --check-prefix=K-NW
+! RUN: not bbc -fopenacc -emit-hlfir %t/kernels-vector-length.f90 -o - 2>&1 | FileCheck %s --check-prefix=K-VL
+! RUN: not bbc -fopenacc -emit-hlfir %t/kernels-loop-num-gangs.f90 -o - 2>&1 | FileCheck %s --check-prefix=KL-NG
+! RUN: not bbc -fopenacc -emit-hlfir %t/kernels-loop-num-workers.f90 -o - 2>&1 | FileCheck %s --check-prefix=KL-NW
+! RUN: not bbc -fopenacc -emit-hlfir %t/kernels-loop-vector-length.f90 -o - 2>&1 | FileCheck %s --check-prefix=KL-VL
+
+! Allowed: kernels without a conflicting size clause, and bare clauses
+! RUN: bbc -fopenacc -emit-hlfir %t/allowed.f90 -o - | FileCheck %s --check-prefix=OK
+
+! LOOP-GANG: 'Gang(value)' not allowed in LOOP directive
+! LOOP-WORKER: 'Worker(value)' not allowed in LOOP directive
+! LOOP-VECTOR: 'Vector(value)' not allowed in LOOP directive
+! PLOOP-GANG: 'Gang(value)' not allowed in PARALLEL LOOP directive
+! PLOOP-WORKER: 'Worker(value)' not allowed in PARALLEL LOOP directive
+! PLOOP-VECTOR: 'Vector(value)' not allowed in PARALLEL LOOP directive
+! SLOOP-GANG: 'Gang(value)' not allowed in SERIAL LOOP directive
+! SLOOP-WORKER: 'Worker(value)' not allowed in SERIAL LOOP directive
+! SLOOP-VECTOR: 'Vector(value)' not allowed in SERIAL LOOP directive
+! PAR-GANG: 'Gang(value)' not allowed in PARALLEL LOOP directive
+! PAR-WORKER: 'Worker(value)' not allowed in PARALLEL LOOP directive
+! PAR-VECTOR: 'Vector(value)' not allowed in PARALLEL LOOP directive
+! SER-GANG: 'Gang(value)' not allowed in SERIAL LOOP directive
+! SER-WORKER: 'Worker(value)' not allowed in SERIAL LOOP directive
+! SER-VECTOR: 'Vector(value)' not allowed in SERIAL LOOP directive
+! RTN-GANG: 'Gang(value)' not allowed in subprogram compiled with ROUTINE directive
+! RTN-WORKER: 'Worker(value)' not allowed in subprogram compiled with ROUTINE directive
+! RTN-VECTOR: 'Vector(value)' not allowed in subprogram compiled with ROUTINE directive
+! K-NG: 'Gang(value)' not allowed in KERNELS region that has a NUM_GANGS clause
+! K-NW: 'Worker(value)' not allowed in KERNELS region that has a NUM_WORKERS clause
+! K-VL: 'Vector(value)' not allowed in KERNELS region that has a VECTOR_LENGTH clause
+! KL-NG: 'Gang(value)' not allowed in KERNELS LOOP region that has a NUM_GANGS clause
+! KL-NW: 'Worker(value)' not allowed in KERNELS LOOP region that has a NUM_WORKERS clause
+! KL-VL: 'Vector(value)' not allowed in KERNELS LOOP region that has a VECTOR_LENGTH clause
+
+!--- loop-gang.f90
+subroutine loop_gang(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc loop gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- loop-worker.f90
+subroutine loop_worker(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc loop worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- loop-vector.f90
+subroutine loop_vector(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc loop vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- parallel-loop-gang.f90
+subroutine parallel_loop_gang(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc parallel loop gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- parallel-loop-worker.f90
+subroutine parallel_loop_worker(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc parallel loop worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- parallel-loop-vector.f90
+subroutine parallel_loop_vector(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc parallel loop vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- serial-loop-gang.f90
+subroutine serial_loop_gang(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc serial loop gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- serial-loop-worker.f90
+subroutine serial_loop_worker(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc serial loop worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- serial-loop-vector.f90
+subroutine serial_loop_vector(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc serial loop vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- parallel-nested-gang.f90
+subroutine parallel_nested_gang(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc parallel
+ !$acc loop gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end parallel
+end subroutine
+
+!--- parallel-nested-worker.f90
+subroutine parallel_nested_worker(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc parallel
+ !$acc loop worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end parallel
+end subroutine
+
+!--- parallel-nested-vector.f90
+subroutine parallel_nested_vector(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc parallel
+ !$acc loop vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end parallel
+end subroutine
+
+!--- serial-nested-gang.f90
+subroutine serial_nested_gang(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc serial
+ !$acc loop gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end serial
+end subroutine
+
+!--- serial-nested-worker.f90
+subroutine serial_nested_worker(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc serial
+ !$acc loop worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end serial
+end subroutine
+
+!--- serial-nested-vector.f90
+subroutine serial_nested_vector(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc serial
+ !$acc loop vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end serial
+end subroutine
+
+!--- routine-gang.f90
+subroutine routine_gang(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc routine
+ !$acc loop gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- routine-worker.f90
+subroutine routine_worker(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc routine
+ !$acc loop worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- routine-vector.f90
+subroutine routine_vector(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc routine
+ !$acc loop vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- kernels-num-gangs.f90
+subroutine kernels_num_gangs(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc kernels num_gangs(8)
+ !$acc loop gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end kernels
+end subroutine
+
+!--- kernels-num-workers.f90
+subroutine kernels_num_workers(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc kernels num_workers(128)
+ !$acc loop worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end kernels
+end subroutine
+
+!--- kernels-vector-length.f90
+subroutine kernels_vector_length(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc kernels vector_length(128)
+ !$acc loop vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end kernels
+end subroutine
+
+!--- kernels-loop-num-gangs.f90
+subroutine kernels_loop_num_gangs(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc kernels loop num_gangs(8) gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- kernels-loop-num-workers.f90
+subroutine kernels_loop_num_workers(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc kernels loop num_workers(128) worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- kernels-loop-vector-length.f90
+subroutine kernels_loop_vector_length(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc kernels loop vector_length(128) vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+
+!--- allowed.f90
+subroutine allowed_kernels_valued(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc kernels
+ !$acc loop gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc loop worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc loop vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end kernels
+end subroutine
+! OK-LABEL: func.func @_QPallowed_kernels_valued
+! OK: acc.kernels
+! OK: acc.loop {{.*}}gang({num=%{{.*}} : i32})
+! OK: acc.loop {{.*}}worker(%{{.*}} : i32)
+! OK: acc.loop {{.*}}vector(%{{.*}} : i32)
+
+subroutine allowed_kernels_loop_valued(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc kernels loop gang(8)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc kernels loop worker(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc kernels loop vector(128)
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+end subroutine
+! OK-LABEL: func.func @_QPallowed_kernels_loop_valued
+! OK: acc.kernels {{.*}}combined
+! OK: acc.loop {{.*}}gang({num=%{{.*}} : i32})
+! OK: acc.loop {{.*}}worker(%{{.*}} : i32)
+! OK: acc.loop {{.*}}vector(%{{.*}} : i32)
+
+subroutine allowed_bare_and_size_clause(a, n)
+ integer :: i, n
+ real :: a(n)
+ !$acc parallel loop gang worker vector
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc kernels num_gangs(8) num_workers(128) vector_length(128)
+ !$acc loop gang worker vector
+ do i = 1, n
+ a(i) = a(i) + 1
+ end do
+ !$acc end kernels
+end subroutine
+! OK-LABEL: func.func @_QPallowed_bare_and_size_clause
+! OK: acc.parallel
+! OK: acc.loop {{.*}}gang
+! OK: acc.kernels {{.*}}num_gangs
+! OK: acc.loop {{.*}}gang
diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90
index 2a00f55b08751..3978f29dbf1fc 100644
--- a/flang/test/Lower/OpenACC/acc-loop.f90
+++ b/flang/test/Lower/OpenACC/acc-loop.f90
@@ -70,38 +70,6 @@ program acc_loop
! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) implicit(true) name("i") -> !fir.ref<i32>
! CHECK: acc.loop gang private(%[[PRIVATE_I]] : !fir.ref<i32>) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) {
! CHECK: acc.yield
-! CHECK-NEXT: } inclusiveUpperbound(array<i1: true>) independent
-
- !$acc loop gang(num: 8)
- DO i = 1, n
- a(i) = b(i)
- END DO
-
-! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32
-! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref<i32>) recipe(@privatization_ref_i32) implicit(true) name("i") -> !fir.ref<i32>
-! CHECK: acc.loop gang({num=[[GANGNUM1]] : i32}) private(%[[PRIVATE_I...
[truncated]
|
clementval
left a comment
There was a problem hiding this comment.
This would be better to be done in semantic checking in check-acc-structure.
| @@ -1030,6 +1128,9 @@ void AccStructureChecker::Enter(const parser::AccClause::Vector &g) { | |||
| if (GetContext().directive != llvm::acc::Directive::ACCD_routine) { | |||
| CheckAllowedOncePerGroup(crtClause, llvm::acc::Clause::ACCC_device_type); | |||
| } | |||
| if (g.v) { | |||
| CheckLoopLevelClauseValue("Vector"); | |||
There was a problem hiding this comment.
Semantic message always makes the clause or directive in full uppercase.
You can use parser::ToUpperCaseLetters(getClauseName([clause](llvm::acc::Clause::ACCC_vector)).str()
Same for the worker and gang
clementval
left a comment
There was a problem hiding this comment.
LGTM. Thanks for addressing the comments.
gang(num:),worker(n), andvector(n)are only valid on a loop associated with kernels, and then only if that kernels construct does not already specifynum_gangs,num_workers, orvector_length.