goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
+ if (ort == C_ORT_ACC && oacc_get_fn_attrib (current_function_decl)
+ && omp_find_clause (clauses, OMP_CLAUSE_GANG))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "gang reduction on an orphan loop");
+ remove = true;
+ break;
+ }
if (reduction_seen == 0)
reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
else if (reduction_seen != -2
field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
+ if (ort == C_ORT_ACC && oacc_get_fn_attrib (current_function_decl)
+ && omp_find_clause (clauses, OMP_CLAUSE_GANG))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "gang reduction on an orphan loop");
+ remove = true;
+ break;
+ }
if (reduction_seen == 0)
reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
else if (reduction_seen != -2
}
}
+static bool
+oacc_is_parallel (gfc_code *code)
+{
+ return code->op == EXEC_OACC_PARALLEL || code->op == EXEC_OACC_PARALLEL_LOOP;
+}
+
+static bool
+oacc_is_kernels (gfc_code *code)
+{
+ return code->op == EXEC_OACC_KERNELS || code->op == EXEC_OACC_KERNELS_LOOP;
+}
static gfc_statement
omp_code_to_statement (gfc_code *code)
if (!oacc_is_loop (code))
return;
+ if (code->op == EXEC_OACC_LOOP
+ && code->ext.omp_clauses->lists[OMP_LIST_REDUCTION]
+ && code->ext.omp_clauses->gang)
+ {
+ fortran_omp_context *c;
+ for (c = omp_current_ctx; c; c = c->previous)
+ if (!oacc_is_loop (c->code))
+ break;
+ if (c == NULL || !(oacc_is_parallel (c->code)
+ || oacc_is_kernels (c->code)))
+ gfc_error ("gang reduction on an orphan loop at %L", &code->loc);
+ }
+
if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
&& code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
OLF_TILE = 1u << 4, /* Tiled loop. */
+ OLF_REDUCTION = 1u << 5, /* Reduction loop. */
/* Explicitly specified loop axes. */
- OLF_DIM_BASE = 5,
+ OLF_DIM_BASE = 6,
OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
tag |= OLF_TILE;
break;
+ case OMP_CLAUSE_REDUCTION:
+ tag |= OLF_REDUCTION;
+ break;
+
default:
continue;
}
non-innermost available level. */
unsigned this_mask = GOMP_DIM_MASK (GOMP_DIM_GANG);
+ /* Orphan reductions cannot have gang partitioning. */
+ if ((loop->flags & OLF_REDUCTION)
+ && oacc_get_fn_attrib (current_function_decl)
+ && !lookup_attribute ("omp target entrypoint",
+ DECL_ATTRIBUTES (current_function_decl)))
+ this_mask = GOMP_DIM_MASK (GOMP_DIM_WORKER);
+
/* Find the first outermost available partition. */
while (this_mask <= outer_mask)
this_mask <<= 1;
#pragma acc loop reduction(+:sum)
for (i = 0; i < 10; i++)
#pragma acc loop reduction(+:sum)
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop reduction(+:sum)
for (k = 0; k < 10; k++)
for (i = 0; i < 10; i++)
{
#pragma acc loop reduction(+:sum)
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop reduction(+:sum)
for (k = 0; k < 10; k++)
sum = 1;
#pragma acc loop reduction(-:diff)
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop reduction(-:diff)
for (k = 0; k < 10; k++)
#pragma acc loop reduction(+:sum)
for (i = 0; i < 10; i++)
#pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop reduction(+:sum)
for (k = 0; k < 10; k++)
#pragma acc loop reduction(+:sum)
for (i = 0; i < 10; i++)
#pragma acc loop collapse(2) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
for (k = 0; k < 10; k++)
#pragma acc loop reduction(+:sum)
#pragma acc loop reduction(+:sum)
for (i = 0; i < 10; i++)
#pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
// { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
#pragma acc loop reduction(+:sum)
for (i = 0; i < 10; i++)
#pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." }
for (k = 0; k < 10; k++)
#pragma acc loop reduction(+:sum)
for (i = 0; i < 10; i++)
#pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop reduction(-:sum)
for (k = 0; k < 10; k++)
#pragma acc loop reduction(+:sum)
for (i = 0; i < 10; i++)
#pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
// { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
#pragma acc loop reduction(+:sum)
for (i = 0; i < 10; i++)
#pragma acc loop reduction(-:sum) // { dg-warning "conflicting reduction operations for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop reduction(+:sum) // { dg-warning "conflicting reduction operations for .sum." })
// { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (i = 0; i < 10; i++)
{
#pragma acc loop reduction(-:diff) // { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop reduction(+:sum)
for (k = 0; k < 10; k++)
sum = 1;
#pragma acc loop reduction(+:sum) // { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ // { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
for (j = 0; j < 10; j++)
#pragma acc loop reduction(-:diff)
for (k = 0; k < 10; k++)
--- /dev/null
+/* Test orphan reductions. */
+
+/* { dg-do compile } */
+
+#pragma acc routine seq
+int
+seq_reduction (int n)
+{
+ int i, sum = 0;
+#pragma acc loop seq reduction(+:sum)
+ for (i = 0; i < n; i++)
+ sum = sum + 1;
+
+ return sum;
+}
+
+#pragma acc routine gang
+int
+gang_reduction (int n)
+{
+ int i, s1 = 0, s2 = 0;
+#pragma acc loop gang reduction(+:s1) /* { dg-error "gang reduction on an orphan loop" } */
+ for (i = 0; i < n; i++)
+ s1 = s1 + 2;
+
+#pragma acc loop gang reduction(+:s2) /* { dg-error "gang reduction on an orphan loop" } */
+ for (i = 0; i < n; i++)
+ s2 = s2 + 2;
+
+
+ return s1 + s2;
+}
+
+#pragma acc routine worker
+int
+worker_reduction (int n)
+{
+ int i, sum = 0;
+#pragma acc loop worker reduction(+:sum)
+ for (i = 0; i < n; i++)
+ sum = sum + 3;
+
+ return sum;
+}
+
+#pragma acc routine vector
+int
+vector_reduction (int n)
+{
+ int i, sum = 0;
+#pragma acc loop vector reduction(+:sum)
+ for (i = 0; i < n; i++)
+ sum = sum + 4;
+
+ return sum;
+}
--- /dev/null
+/* Ensure that the middle end does not assign gang level parallelism
+ to orphan loop containing reductions. */
+
+/* { dg-do compile } */
+/* { dg-additional-options "-fopt-info-optimized-omp" } */
+/* { dg-additional-options "-Wopenacc-parallelism" } */
+
+#pragma acc routine gang
+int
+f1 () /* { dg-warning "region is gang partitioned but does not contain gang partitioned code" } */
+{
+ int sum = 0, i;
+
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC worker vector loop parallelism" } */
+ for (i = 0; i < 100; i++)
+ sum++;
+
+ return sum;
+}
+
+#pragma acc routine gang
+int
+f2 () /* { dg-warning "region is gang partitioned but does not contain gang partitioned code" } */
+{
+ int sum = 0, i, j;
+
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC worker loop parallelism" } */
+ for (i = 0; i < 100; i++)
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC vector loop parallelism" } */
+ for (j = 0; j < 100; j++)
+ sum++;
+
+ return sum;
+}
+
+#pragma acc routine gang
+int
+f3 () /* { dg-warning "region is gang partitioned but does not contain gang partitioned code" } */
+{
+ int sum = 0, i, j, k;
+
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC worker loop parallelism" } */
+ for (i = 0; i < 100; i++)
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC seq loop parallelism" } */
+ /* { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 } */
+ for (j = 0; j < 100; j++)
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC vector loop parallelism" } */
+ for (k = 0; k < 100; k++)
+ sum++;
+
+ return sum;
+}
+
+int
+main ()
+{
+ int sum = 0, i, j, k;
+
+#pragma acc parallel copy (sum)
+ {
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC gang vector loop parallelism" } */
+ for (i = 0; i < 100; i++)
+ sum++;
+ }
+
+#pragma acc parallel copy (sum)
+ {
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC gang worker loop parallelism" } */
+ for (i = 0; i < 100; i++)
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC vector loop parallelism" } */
+ for (j = 0; j < 100; j++)
+ sum++;
+ }
+
+#pragma acc parallel copy (sum)
+ {
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC gang loop parallelism" } */
+ for (i = 0; i < 100; i++)
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC worker loop parallelism" } */
+ for (j = 0; j < 100; j++)
+#pragma acc loop reduction (+:sum) /* { dg-optimized "assigned OpenACC vector loop parallelism" } */
+ for (k = 0; k < 100; k++)
+ sum++;
+ }
+
+ return sum;
+}
}
}
-/* { dg-final { scan-tree-dump {OpenACC loops.*Loop 0\(0\).*Loop 24\(1\).*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*Head-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 1, 36\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 0\);.*Tail-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 0\);.*Loop 6\(6\).*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*Head-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 1\);.*Head-1:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 2\);.*Tail-1:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 2\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 2\);.*Tail-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 1\);} "oaccloops" } } */
+/* { dg-final { scan-tree-dump {OpenACC loops.*Loop 0\(0\).*Loop 44\(1\).*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 1, 68\);.*Head-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 1, 68\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 0\);.*Tail-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 0\);.*Loop 6\(6\).*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*Head-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, 0, 2, 6\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 1\);.*Head-1:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_HEAD_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_FORK, \.data_dep\.[0-9_]+, 2\);.*Tail-1:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 2\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 2\);.*Tail-0:.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_TAIL_MARK, \.data_dep\.[0-9_]+, 1\);.*\.data_dep\.[0-9_]+ = \.UNIQUE \(OACC_JOIN, \.data_dep\.[0-9_]+, 1\);} "oaccloops" } } */
!$acc loop reduction(+:sum)
do i = 1, 10
!$acc loop reduction(+:sum)
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop reduction(+:sum)
do k = 1, 10
!$acc loop reduction(+:sum) reduction(-:diff)
do i = 1, 10
!$acc loop reduction(+:sum)
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop reduction(+:sum)
do k = 1, 10
end do
!$acc loop reduction(-:diff)
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop reduction(-:diff)
do k = 1, 10
!$acc loop reduction(+:sum)
do i = 1, 10
!$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop reduction(+:sum)
do k = 1, 10
!$acc loop reduction(+:sum)
do i = 1, 10
!$acc loop collapse(2) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
do k = 1, 10
!$acc loop reduction(+:sum)
!$acc loop reduction(+:sum)
do i = 1, 10
!$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
!$acc loop reduction(+:sum)
do i = 1, 10
!$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
do k = 1, 10
!$acc loop reduction(+:sum)
do i = 1, 10
!$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop reduction(-:sum)
do k = 1, 10
!$acc loop reduction(+:sum)
do i = 1, 10
!$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
!$acc loop reduction(+:sum)
do i = 1, 10
!$acc loop reduction(-:sum) ! { dg-warning "conflicting reduction operations for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop reduction(+:sum) ! { dg-warning "conflicting reduction operations for .sum." }
! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
!$acc loop reduction(+:sum) reduction(-:diff)
do i = 1, 10
!$acc loop reduction(-:diff) ! { dg-warning "nested loop in reduction needs reduction clause for .sum." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop reduction(+:sum)
do k = 1, 10
end do
!$acc loop reduction(+:sum) ! { dg-warning "nested loop in reduction needs reduction clause for .diff." }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
do j = 1, 10
!$acc loop reduction(-:diff)
do k = 1, 10
--- /dev/null
+! Verify that gang reduction on orphan OpenACC loops reported as errors.
+
+! { dg-do compile }
+
+subroutine s1
+ implicit none
+
+ integer, parameter :: n = 100
+ integer :: i, sum
+ sum = 0
+
+ !$acc parallel reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+ !$acc end parallel
+
+ !$acc parallel loop gang reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+
+ !$acc parallel
+ !$acc loop gang reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+ !$acc end parallel
+end subroutine s1
+
+subroutine s2
+ implicit none
+ !$acc routine worker
+
+ integer, parameter :: n = 100
+ integer :: i, j, sum
+ sum = 0
+
+ !$acc loop gang reduction(+:sum) ! { dg-error "gang reduction on an orphan loop" }
+ do i = 1, n
+ sum = sum + 1
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, n
+ !$acc loop gang reduction(+:sum) ! { dg-error "gang reduction on an orphan loop" }
+ do j = 1, n
+ sum = sum + 1
+ end do
+ end do
+end subroutine s2
+
+integer function f1 ()
+ implicit none
+
+ integer, parameter :: n = 100
+ integer :: i, sum
+ sum = 0
+
+ !$acc parallel reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+ !$acc end parallel
+
+ !$acc parallel loop gang reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+
+ !$acc parallel
+ !$acc loop gang reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+ !$acc end parallel
+
+ f1 = sum
+end function f1
+
+integer function f2 ()
+ implicit none
+ !$acc routine worker
+
+ integer, parameter :: n = 100
+ integer :: i, j, sum
+ sum = 0
+
+ !$acc loop gang reduction(+:sum) ! { dg-error "gang reduction on an orphan loop" }
+ do i = 1, n
+ sum = sum + 1
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, n
+ !$acc loop gang reduction(+:sum) ! { dg-error "gang reduction on an orphan loop" }
+ do j = 1, n
+ sum = sum + 1
+ end do
+ end do
+
+ f2 = sum
+end function f2
+
+module m
+contains
+ subroutine s3
+ implicit none
+
+ integer, parameter :: n = 100
+ integer :: i, sum
+ sum = 0
+
+ !$acc parallel reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+ !$acc end parallel
+
+ !$acc parallel loop gang reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+
+ !$acc parallel
+ !$acc loop gang reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+ !$acc end parallel
+ end subroutine s3
+
+ subroutine s4
+ implicit none
+ !$acc routine worker
+
+ integer, parameter :: n = 100
+ integer :: i, j, sum
+ sum = 0
+
+ !$acc loop gang reduction(+:sum) ! { dg-error "gang reduction on an orphan loop" }
+ do i = 1, n
+ sum = sum + 1
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, n
+ !$acc loop gang reduction(+:sum) ! { dg-error "gang reduction on an orphan loop" }
+ do j = 1, n
+ sum = sum + 1
+ end do
+ end do
+ end subroutine s4
+
+ integer function f3 ()
+ implicit none
+
+ integer, parameter :: n = 100
+ integer :: i, sum
+ sum = 0
+
+ !$acc parallel reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+ !$acc end parallel
+
+ !$acc parallel loop gang reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+
+ !$acc parallel
+ !$acc loop gang reduction(+:sum)
+ do i = 1, n
+ sum = sum + 1
+ end do
+ !$acc end parallel
+
+ f3 = sum
+ end function f3
+
+ integer function f4 ()
+ implicit none
+ !$acc routine worker
+
+ integer, parameter :: n = 100
+ integer :: i, j, sum
+ sum = 0
+
+ !$acc loop gang reduction(+:sum) ! { dg-error "gang reduction on an orphan loop" }
+ do i = 1, n
+ sum = sum + 1
+ end do
+
+ !$acc loop reduction(+:sum)
+ do i = 1, n
+ !$acc loop gang reduction(+:sum) ! { dg-error "gang reduction on an orphan loop" }
+ do j = 1, n
+ sum = sum + 1
+ end do
+ end do
+
+ f4 = sum
+ end function f4
+end module m
--- /dev/null
+! Ensure that the middle end does not assign gang level parallelism to
+! orphan loop containing reductions.
+
+! { dg-do compile }
+! { dg-additional-options "-fopt-info-optimized-omp" }
+! { dg-additional-options "-Wopenacc-parallelism" }
+
+subroutine s1 ! { dg-warning "region is gang partitioned but does not contain gang partitioned code" }
+ implicit none
+ !$acc routine gang
+ integer i, sum
+
+ sum = 0
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC worker vector loop parallelism" }
+ do i = 1, 10
+ sum = sum + 1
+ end do
+end subroutine s1
+
+subroutine s2 ! { dg-warning "region is gang partitioned but does not contain gang partitioned code" }
+ implicit none
+ !$acc routine gang
+ integer i, j, sum
+
+ sum = 0
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC worker loop parallelism" }
+ do i = 1, 10
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC vector loop parallelism" }
+ do j = 1, 10
+ sum = sum + 1
+ end do
+ end do
+end subroutine s2
+
+subroutine s3 ! { dg-warning "region is gang partitioned but does not contain gang partitioned code" }
+ implicit none
+ !$acc routine gang
+ integer i, j, k, sum
+
+ sum = 0
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC worker loop parallelism" }
+ do i = 1, 10
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC seq loop parallelism" }
+ ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+ do j = 1, 10
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC vector loop parallelism" }
+ do k = 1, 10
+ sum = sum + 1
+ end do
+ end do
+ end do
+end subroutine s3
+
+subroutine s4
+ implicit none
+
+ integer i, j, k, sum
+
+ sum = 0
+ !$acc parallel copy(sum)
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC gang vector loop parallelism" }
+ do i = 1, 10
+ sum = sum + 1
+ end do
+ !$acc end parallel
+
+ !$acc parallel copy(sum)
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC gang worker loop parallelism" }
+ do i = 1, 10
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC vector loop parallelism" }
+ do j = 1, 10
+ sum = sum + 1
+ end do
+ end do
+ !$acc end parallel
+
+ !$acc parallel copy(sum)
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC gang loop parallelism" }
+ do i = 1, 10
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC worker loop parallelism" }
+ do j = 1, 10
+ !$acc loop reduction (+:sum) ! { dg-optimized "assigned OpenACC vector loop parallelism" }
+ do k = 1, 10
+ sum = sum + 1
+ end do
+ end do
+ end do
+ !$acc end parallel
+end subroutine s4
! { dg-additional-sources parallel-dims-aux.c }
! { dg-do run }
+ ! { dg-skip-if TODO { *-*-* } }
! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" }
! { dg-additional-options "-fopt-info-note-omp" }