diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp index 25bc1de56120f..5ef60459a5dfc 100644 --- a/flang/lib/Semantics/check-acc-structure.cpp +++ b/flang/lib/Semantics/check-acc-structure.cpp @@ -157,7 +157,9 @@ void AccStructureChecker::Enter(const parser::AccClause &x) { SetContextClause(x); } -void AccStructureChecker::Leave(const parser::AccClauseList &) {} +void AccStructureChecker::Leave(const parser::AccClauseList &) { + CheckLoopLevelClauseKernelsConflicts(); +} void AccStructureChecker::Enter(const parser::OpenACCBlockConstruct &x) { const auto &beginBlockDir{std::get(x.t)}; @@ -293,6 +295,105 @@ std::optional AccStructureChecker::getGangDimensionSize( return std::nullopt; } +void AccStructureChecker::CheckLoopLevelClauseValue( + llvm::StringRef clauseName) { + if (GetContext().directive == llvm::acc::ACCD_kernels_loop || + IsInsideKernelsConstruct()) + return; + + if (GetContext().directive == llvm::acc::ACCD_routine || + HasOpenACCRoutineDirective( + &context_.FindScope(GetContext().clauseSource))) { + context_.Say(GetContext().clauseSource, + "'%s(value)' not allowed in subprogram compiled with ROUTINE directive"_err_en_US, + clauseName.str()); + return; + } + + llvm::acc::Directive dir{GetContext().directive}; + if (dir == llvm::acc::ACCD_loop) { + if (std::optional parent{ + getParentComputeConstruct()}) { + if (*parent == llvm::acc::ACCD_parallel) + dir = llvm::acc::ACCD_parallel_loop; + else if (*parent == llvm::acc::ACCD_serial) + dir = llvm::acc::ACCD_serial_loop; + } + } + context_.Say(GetContext().clauseSource, + "'%s(value)' not allowed in %s directive"_err_en_US, clauseName.str(), + parser::ToUpperCaseLetters(getDirectiveName(dir).str())); +} + +static bool AccClauseHasVectorValue(const parser::AccClause &clause) { + const auto *vectorClause{std::get_if(&clause.u)}; + return vectorClause && vectorClause->v.has_value(); +} + +static bool AccClauseHasWorkerValue(const parser::AccClause &clause) { + const auto *workerClause{std::get_if(&clause.u)}; + return workerClause && workerClause->v.has_value(); +} + +static bool AccClauseHasGangNum(const parser::AccClause &clause) { + const auto *gangClause{std::get_if(&clause.u)}; + if (!gangClause || !gangClause->v) + return false; + for (const parser::AccGangArg &gangArg : gangClause->v->v) + if (std::get_if(&gangArg.u)) + return true; + return false; +} + +void AccStructureChecker::CheckLoopLevelClauseKernelsConflicts() { + if (dirContext_.empty()) + return; + if (GetContext().directive != llvm::acc::ACCD_kernels_loop && + !IsInsideKernelsConstruct()) + return; + + auto hasKernelsSizeClause{[&](llvm::acc::Clause sizeClause) { + for (DirectiveContext &ctx : dirContext_) { + if ((ctx.directive == llvm::acc::ACCD_kernels || + ctx.directive == llvm::acc::ACCD_kernels_loop) && + FindClause(ctx, sizeClause)) + return true; + } + return false; + }}; + + llvm::acc::Directive kernelsDir{ + GetContext().directive == llvm::acc::ACCD_kernels_loop + ? llvm::acc::ACCD_kernels_loop + : llvm::acc::ACCD_kernels}; + std::string dirName{ + parser::ToUpperCaseLetters(getDirectiveName(kernelsDir).str())}; + + auto emitConflicts{[&](llvm::acc::Clause loopClause, + llvm::acc::Clause sizeClause, + bool (*isValued)(const parser::AccClause &)) { + if (!hasKernelsSizeClause(sizeClause)) + return; + for (const auto &entry : FindClauses(loopClause)) { + const parser::AccClause *clause{entry.second}; + if (clause && isValued(*clause)) { + context_.Say(clause->source, + "'%s(value)' not allowed in %s region that has a %s clause"_err_en_US, + parser::ToUpperCaseLetters(getClauseName(loopClause).str()), + dirName, + parser::ToUpperCaseLetters(getClauseName(sizeClause).str())); + } + } + }}; + + emitConflicts(llvm::acc::Clause::ACCC_vector, + llvm::acc::Clause::ACCC_vector_length, AccClauseHasVectorValue); + emitConflicts(llvm::acc::Clause::ACCC_worker, + llvm::acc::Clause::ACCC_num_workers, AccClauseHasWorkerValue); + emitConflicts(llvm::acc::Clause::ACCC_gang, llvm::acc::Clause::ACCC_num_gangs, + AccClauseHasGangNum); +} + void AccStructureChecker::CheckNotInSameOrSubLevelLoopConstruct() { for (std::size_t i = dirContext_.size() - 1; i > 0; --i) { auto &parent{dirContext_[i - 1]}; @@ -1030,6 +1131,10 @@ 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( + parser::ToUpperCaseLetters(getClauseName(crtClause).str())); + } } void AccStructureChecker::Enter(const parser::AccClause::Worker &g) { @@ -1042,6 +1147,10 @@ void AccStructureChecker::Enter(const parser::AccClause::Worker &g) { if (GetContext().directive != llvm::acc::Directive::ACCD_routine) { CheckAllowedOncePerGroup(crtClause, llvm::acc::Clause::ACCC_device_type); } + if (g.v) { + CheckLoopLevelClauseValue( + parser::ToUpperCaseLetters(getClauseName(crtClause).str())); + } } void AccStructureChecker::Enter(const parser::AccClause::Tile &g) { @@ -1090,6 +1199,15 @@ void AccStructureChecker::Enter(const parser::AccClause::Gang &g) { context_.Say(GetContext().clauseSource, "The num argument is not allowed when dim is specified"_err_en_US); } + + // Only the num argument is restricted to kernels. The static and dim + // arguments are allowed on any loop. On ROUTINE, num is already diagnosed + // above as only dim being allowed. + if (hasNum && + GetContext().directive != llvm::acc::Directive::ACCD_routine) { + CheckLoopLevelClauseValue( + parser::ToUpperCaseLetters(getClauseName(crtClause).str())); + } } } diff --git a/flang/lib/Semantics/check-acc-structure.h b/flang/lib/Semantics/check-acc-structure.h index 4f4019b3db9b8..135f34abc8a3c 100644 --- a/flang/lib/Semantics/check-acc-structure.h +++ b/flang/lib/Semantics/check-acc-structure.h @@ -117,6 +117,8 @@ class AccStructureChecker std::optional getGangDimensionSize( DirectiveContext &dirContext); void CheckNotInSameOrSubLevelLoopConstruct(); + void CheckLoopLevelClauseValue(llvm::StringRef clauseName); + void CheckLoopLevelClauseKernelsConflicts(); void CheckRoutineCallInLoop(const Symbol &); void CheckMultipleOccurrenceInDeclare( const parser::AccObjectList &, llvm::acc::Clause); diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90 index 2a00f55b08751..2858a1cfbff0e 100644 --- a/flang/test/Lower/OpenACC/acc-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-loop.f90 @@ -72,6 +72,9 @@ program acc_loop ! CHECK: acc.yield ! CHECK-NEXT: } inclusiveUpperbound(array) independent +! A GANG clause with a num argument requires the loop to be associated with a +! kernels construct, which also makes the loop default to auto. + !$acc kernels !$acc loop gang(num: 8) DO i = 1, n a(i) = b(i) @@ -81,7 +84,7 @@ program acc_loop ! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) recipe(@privatization_ref_i32) implicit(true) name("i") -> !fir.ref ! CHECK: acc.loop gang({num=[[GANGNUM1]] : i32}) private(%[[PRIVATE_I]] : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent +! CHECK-NEXT: } inclusiveUpperbound(array) auto_ !$acc loop gang(num: gangNum) DO i = 1, n @@ -92,17 +95,18 @@ program acc_loop ! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) recipe(@privatization_ref_i32) implicit(true) name("i") -> !fir.ref ! CHECK: acc.loop gang({num=[[GANGNUM2]] : i32}) private(%[[PRIVATE_I]] : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent +! CHECK-NEXT: } inclusiveUpperbound(array) auto_ !$acc loop gang(num: gangNum, static: gangStatic) DO i = 1, n a(i) = b(i) END DO + !$acc end kernels ! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) recipe(@privatization_ref_i32) implicit(true) name("i") -> !fir.ref ! CHECK: acc.loop gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) private(%[[PRIVATE_I]] : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent +! CHECK-NEXT: } inclusiveUpperbound(array) auto_ !$acc loop vector DO i = 1, n @@ -114,6 +118,9 @@ program acc_loop ! CHECK: acc.yield ! CHECK-NEXT: } inclusiveUpperbound(array) independent +! A VECTOR clause with a value requires the loop to be associated with a +! kernels construct, which also makes the loop default to auto. + !$acc kernels !$acc loop vector(128) DO i = 1, n a(i) = b(i) @@ -123,18 +130,19 @@ program acc_loop ! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) recipe(@privatization_ref_i32) implicit(true) name("i") -> !fir.ref ! CHECK: acc.loop vector([[CONSTANT128]] : i32) private(%[[PRIVATE_I]] : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent +! CHECK-NEXT: } inclusiveUpperbound(array) auto_ !$acc loop vector(vectorLength) DO i = 1, n a(i) = b(i) END DO + !$acc end kernels ! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) recipe(@privatization_ref_i32) implicit(true) name("i") -> !fir.ref ! CHECK: acc.loop vector([[VECTORLENGTH]] : i32) private(%[[PRIVATE_I]] : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent +! CHECK-NEXT: } inclusiveUpperbound(array) auto_ !$acc loop worker DO i = 1, n @@ -146,16 +154,20 @@ program acc_loop ! CHECK: acc.yield ! CHECK-NEXT: } inclusiveUpperbound(array) independent +! A WORKER clause with a value requires the loop to be associated with a +! kernels construct, which also makes the loop default to auto. + !$acc kernels !$acc loop worker(128) DO i = 1, n a(i) = b(i) END DO + !$acc end kernels ! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 ! CHECK: %[[PRIVATE_I:.*]] = acc.private varPtr(%{{.*}} : !fir.ref) recipe(@privatization_ref_i32) implicit(true) name("i") -> !fir.ref ! CHECK: acc.loop worker([[WORKER128]] : i32) private(%[[PRIVATE_I]] : !fir.ref) control(%arg0 : i32) = (%{{.*}} : i32) to (%{{.*}} : i32) step (%{{.*}} : i32) { ! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent +! CHECK-NEXT: } inclusiveUpperbound(array) auto_ !$acc loop private(c) DO i = 1, n @@ -364,9 +376,13 @@ program acc_loop 100 continue ! CHECK: acc.loop +! A GANG clause with a num argument requires the loop to be associated with a +! kernels construct. + !$acc kernels !$acc loop gang device_type(nvidia) gang(8) DO i = 1, n END DO + !$acc end kernels ! CHECK: acc.loop gang([#acc.device_type], {num=%c8{{.*}} : i32} [#acc.device_type]) diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 index be39c4b035209..8b163593fede7 100644 --- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -509,43 +509,8 @@ subroutine acc_parallel_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{.*}} - !$acc parallel loop gang(num: 8) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.parallel {{.*}} { -! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 -! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} - - !$acc parallel loop gang(num: gangNum) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.parallel {{.*}} { -! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref -! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} - - !$acc parallel loop gang(num: gangNum, static: gangStatic) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.parallel {{.*}} { -! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} +! A GANG clause with a num argument is only allowed on a loop associated with +! a kernels construct, so it is covered by acc-kernels-loop.f90 instead. !$acc parallel loop vector DO i = 1, n @@ -559,32 +524,8 @@ subroutine acc_parallel_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{.*}} - !$acc parallel loop vector(128) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.parallel {{.*}} { -! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} - - !$acc parallel loop vector(vectorLength) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.parallel {{.*}} { -! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref -! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { -! CHECK-NOT: fir.do_loop -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} +! A VECTOR clause with a value is only allowed on a loop associated with a +! kernels construct, so it is covered by acc-kernels-loop.f90 instead. !$acc parallel loop worker DO i = 1, n @@ -599,19 +540,8 @@ subroutine acc_parallel_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{.*}} - !$acc parallel loop worker(128) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.parallel {{.*}}{ -! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { -! CHECK-NOT: fir.do_loop -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) independent -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} +! A WORKER clause with a value is only allowed on a loop associated with a +! kernels construct, so it is covered by acc-kernels-loop.f90 instead. !$acc parallel loop collapse(2) DO i = 1, n diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 index ebcf7fcd52477..46ab7b3d37302 100644 --- a/flang/test/Lower/OpenACC/acc-serial-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -446,43 +446,8 @@ subroutine acc_serial_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{.*}} - !$acc serial loop gang(num: 8) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.serial {{.*}} { -! CHECK: [[GANGNUM1:%.*]] = arith.constant 8 : i32 -! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM1]] : i32}) {{.*}} { -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) auto_ -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} - - !$acc serial loop gang(num: gangNum) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.serial {{.*}} { -! CHECK: [[GANGNUM2:%.*]] = fir.load %{{.*}} : !fir.ref -! CHECK: acc.loop {{.*}} gang({num=[[GANGNUM2]] : i32}) {{.*}} { -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) auto_ -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} - - !$acc serial loop gang(num: gangNum, static: gangStatic) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.serial {{.*}} { -! CHECK: acc.loop {{.*}} gang({num=%{{.*}} : i32, static=%{{.*}} : i32}) {{.*}} { -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) auto_ -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} +! A GANG clause with a num argument is only allowed on a loop associated with +! a kernels construct, so it is covered by acc-kernels-loop.f90 instead. !$acc serial loop vector DO i = 1, n @@ -496,31 +461,8 @@ subroutine acc_serial_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{.*}} - !$acc serial loop vector(128) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.serial {{.*}} { -! CHECK: [[CONSTANT128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop {{.*}} vector([[CONSTANT128]] : i32) {{.*}} { -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) auto_ -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} - - !$acc serial loop vector(vectorLength) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.serial {{.*}} { -! CHECK: [[VECTORLENGTH:%.*]] = fir.load %{{.*}} : !fir.ref -! CHECK: acc.loop {{.*}} vector([[VECTORLENGTH]] : i32) {{.*}} { -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) auto_ -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} +! A VECTOR clause with a value is only allowed on a loop associated with a +! kernels construct, so it is covered by acc-kernels-loop.f90 instead. !$acc serial loop worker DO i = 1, n @@ -534,18 +476,8 @@ subroutine acc_serial_loop ! CHECK: acc.yield ! CHECK-NEXT: }{{.*}} - !$acc serial loop worker(128) - DO i = 1, n - a(i) = b(i) - END DO - -! CHECK: acc.serial {{.*}} { -! CHECK: [[WORKER128:%.*]] = arith.constant 128 : i32 -! CHECK: acc.loop {{.*}} worker([[WORKER128]] : i32) {{.*}} { -! CHECK: acc.yield -! CHECK-NEXT: } inclusiveUpperbound(array) auto_ -! CHECK: acc.yield -! CHECK-NEXT: }{{.*}} +! A WORKER clause with a value is only allowed on a loop associated with a +! kernels construct, so it is covered by acc-kernels-loop.f90 instead. !$acc serial loop collapse(2) DO i = 1, n diff --git a/flang/test/Parser/acc-unparse.f90 b/flang/test/Parser/acc-unparse.f90 index 97608a29b87de..38c51e4a6cc39 100644 --- a/flang/test/Parser/acc-unparse.f90 +++ b/flang/test/Parser/acc-unparse.f90 @@ -47,6 +47,9 @@ subroutine acc_loop() end do ! CHECK: !$ACC LOOP GANG +! A GANG num argument requires the loop to be associated with a kernels +! construct. + !$acc kernels !$acc loop gang(gangNum) do i = 1, 10 a(i) = i @@ -57,6 +60,7 @@ subroutine acc_loop() do i = 1, 10 a(i) = i end do + !$acc end kernels ! CHECK: !$ACC LOOP GANG(NUM:gangnum) !$acc loop gang(dim: gangDim) @@ -108,6 +112,9 @@ subroutine acc_loop() end do ! CHECK: !$ACC LOOP GANG(DIM:gangdim) +! A GANG num argument and a valued WORKER/VECTOR clause require the loop to be +! associated with a kernels construct. + !$acc kernels !$acc loop gang(num : gangNum) do i = 1, 10 a(i) = i @@ -124,6 +131,7 @@ subroutine acc_loop() do i = 1, 10 a(i) = i end do + !$acc end kernels ! CHECK: !$ACC LOOP VECTOR(128_4) end subroutine diff --git a/flang/test/Semantics/OpenACC/acc-loop-vector-value.f90 b/flang/test/Semantics/OpenACC/acc-loop-vector-value.f90 new file mode 100644 index 0000000000000..ce5fd95da77e3 --- /dev/null +++ b/flang/test/Semantics/OpenACC/acc-loop-vector-value.f90 @@ -0,0 +1,513 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenacc + +! A VECTOR/WORKER clause with a value, or a GANG clause with a num argument, +! is only allowed on a loop associated with KERNELS, and then only when that +! KERNELS construct has no matching size clause (VECTOR_LENGTH/NUM_WORKERS/ +! NUM_GANGS). GANG dim and static arguments are allowed on any loop. + +subroutine loop_vector(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'VECTOR(value)' not allowed in LOOP directive + !$acc loop vector(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine parallel_loop_vector(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'VECTOR(value)' not allowed in PARALLEL LOOP directive + !$acc parallel loop vector(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine serial_loop_vector(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'VECTOR(value)' not allowed in SERIAL LOOP directive + !$acc serial loop vector(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine parallel_nested_vector(a, n) + integer :: i, n + real :: a(n) + !$acc parallel + !ERROR: 'VECTOR(value)' not allowed in PARALLEL LOOP directive + !$acc loop vector(128) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end parallel +end subroutine + +subroutine serial_nested_vector(a, n) + integer :: i, n + real :: a(n) + !$acc serial + !ERROR: 'VECTOR(value)' not allowed in SERIAL LOOP directive + !$acc loop vector(128) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end serial +end subroutine + +subroutine routine_vector(a, n) + !$acc routine vector + integer :: i, n + real :: a(n) + !ERROR: 'VECTOR(value)' not allowed in subprogram compiled with ROUTINE directive + !$acc loop vector(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine kernels_vector_length(a, n) + integer :: i, n + real :: a(n) + !$acc kernels vector_length(128) + !ERROR: 'VECTOR(value)' not allowed in KERNELS region that has a VECTOR_LENGTH clause + !$acc loop vector(128) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end kernels +end subroutine + +subroutine kernels_loop_vector_length(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'VECTOR(value)' not allowed in KERNELS LOOP region that has a VECTOR_LENGTH clause + !$acc kernels loop vector_length(128) vector(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine loop_worker(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'WORKER(value)' not allowed in LOOP directive + !$acc loop worker(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine parallel_loop_worker(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'WORKER(value)' not allowed in PARALLEL LOOP directive + !$acc parallel loop worker(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine serial_loop_worker(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'WORKER(value)' not allowed in SERIAL LOOP directive + !$acc serial loop worker(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine parallel_nested_worker(a, n) + integer :: i, n + real :: a(n) + !$acc parallel + !ERROR: 'WORKER(value)' not allowed in PARALLEL LOOP directive + !$acc loop worker(128) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end parallel +end subroutine + +subroutine serial_nested_worker(a, n) + integer :: i, n + real :: a(n) + !$acc serial + !ERROR: 'WORKER(value)' not allowed in SERIAL LOOP directive + !$acc loop worker(128) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end serial +end subroutine + +subroutine routine_worker(a, n) + !$acc routine worker + integer :: i, n + real :: a(n) + !ERROR: 'WORKER(value)' not allowed in subprogram compiled with ROUTINE directive + !$acc loop worker(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine kernels_num_workers(a, n) + integer :: i, n + real :: a(n) + !$acc kernels num_workers(128) + !ERROR: 'WORKER(value)' not allowed in KERNELS region that has a NUM_WORKERS clause + !$acc loop worker(128) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end kernels +end subroutine + +subroutine kernels_loop_num_workers(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'WORKER(value)' not allowed in KERNELS LOOP region that has a NUM_WORKERS clause + !$acc kernels loop num_workers(128) worker(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine loop_gang(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'GANG(value)' not allowed in LOOP directive + !$acc loop gang(8) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine parallel_loop_gang(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive + !$acc parallel loop gang(8) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine serial_loop_gang(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'GANG(value)' not allowed in SERIAL LOOP directive + !$acc serial loop gang(num: 8) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine parallel_nested_gang(a, n) + integer :: i, n + real :: a(n) + !$acc parallel + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive + !$acc loop gang(8) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end parallel +end subroutine + +subroutine serial_nested_gang(a, n) + integer :: i, n + real :: a(n) + !$acc serial + !ERROR: 'GANG(value)' not allowed in SERIAL LOOP directive + !$acc loop gang(8) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end serial +end subroutine + +subroutine routine_gang(a, n) + !$acc routine gang + integer :: i, n + real :: a(n) + !ERROR: 'GANG(value)' not allowed in subprogram compiled with ROUTINE directive + !$acc loop gang(8) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine kernels_num_gangs(a, n) + integer :: i, n + real :: a(n) + !$acc kernels num_gangs(8) + !ERROR: 'GANG(value)' not allowed in KERNELS region that has a NUM_GANGS clause + !$acc loop gang(8) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end kernels +end subroutine + +subroutine kernels_loop_num_gangs(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'GANG(value)' not allowed in KERNELS LOOP region that has a NUM_GANGS clause + !$acc kernels loop num_gangs(8) gang(8) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +! Size clause after the loop-level clause on the same combined directive. +subroutine kernels_loop_gang_then_num_gangs(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'GANG(value)' not allowed in KERNELS LOOP region that has a NUM_GANGS clause + !$acc kernels loop gang(8) num_gangs(8) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine kernels_loop_worker_then_num_workers(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'WORKER(value)' not allowed in KERNELS LOOP region that has a NUM_WORKERS clause + !$acc kernels loop worker(128) num_workers(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine kernels_loop_vector_then_vector_length(a, n) + integer :: i, n + real :: a(n) + !ERROR: 'VECTOR(value)' not allowed in KERNELS LOOP region that has a VECTOR_LENGTH clause + !$acc kernels loop vector(128) vector_length(128) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine allowed_kernels_valued(a, n) + integer :: i, n + real :: a(n) + !$acc kernels + !$acc loop vector(128) + 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 gang(8) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc loop vector + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc loop worker + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc loop gang + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end kernels + + !$acc kernels loop vector(128) + 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 gang(8) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine allowed_gang_dim_and_static(a, n) + integer :: i, n + real :: a(n) + !$acc loop gang(dim: 1) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc parallel + !$acc loop gang(static: *) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end parallel + !$acc parallel loop gang worker vector + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +! Non-constant integer expressions are still "valued" clauses. +subroutine nonconstant_loop_level_values(a, n, vl, wn, gn) + integer :: i, n, vl, wn, gn + real :: a(n) + !ERROR: 'VECTOR(value)' not allowed in LOOP directive + !$acc loop vector(vl) + do i = 1, n + a(i) = a(i) + 1 + end do + !ERROR: 'VECTOR(value)' not allowed in LOOP directive + !$acc loop vector(length: vl) + do i = 1, n + a(i) = a(i) + 1 + end do + !ERROR: 'WORKER(value)' not allowed in LOOP directive + !$acc loop worker(wn) + do i = 1, n + a(i) = a(i) + 1 + end do + !ERROR: 'WORKER(value)' not allowed in LOOP directive + !$acc loop worker(num: wn) + do i = 1, n + a(i) = a(i) + 1 + end do + !ERROR: 'GANG(value)' not allowed in LOOP directive + !$acc loop gang(gn) + do i = 1, n + a(i) = a(i) + 1 + end do + !ERROR: 'GANG(value)' not allowed in LOOP directive + !$acc loop gang(num: gn) + do i = 1, n + a(i) = a(i) + 1 + end do + !ERROR: 'VECTOR(value)' not allowed in PARALLEL LOOP directive + !$acc parallel loop vector(vl + 1) + do i = 1, n + a(i) = a(i) + 1 + end do + !ERROR: 'WORKER(value)' not allowed in SERIAL LOOP directive + !$acc serial loop worker(wn * 2) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc parallel + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive + !$acc loop gang(num: gn) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end parallel +end subroutine + +subroutine nonconstant_routine_vector(a, n, vl) + !$acc routine vector + integer :: i, n, vl + real :: a(n) + !ERROR: 'VECTOR(value)' not allowed in subprogram compiled with ROUTINE directive + !$acc loop vector(vl) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine nonconstant_kernels_conflicts(a, n, vl, wn, gn) + integer :: i, n, vl, wn, gn + real :: a(n) + !$acc kernels vector_length(vl) + !ERROR: 'VECTOR(value)' not allowed in KERNELS region that has a VECTOR_LENGTH clause + !$acc loop vector(vl) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end kernels + + !$acc kernels num_workers(wn) + !ERROR: 'WORKER(value)' not allowed in KERNELS region that has a NUM_WORKERS clause + !$acc loop worker(wn) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end kernels + + !$acc kernels num_gangs(gn) + !ERROR: 'GANG(value)' not allowed in KERNELS region that has a NUM_GANGS clause + !$acc loop gang(gn) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end kernels + + !ERROR: 'VECTOR(value)' not allowed in KERNELS LOOP region that has a VECTOR_LENGTH clause + !$acc kernels loop vector(vl) vector_length(vl) + do i = 1, n + a(i) = a(i) + 1 + end do + !ERROR: 'WORKER(value)' not allowed in KERNELS LOOP region that has a NUM_WORKERS clause + !$acc kernels loop worker(num: wn) num_workers(wn) + do i = 1, n + a(i) = a(i) + 1 + end do + !ERROR: 'GANG(value)' not allowed in KERNELS LOOP region that has a NUM_GANGS clause + !$acc kernels loop gang(num: gn) num_gangs(gn) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine + +subroutine allowed_kernels_nonconstant(a, n, vl, wn, gn) + integer :: i, n, vl, wn, gn + real :: a(n) + !$acc kernels + !$acc loop vector(vl) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc loop worker(wn) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc loop gang(gn) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc loop vector(length: vl) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc loop worker(num: wn) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc loop gang(num: gn) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc end kernels + + !$acc kernels loop vector(vl) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc kernels loop worker(wn) + do i = 1, n + a(i) = a(i) + 1 + end do + !$acc kernels loop gang(num: gn) + do i = 1, n + a(i) = a(i) + 1 + end do +end subroutine diff --git a/flang/test/Semantics/OpenACC/acc-loop.f90 b/flang/test/Semantics/OpenACC/acc-loop.f90 index 8e44423a6bb3e..0a5380a692b42 100644 --- a/flang/test/Semantics/OpenACC/acc-loop.f90 +++ b/flang/test/Semantics/OpenACC/acc-loop.f90 @@ -65,6 +65,7 @@ program openacc_loop_validity !$acc parallel !ERROR: At most one VECTOR clause can appear on the LOOP directive or in group separated by the DEVICE_TYPE clause + !ERROR: 'VECTOR(value)' not allowed in PARALLEL LOOP directive !$acc loop vector vector(128) do i = 1, N a(i) = 3.14d0 @@ -79,6 +80,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'VECTOR(value)' not allowed in PARALLEL LOOP directive !$acc loop vector(10) do i = 1, N a(i) = 3.14d0 @@ -86,6 +88,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'VECTOR(value)' not allowed in PARALLEL LOOP directive !$acc loop vector(vector_size) do i = 1, N a(i) = 3.14d0 @@ -93,6 +96,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'VECTOR(value)' not allowed in PARALLEL LOOP directive !$acc loop vector(length: vector_size) do i = 1, N a(i) = 3.14d0 @@ -101,6 +105,7 @@ program openacc_loop_validity !$acc parallel !ERROR: At most one WORKER clause can appear on the LOOP directive or in group separated by the DEVICE_TYPE clause + !ERROR: 'WORKER(value)' not allowed in PARALLEL LOOP directive !$acc loop worker worker(10) do i = 1, N a(i) = 3.14d0 @@ -115,6 +120,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'WORKER(value)' not allowed in PARALLEL LOOP directive !$acc loop worker(10) do i = 1, N a(i) = 3.14d0 @@ -122,6 +128,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'WORKER(value)' not allowed in PARALLEL LOOP directive !$acc loop worker(worker_size) do i = 1, N a(i) = 3.14d0 @@ -129,6 +136,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'WORKER(value)' not allowed in PARALLEL LOOP directive !$acc loop worker(num : worker_size) do i = 1, N a(i) = 3.14d0 @@ -137,29 +145,34 @@ program openacc_loop_validity !$acc parallel !ERROR: At most one GANG clause can appear on the LOOP directive or in group separated by the DEVICE_TYPE clause + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive !$acc loop gang gang(gang_size) do i = 1, N a(i) = 3.14d0 end do !$acc end parallel + !ERROR: 'GANG(value)' not allowed in LOOP directive !$acc loop gang device_type(default) gang(gang_size) do i = 1, N a(i) = 3.14d0 end do !ERROR: At most one GANG clause can appear on the PARALLEL LOOP directive or in group separated by the DEVICE_TYPE clause + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive !$acc parallel loop gang gang(gang_size) do i = 1, N a(i) = 3.14d0 end do + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive !$acc parallel loop gang device_type(default) gang(gang_size) do i = 1, N a(i) = 3.14d0 end do !$acc parallel + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive !$acc loop gang(gang_size) do i = 1, N a(i) = 3.14d0 @@ -167,6 +180,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive !$acc loop gang(num: gang_size) do i = 1, N a(i) = 3.14d0 @@ -174,6 +188,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive !$acc loop gang(gang_size, static:*) do i = 1, N a(i) = 3.14d0 @@ -181,6 +196,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive !$acc loop gang(num: gang_size, static:*) do i = 1, N a(i) = 3.14d0 @@ -188,6 +204,7 @@ program openacc_loop_validity !$acc end parallel !$acc parallel + !ERROR: 'GANG(value)' not allowed in PARALLEL LOOP directive !$acc loop gang(num: gang_size, static: gang_size) do i = 1, N a(i) = 3.14d0 @@ -368,6 +385,7 @@ program openacc_loop_validity end do !ERROR: The num argument is not allowed when dim is specified + !ERROR: 'GANG(value)' not allowed in LOOP directive !$acc loop gang(1, dim: 2) do i = 1, N end do @@ -392,14 +410,17 @@ program openacc_loop_validity end do !$acc end parallel + !ERROR: 'GANG(value)' not allowed in LOOP directive !$acc loop gang device_type(nvidia) gang(num: 8) DO i = 1, n END DO + !ERROR: 'VECTOR(value)' not allowed in LOOP directive !$acc loop vector device_type(default) vector(16) DO i = 1, n END DO + !ERROR: 'WORKER(value)' not allowed in LOOP directive !$acc loop worker device_type(*) worker(8) DO i = 1, n END DO