OpenMP: New C/C++ testcases for imperfectly nested loops.

gcc/testsuite/ChangeLog
	* c-c++-common/gomp/imperfect-attributes.c: New.
	* c-c++-common/gomp/imperfect-badloops.c: New.
	* c-c++-common/gomp/imperfect-blocks.c: New.
	* c-c++-common/gomp/imperfect-extension.c: New.
	* c-c++-common/gomp/imperfect-gotos.c: New.
	* c-c++-common/gomp/imperfect-invalid-scope.c: New.
	* c-c++-common/gomp/imperfect-labels.c: New.
	* c-c++-common/gomp/imperfect-legacy-syntax.c: New.
	* c-c++-common/gomp/imperfect-pragmas.c: New.
	* c-c++-common/gomp/imperfect1.c: New.
	* c-c++-common/gomp/imperfect2.c: New.
	* c-c++-common/gomp/imperfect3.c: New.
	* c-c++-common/gomp/imperfect4.c: New.
	* c-c++-common/gomp/imperfect5.c: New.

libgomp/ChangeLog
	* testsuite/libgomp.c-c++-common/imperfect1.c: New.
	* testsuite/libgomp.c-c++-common/imperfect2.c: New.
	* testsuite/libgomp.c-c++-common/imperfect3.c: New.
	* testsuite/libgomp.c-c++-common/imperfect4.c: New.
	* testsuite/libgomp.c-c++-common/imperfect5.c: New.
	* testsuite/libgomp.c-c++-common/imperfect6.c: New.
	* testsuite/libgomp.c-c++-common/target-imperfect1.c: New.
	* testsuite/libgomp.c-c++-common/target-imperfect2.c: New.
	* testsuite/libgomp.c-c++-common/target-imperfect3.c: New.
	* testsuite/libgomp.c-c++-common/target-imperfect4.c: New.
This commit is contained in:
Sandra Loosemore 2023-08-24 17:35:01 +00:00
parent 53891f18f3
commit 410df0843d
24 changed files with 2018 additions and 0 deletions

View file

@ -0,0 +1,81 @@
/* { dg-do compile { target { c || c++11 } } } */
/* Check that a nested FOR loop with standard c/c++ attributes on it
is treated as intervening code, since it doesn't match the grammar
for canonical loop nest form. */
extern void do_something (void);
void imperfect1 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
{
[[]] for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
void perfect1 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
/* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */
{
[[]] for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
/* Similar, but put the attributes on a block wrapping the nested loop
instead. */
void imperfect2 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
{
[[]]
{
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
}
void perfect2 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
/* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */
{
[[]]
{
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
}
/* Make sure attributes are accepted in the innermost loop body, which has
no intervening code restrictions. */
void imperfect3 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
{
[[]] do_something ();
}
}
void perfect3 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
{
[[]] do_something ();
}
}

View file

@ -0,0 +1,50 @@
/* { dg-do compile } */
/* This test case is expected to fail due to errors. */
int f1 (int depth, int iter);
int f2 (int depth, int iter);
void do_something (void);
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for collapse(3)
for (i = 0; i < a1; i++)
{
f1 (0, i);
if (a1 < a2)
{
int z = 0;
while (z < i) /* { dg-error "loop not permitted in intervening code " } */
{
do_something ();
z++;
}
do /* { dg-error "loop not permitted in intervening code " } */
{
do_something ();
z--;
} while (z >= 0);
}
for (j = 0; j < a2; j++)
{
for (k = 0; k < a3; k++)
{
f1 (2, k);
f2 (2, k);
}
f2 (1, j);
}
if (a1 < a3)
{
int z;
for (z = 0; z < i; z++) /* { dg-error "loop not permitted in intervening code " } */
{
do_something ();
}
}
f2 (0, i);
}
}

View file

@ -0,0 +1,75 @@
/* { dg-do compile } */
/* Check that compound statements in intervening code are correctly
handled. */
extern void do_something (void);
void imperfect1 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++)
{
{}
for (int j = 0; j < y; j++)
do_something ();
}
}
void perfect1 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++) /* { dg-error "inner loops must be perfectly nested" } */
{
{}
for (int j = 0; j < y; j++)
do_something ();
}
}
void imperfect2 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
do_something ();
{}
}
}
void perfect2 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++) /* { dg-error "inner loops must be perfectly nested" } */
{
for (int j = 0; j < y; j++)
do_something ();
{}
}
}
void imperfect3 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++)
{
{ do_something (); }
for (int j = 0; j < y; j++)
do_something ();
{ do_something (); }
}
}
void perfect3 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++) /* { dg-error "inner loops must be perfectly nested" } */
{
{ do_something (); }
for (int j = 0; j < y; j++)
do_something ();
{ do_something (); }
}
}

View file

@ -0,0 +1,55 @@
/* { dg-do compile } */
/* Check that __extension__ introduces intervening code. */
extern void do_something (void);
void imperfect1 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
{
__extension__ ({
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
});
}
}
void perfect1 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
/* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */
{
__extension__ ({
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
});
}
}
/* Check that we don't barf on __extension__ in the inner loop body. */
void imperfect2 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
{
__extension__ ({
do_something ();
});
}
}
void perfect2 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
{
__extension__ ({
do_something ();
});
}
}

View file

@ -0,0 +1,174 @@
/* { dg-do compile } */
/* This file contains tests that are expected to fail. */
/* These jumps are all OK since they are to/from the same structured block. */
void f1a (void)
{
#pragma omp for collapse(2)
for (int i = 0; i < 64; ++i)
{
goto a; a:;
for (int j = 0; j < 64; ++j)
{
goto c; c:;
}
goto b; b:;
}
}
/* Jump around loop body to/from different structured blocks of intervening
code. */
void f2a (void)
{
#pragma omp for collapse(2)
for (int i = 0; i < 64; ++i)
{
goto a; a:;
if (i > 16) goto b; /* { dg-error "invalid branch to/from OpenMP structured block" } */
for (int j = 0; j < 64; ++j)
{
goto c; c:;
}
goto b; b:;
}
}
/* Jump into loop body from intervening code. */
void f3a (void)
{
#pragma omp for collapse(2)
for (int i = 0; i < 64; ++i)
{
goto a; a:;
if (i > 16) goto c; /* { dg-error "invalid branch to/from OpenMP structured block" } */
for (int j = 0; j < 64; ++j)
{
c:
;
}
goto b; b:;
}
}
/* Jump out of loop body to intervening code. */
void f4a (void)
{
#pragma omp for collapse(2)
for (int i = 0; i < 64; ++i)
{
goto a; a:;
for (int j = 0; j < 64; ++j)
if (i > 16) goto c; /* { dg-error "invalid branch to/from OpenMP structured block" } */
c:
;
goto b; b:;
}
}
/* The next group of tests use the GNU extension for local labels. Expected
behavior is the same as the above group. */
/* These jumps are all OK since they are to/from the same structured block. */
void f1b (void)
{
#pragma omp for collapse(2)
for (int i = 0; i < 64; ++i)
{
__label__ a, b, c;
goto a; a:;
for (int j = 0; j < 64; ++j)
{
goto c; c:;
}
goto b; b:;
}
}
/* Jump around loop body to/from different structured blocks of intervening
code. */
void f2b (void)
{
#pragma omp for collapse(2)
for (int i = 0; i < 64; ++i)
{
__label__ a, b, c;
goto a; a:;
if (i > 16) goto b; /* { dg-error "invalid branch to/from OpenMP structured block" } */
for (int j = 0; j < 64; ++j)
{
goto c; c:;
}
goto b; b:;
}
}
/* Jump into loop body from intervening code. */
void f3b (void)
{
#pragma omp for collapse(2)
for (int i = 0; i < 64; ++i)
{
__label__ a, b, c;
goto a; a:;
if (i > 16) goto c; /* { dg-error "invalid branch to/from OpenMP structured block" } */
for (int j = 0; j < 64; ++j)
{
c:
;
}
goto b; b:;
}
}
/* Jump out of loop body to intervening code. */
void f4b (void)
{
#pragma omp for collapse(2)
for (int i = 0; i < 64; ++i)
{
__label__ a, b, c;
goto a; a:;
for (int j = 0; j < 64; ++j)
if (i > 16) goto c; /* { dg-error "invalid branch to/from OpenMP structured block" } */
c:
;
goto b; b:;
}
}
/* Test that the even the valid jumps are rejected when intervening code
is not allowed at all. */
void f1c (void)
{
#pragma omp for ordered(2)
for (int i = 0; i < 64; ++i) /* { dg-error "inner loops must be perfectly nested" } */
{
goto a; a:;
for (int j = 0; j < 64; ++j)
{
goto c; c:;
}
goto b; b:;
}
}
void f1d (void)
{
#pragma omp for ordered(2)
for (int i = 0; i < 64; ++i) /* { dg-error "inner loops must be perfectly nested" } */
{
__label__ a, b, c;
goto a; a:;
for (int j = 0; j < 64; ++j)
{
goto c; c:;
}
goto b; b:;
}
}

View file

@ -0,0 +1,77 @@
/* { dg-do compile } */
/* Check that various cases of invalid references to variables bound
in an intervening code scope are diagnosed and do not ICE. This test
is expected to produce errors. */
extern void foo (int, int);
void f1 (void)
{
#pragma omp for collapse (2)
for (int i = 0; i < 64; i++)
{
int v = (i + 4) * 2;
for (int j = v; j < 64; j++) /* { dg-error "initializer is bound in intervening code" } */
foo (i, j);
}
}
void f2 (void)
{
#pragma omp for collapse (2)
for (int i = 0; i < 64; i++)
{
int v = (i + 4) * 2;
for (int j = 0; j < v; j++) /* { dg-error "end test is bound in intervening code" } */
foo (i, j);
}
}
void f3 (void)
{
#pragma omp for collapse (2)
for (int i = 0; i < 64; i++)
{
int v = (i + 4) * 2;
for (int j = 0; j < 64; j = j + v) /* { dg-error "increment expression is bound in intervening code" } */
foo (i, j);
}
}
void f4 (void)
{
#pragma omp for collapse (2)
for (int i = 0; i < 64; i++)
{
int v = 8;
for (int j = v; j < 64; j++) /* { dg-error "initializer is bound in intervening code" } */
foo (i, j);
}
}
void f5 (void)
{
#pragma omp for collapse (2)
for (int i = 0; i < 64; i++)
{
int j;
for (j = 0; j < 64; j++) /* { dg-error "loop variable is bound in intervening code" } */
foo (i, j);
}
}
void f6 (void)
{
#pragma omp for collapse (2)
for (int i = 0; i < 64; i++)
{
int j;
{
int v = 8;
for (j = v; j < 64; j++) /* { dg-error "loop variable is bound in intervening code" } */
/* { dg-error "initializer is bound in intervening code" "" { target *-*-* } .-1 } */
foo (i, j);
}
}
}

View file

@ -0,0 +1,85 @@
/* { dg-do compile } */
/* Check that a nested FOR loop with a label on it is treated as
intervening code, since it doesn't match the grammar for canonical
loop nest form. */
extern void do_something (void);
void imperfect1 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
{
foo:
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
void perfect1 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
/* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */
{
foo:
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
/* Similar, but put the label on a block wrapping the nested loop instead. */
void imperfect2 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
{
foo:
{
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
}
void perfect2 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
/* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */
{
foo:
{
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
}
/* Sanity check that labels are allowed in the innermost loop body. */
void imperfect3 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
{
foo:
do_something ();
}
}
void perfect3 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
{
foo:
do_something ();
}
}

View file

@ -0,0 +1,44 @@
/* { dg-do compile } */
/* Braces may enclose a nested FOR even when intervening code is not
permitted. Before GCC implemented OpenMP 5.1 canonical loop syntax
and support for intervening code, it used to ignore empty statements
instead of treating them as intervening code; as an extension, those
are still accepted without complaint even in constructs where intervening
code is not supposed to be valid. */
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for ordered(3)
for (i = 0; i < a1; i++)
{
for (j = 0; j < a2; j++)
{
for (k = 0; k < a3; k++)
{
}
}
}
}
void s2 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for ordered(3)
for (i = 0; i < a1; i++)
{
;
for (j = 0; j < a2; j++)
{
;
for (k = 0; k < a3; k++)
{
}
;
}
;
}
}

View file

@ -0,0 +1,85 @@
/* { dg-do compile } */
/* Check that non-statement pragmas are accepted in a canonical loop nest
even when perfect nesting is required. */
extern void do_something (void);
void imperfect1 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++)
{
#pragma GCC diagnostic push
for (int j = 0; j < y; j++)
do_something ();
#pragma GCC diagnostic pop
}
}
void perfect1 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++)
{
#pragma GCC diagnostic push
for (int j = 0; j < y; j++)
do_something ();
#pragma GCC diagnostic pop
}
}
/* "GCC unroll" is a statement pragma that consumes the following loop as
a substatement. Thus, the inner loop should be treated as intervening
code rather than part of the loop nest. */
void imperfect2 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
{
#pragma GCC unroll 4
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
void perfect2 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++) /* { dg-error "not enough nested loops" } */
/* { dg-error "inner loops must be perfectly nested" "" { target *-*-*} .-1 } */
{
#pragma GCC unroll 4
for (int j = 0; j < y; j++) /* { dg-error "loop not permitted in intervening code" } */
do_something ();
}
}
/* Check that statement pragmas are accepted in the innermost loop body. */
void imperfect3 (int x, int y)
{
#pragma omp for collapse (2)
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
{
#pragma GCC unroll 4
for (int k = 0; k < 4; k++)
do_something ();
}
}
void perfect3 (int x, int y)
{
#pragma omp for ordered (2)
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
{
#pragma GCC unroll 4
for (int k = 0; k < 4; k++)
do_something ();
}
}

View file

@ -0,0 +1,38 @@
/* { dg-do compile } */
/* This test case is expected to fail due to errors. */
int f1 (int depth, int iter);
int f2 (int depth, int iter);
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for collapse(3)
for (i = 0; i < a1; i++)
{
f1 (0, i);
for (j = 0; j < a2; j++)
{
#pragma omp barrier /* { dg-error "intervening code must not contain OpenMP directives" } */
f1 (1, j);
if (i == 2)
continue; /* { dg-error "invalid exit" } */
else
break; /* { dg-error "invalid exit" } */
for (k = 0; k < a3; k++)
{
f1 (2, k);
f2 (2, k);
}
f2 (1, j);
}
for (k = 0; k < a3; k++) /* { dg-error "loop not permitted in intervening code " } */
{
f1 (2, k);
f2 (2, k);
}
f2 (0, i);
}
}

View file

@ -0,0 +1,34 @@
/* { dg-do compile } */
/* This test case is expected to fail due to errors. */
/* These functions that are part of the OpenMP runtime API would ordinarily
be declared in omp.h, but we don't have that here. */
extern int omp_get_num_threads(void);
extern int omp_get_max_threads(void);
int f1 (int depth, int iter);
int f2 (int depth, int iter);
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for collapse(3)
for (i = 0; i < a1; i++)
{
f1 (0, i);
for (j = 0; j < omp_get_num_threads (); j++) /* This is OK */
{
f1 (1, omp_get_num_threads ()); /* { dg-error "not permitted in intervening code" } */
for (k = omp_get_num_threads (); k < a3; k++) /* This is OK */
{
f1 (2, omp_get_num_threads ());
f2 (2, omp_get_max_threads ());
}
f2 (1, omp_get_max_threads ()); /* { dg-error "not permitted in intervening code" } */
}
f2 (0, i);
}
}

View file

@ -0,0 +1,52 @@
/* { dg-do compile } */
/* This test case is expected to fail due to errors. */
/* Test that the imperfectly-nested loops with the ordered clause gives
an error, and that there is only one error (and not one on every
intervening statement). */
int f1 (int depth, int iter);
int f2 (int depth, int iter);
void s1 (int a1, int a2, int a3)
{
int i, j, k;
/* This loop without intervening code ought to be OK. */
#pragma omp for ordered(3)
for (i = 0; i < a1; i++)
{
for (j = 0; j < a2; j++)
{
for (k = 0; k < a3; k++)
{
f1 (2, k);
f2 (2, k);
#pragma omp ordered doacross(source:omp_cur_iteration)
#pragma omp ordered doacross(sink: i - 2, j + 2, k - 1)
}
}
}
/* Now add intervening code. */
#pragma omp for ordered(3)
for (i = 0; i < a1; i++) /* { dg-error "inner loops must be perfectly nested" } */
{
f1 (0, i);
for (j = 0; j < a2; j++)
{
f1 (1, j);
for (k = 0; k < a3; k++)
{
f1 (2, k);
f2 (2, k);
#pragma omp ordered doacross(source:omp_cur_iteration)
#pragma omp ordered doacross(sink: i - 2, j + 2, k - 1)
}
f2 (1, j);
}
f2 (0, i);
}
}

View file

@ -0,0 +1,33 @@
/* { dg-do compile } */
/* This test case is expected to fail due to errors. */
int f1 (int depth, int iter);
int f2 (int depth, int iter);
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for collapse(4)
for (i = 0; i < a1; i++) /* { dg-error "not enough nested loops" } */
{
f1 (0, i);
for (j = 0; j < a2; j++)
{
f1 (1, j);
for (k = 0; k < a3; k++)
{
/* According to the grammar, this is intervening code; we
don't know that we are also missing a nested for loop
until we have parsed this whole compound expression. */
#pragma omp barrier /* { dg-error "intervening code must not contain OpenMP directives" } */
f1 (2, k);
f2 (2, k);
}
f2 (1, j);
}
f2 (0, i);
}
}

View file

@ -0,0 +1,95 @@
/* { dg-do compile } */
/* This test case is expected to fail due to errors. */
#define N 30
#define M 3
int a[N][M], b[N][M], c[N][M];
extern void dostuff (int, int);
/* good1 and good2 should compile without error. */
void
good1 (void)
{
int x, shift;
x = 0;
#pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift)
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
x += a[i][j];
x += b[i][j];
#pragma omp scan inclusive(x)
shift = i + 29*j;
c[i][j] = x + shift;
}
}
}
void
good2 (void)
{
int x, shift;
x = 0;
#pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift)
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
shift = i + 29*j;
c[i][j] = x + shift;
#pragma omp scan exclusive(x)
x += a[i][j];
x += b[i][j];
}
}
}
/* Adding intervening code should trigger an error. */
void
bad1 (void)
{
int x, shift;
x = 0;
#pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift)
for (int i = 0; i < N; i++) /* { dg-error "inner loops must be perfectly nested" } */
{
dostuff (i, 0);
for (int j = 0; j < M; j++)
{
x += a[i][j];
x += b[i][j];
#pragma omp scan inclusive(x)
shift = i + 29*j;
c[i][j] = x + shift;
}
}
}
void
bad2 (void)
{
int x, shift;
x = 0;
#pragma omp parallel for simd collapse(2) reduction(inscan,+: x) private(shift)
for (int i = 0; i < N; i++) /* { dg-error "inner loops must be perfectly nested" } */
{
for (int j = 0; j < M; j++)
{
shift = i + 29*j;
c[i][j] = x + shift;
#pragma omp scan exclusive(x)
x += a[i][j];
x += b[i][j];
}
dostuff (i, 1);
}
}

View file

@ -0,0 +1,76 @@
/* { dg-do run } */
static int f1count[3], f2count[3];
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
int f1 (int depth, int iter)
{
f1count[depth]++;
return iter;
}
int f2 (int depth, int iter)
{
f2count[depth]++;
return iter;
}
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for collapse(3)
for (i = 0; i < a1; i++)
{
f1 (0, i);
for (j = 0; j < a2; j++)
{
f1 (1, j);
for (k = 0; k < a3; k++)
{
f1 (2, k);
f2 (2, k);
}
f2 (1, j);
}
f2 (0, i);
}
}
int
main (void)
{
f1count[0] = 0;
f1count[1] = 0;
f1count[2] = 0;
f2count[0] = 0;
f2count[1] = 0;
f2count[2] = 0;
s1 (3, 4, 5);
/* All intervening code at the same depth must be executed the same
number of times. */
if (f1count[0] != f2count[0]) abort ();
if (f1count[1] != f2count[1]) abort ();
if (f1count[2] != f2count[2]) abort ();
/* Intervening code must be executed at least as many times as the loop
that encloses it. */
if (f1count[0] < 3) abort ();
if (f1count[1] < 3 * 4) abort ();
/* Intervening code must not be executed more times than the number
of logical iterations. */
if (f1count[0] > 3 * 4 * 5) abort ();
if (f1count[1] > 3 * 4 * 5) abort ();
/* Check that the innermost loop body is executed exactly the number
of logical iterations expected. */
if (f1count[2] != 3 * 4 * 5) abort ();
}

View file

@ -0,0 +1,114 @@
/* { dg-do run } */
static int f1count[3], f2count[3];
static int g1count[3], g2count[3];
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
int f1 (int depth, int iter)
{
f1count[depth]++;
return iter;
}
int f2 (int depth, int iter)
{
f2count[depth]++;
return iter;
}
int g1 (int depth, int iter)
{
g1count[depth]++;
return iter;
}
int g2 (int depth, int iter)
{
g2count[depth]++;
return iter;
}
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for collapse(3)
for (i = 0; i < a1; i++)
{
f1 (0, i);
{
g1 (0, i);
for (j = 0; j < a2; j++)
{
f1 (1, j);
{
g1 (1, j);
for (k = 0; k < a3; k++)
{
f1 (2, k);
{
g1 (2, k);
g2 (2, k);
}
f2 (2, k);
}
g2 (1, j);
}
f2 (1, j);
}
g2 (0, i);
}
f2 (0, i);
}
}
int
main (void)
{
f1count[0] = 0;
f1count[1] = 0;
f1count[2] = 0;
f2count[0] = 0;
f2count[1] = 0;
f2count[2] = 0;
g1count[0] = 0;
g1count[1] = 0;
g1count[2] = 0;
g2count[0] = 0;
g2count[1] = 0;
g2count[2] = 0;
s1 (3, 4, 5);
/* All intervening code at the same depth must be executed the same
number of times. */
if (f1count[0] != f2count[0]) abort ();
if (f1count[1] != f2count[1]) abort ();
if (f1count[2] != f2count[2]) abort ();
if (g1count[0] != f1count[0]) abort ();
if (g2count[0] != f1count[0]) abort ();
if (g1count[1] != f1count[1]) abort ();
if (g2count[1] != f1count[1]) abort ();
if (g1count[2] != f1count[2]) abort ();
if (g2count[2] != f1count[2]) abort ();
/* Intervening code must be executed at least as many times as the loop
that encloses it. */
if (f1count[0] < 3) abort ();
if (f1count[1] < 3 * 4) abort ();
/* Intervening code must not be executed more times than the number
of logical iterations. */
if (f1count[0] > 3 * 4 * 5) abort ();
if (f1count[1] > 3 * 4 * 5) abort ();
/* Check that the innermost loop body is executed exactly the number
of logical iterations expected. */
if (f1count[2] != 3 * 4 * 5) abort ();
}

View file

@ -0,0 +1,119 @@
/* { dg-do run } */
/* Like imperfect2.c, but includes bindings in the blocks. */
static int f1count[3], f2count[3];
static int g1count[3], g2count[3];
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
int f1 (int depth, int iter)
{
f1count[depth]++;
return iter;
}
int f2 (int depth, int iter)
{
f2count[depth]++;
return iter;
}
int g1 (int depth, int iter)
{
g1count[depth]++;
return iter;
}
int g2 (int depth, int iter)
{
g2count[depth]++;
return iter;
}
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for collapse(3)
for (i = 0; i < a1; i++)
{
int local0 = 0;
f1 (local0, i);
{
g1 (local0, i);
for (j = 0; j < a2; j++)
{
int local1 = 1;
f1 (local1, j);
{
g1 (local1, j);
for (k = 0; k < a3; k++)
{
int local2 = 2;
f1 (local2, k);
{
g1 (local2, k);
g2 (local2, k);
}
f2 (local2, k);
}
g2 (local1, j);
}
f2 (local1, j);
}
g2 (local0, i);
}
f2 (local0, i);
}
}
int
main (void)
{
f1count[0] = 0;
f1count[1] = 0;
f1count[2] = 0;
f2count[0] = 0;
f2count[1] = 0;
f2count[2] = 0;
g1count[0] = 0;
g1count[1] = 0;
g1count[2] = 0;
g2count[0] = 0;
g2count[1] = 0;
g2count[2] = 0;
s1 (3, 4, 5);
/* All intervening code at the same depth must be executed the same
number of times. */
if (f1count[0] != f2count[0]) abort ();
if (f1count[1] != f2count[1]) abort ();
if (f1count[2] != f2count[2]) abort ();
if (g1count[0] != f1count[0]) abort ();
if (g2count[0] != f1count[0]) abort ();
if (g1count[1] != f1count[1]) abort ();
if (g2count[1] != f1count[1]) abort ();
if (g1count[2] != f1count[2]) abort ();
if (g2count[2] != f1count[2]) abort ();
/* Intervening code must be executed at least as many times as the loop
that encloses it. */
if (f1count[0] < 3) abort ();
if (f1count[1] < 3 * 4) abort ();
/* Intervening code must not be executed more times than the number
of logical iterations. */
if (f1count[0] > 3 * 4 * 5) abort ();
if (f1count[1] > 3 * 4 * 5) abort ();
/* Check that the innermost loop body is executed exactly the number
of logical iterations expected. */
if (f1count[2] != 3 * 4 * 5) abort ();
}

View file

@ -0,0 +1,117 @@
/* { dg-do run } */
/* Like imperfect2.c, but includes blocks that are themselves intervening
code. */
static int f1count[3], f2count[3];
static int g1count[3], g2count[3];
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
int f1 (int depth, int iter)
{
f1count[depth]++;
return iter;
}
int f2 (int depth, int iter)
{
f2count[depth]++;
return iter;
}
int g1 (int depth, int iter)
{
g1count[depth]++;
return iter;
}
int g2 (int depth, int iter)
{
g2count[depth]++;
return iter;
}
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp for collapse(3)
for (i = 0; i < a1; i++)
{
{ f1 (0, i); }
{
g1 (0, i);
for (j = 0; j < a2; j++)
{
{ f1 (1, j); }
{
{ g1 (1, j); }
for (k = 0; k < a3; k++)
{
f1 (2, k);
{
g1 (2, k);
g2 (2, k);
}
f2 (2, k);
}
{ g2 (1, j); }
}
{ f2 (1, j); }
}
{ g2 (0, i); }
}
{ f2 (0, i); }
}
}
int
main (void)
{
f1count[0] = 0;
f1count[1] = 0;
f1count[2] = 0;
f2count[0] = 0;
f2count[1] = 0;
f2count[2] = 0;
g1count[0] = 0;
g1count[1] = 0;
g1count[2] = 0;
g2count[0] = 0;
g2count[1] = 0;
g2count[2] = 0;
s1 (3, 4, 5);
/* All intervening code at the same depth must be executed the same
number of times. */
if (f1count[0] != f2count[0]) abort ();
if (f1count[1] != f2count[1]) abort ();
if (f1count[2] != f2count[2]) abort ();
if (g1count[0] != f1count[0]) abort ();
if (g2count[0] != f1count[0]) abort ();
if (g1count[1] != f1count[1]) abort ();
if (g2count[1] != f1count[1]) abort ();
if (g1count[2] != f1count[2]) abort ();
if (g2count[2] != f1count[2]) abort ();
/* Intervening code must be executed at least as many times as the loop
that encloses it. */
if (f1count[0] < 3) abort ();
if (f1count[1] < 3 * 4) abort ();
/* Intervening code must not be executed more times than the number
of logical iterations. */
if (f1count[0] > 3 * 4 * 5) abort ();
if (f1count[1] > 3 * 4 * 5) abort ();
/* Check that the innermost loop body is executed exactly the number
of logical iterations expected. */
if (f1count[2] != 3 * 4 * 5) abort ();
}

View file

@ -0,0 +1,49 @@
/* { dg-do run } */
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
static int inner_loop_count = 0;
static int intervening_code_count = 0;
void
g (int x, int y)
{
inner_loop_count++;
}
int
foo (int imax, int jmax)
{
int j = 0;
#pragma omp for collapse(2)
for (int i = 0; i < imax; ++i)
{
/* All the intervening code at the same level must be executed
the same number of times. */
++intervening_code_count;
for (int j = 0; j < jmax; ++j)
{
g (i, j);
}
/* This is the outer j, not the one from the inner collapsed loop. */
++j;
}
return j;
}
int
main (void)
{
int j = foo (5, 3);
if (j != intervening_code_count)
abort ();
if (inner_loop_count != 5 * 3)
abort ();
if (intervening_code_count < 5 || intervening_code_count > 5 * 3)
abort ();
}

View file

@ -0,0 +1,115 @@
/* { dg-do run } */
/* Like imperfect4.c, but bind the iteration variables in the loops. */
static int f1count[3], f2count[3];
static int g1count[3], g2count[3];
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
int f1 (int depth, int iter)
{
f1count[depth]++;
return iter;
}
int f2 (int depth, int iter)
{
f2count[depth]++;
return iter;
}
int g1 (int depth, int iter)
{
g1count[depth]++;
return iter;
}
int g2 (int depth, int iter)
{
g2count[depth]++;
return iter;
}
void s1 (int a1, int a2, int a3)
{
#pragma omp for collapse(3)
for (int i = 0; i < a1; i++)
{
{ f1 (0, i); }
{
g1 (0, i);
for (int j = 0; j < a2; j++)
{
{ f1 (1, j); }
{
{ g1 (1, j); }
for (int k = 0; k < a3; k++)
{
f1 (2, k);
{
g1 (2, k);
g2 (2, k);
}
f2 (2, k);
}
{ g2 (1, j); }
}
{ f2 (1, j); }
}
{ g2 (0, i); }
}
{ f2 (0, i); }
}
}
int
main (void)
{
f1count[0] = 0;
f1count[1] = 0;
f1count[2] = 0;
f2count[0] = 0;
f2count[1] = 0;
f2count[2] = 0;
g1count[0] = 0;
g1count[1] = 0;
g1count[2] = 0;
g2count[0] = 0;
g2count[1] = 0;
g2count[2] = 0;
s1 (3, 4, 5);
/* All intervening code at the same depth must be executed the same
number of times. */
if (f1count[0] != f2count[0]) abort ();
if (f1count[1] != f2count[1]) abort ();
if (f1count[2] != f2count[2]) abort ();
if (g1count[0] != f1count[0]) abort ();
if (g2count[0] != f1count[0]) abort ();
if (g1count[1] != f1count[1]) abort ();
if (g2count[1] != f1count[1]) abort ();
if (g1count[2] != f1count[2]) abort ();
if (g2count[2] != f1count[2]) abort ();
/* Intervening code must be executed at least as many times as the loop
that encloses it. */
if (f1count[0] < 3) abort ();
if (f1count[1] < 3 * 4) abort ();
/* Intervening code must not be executed more times than the number
of logical iterations. */
if (f1count[0] > 3 * 4 * 5) abort ();
if (f1count[1] > 3 * 4 * 5) abort ();
/* Check that the innermost loop body is executed exactly the number
of logical iterations expected. */
if (f1count[2] != 3 * 4 * 5) abort ();
}

View file

@ -0,0 +1,81 @@
/* { dg-do run } */
/* Like imperfect1.c, but enables offloading. */
static int f1count[3], f2count[3];
#pragma omp declare target enter (f1count, f2count)
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
int f1 (int depth, int iter)
{
#pragma omp atomic
f1count[depth]++;
return iter;
}
int f2 (int depth, int iter)
{
#pragma omp atomic
f2count[depth]++;
return iter;
}
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp target parallel for collapse(3) map(always, tofrom:f1count, f2count)
for (i = 0; i < a1; i++)
{
f1 (0, i);
for (j = 0; j < a2; j++)
{
f1 (1, j);
for (k = 0; k < a3; k++)
{
f1 (2, k);
f2 (2, k);
}
f2 (1, j);
}
f2 (0, i);
}
}
int
main (void)
{
f1count[0] = 0;
f1count[1] = 0;
f1count[2] = 0;
f2count[0] = 0;
f2count[1] = 0;
f2count[2] = 0;
s1 (3, 4, 5);
/* All intervening code at the same depth must be executed the same
number of times. */
if (f1count[0] != f2count[0]) abort ();
if (f1count[1] != f2count[1]) abort ();
if (f1count[2] != f2count[2]) abort ();
/* Intervening code must be executed at least as many times as the loop
that encloses it. */
if (f1count[0] < 3) abort ();
if (f1count[1] < 3 * 4) abort ();
/* Intervening code must not be executed more times than the number
of logical iterations. */
if (f1count[0] > 3 * 4 * 5) abort ();
if (f1count[1] > 3 * 4 * 5) abort ();
/* Check that the innermost loop body is executed exactly the number
of logical iterations expected. */
if (f1count[2] != 3 * 4 * 5) abort ();
}

View file

@ -0,0 +1,122 @@
/* { dg-do run } */
/* Like imperfect2.c, but enables offloading. */
static int f1count[3], f2count[3];
static int g1count[3], g2count[3];
#pragma omp declare target enter (f1count, f2count)
#pragma omp declare target enter (g1count, g2count)
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
int f1 (int depth, int iter)
{
#pragma omp atomic
f1count[depth]++;
return iter;
}
int f2 (int depth, int iter)
{
#pragma omp atomic
f2count[depth]++;
return iter;
}
int g1 (int depth, int iter)
{
#pragma omp atomic
g1count[depth]++;
return iter;
}
int g2 (int depth, int iter)
{
#pragma omp atomic
g2count[depth]++;
return iter;
}
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp target parallel for collapse(3) map(always, tofrom:f1count, f2count, g1count, g2count)
for (i = 0; i < a1; i++)
{
f1 (0, i);
{
g1 (0, i);
for (j = 0; j < a2; j++)
{
f1 (1, j);
{
g1 (1, j);
for (k = 0; k < a3; k++)
{
f1 (2, k);
{
g1 (2, k);
g2 (2, k);
}
f2 (2, k);
}
g2 (1, j);
}
f2 (1, j);
}
g2 (0, i);
}
f2 (0, i);
}
}
int
main (void)
{
f1count[0] = 0;
f1count[1] = 0;
f1count[2] = 0;
f2count[0] = 0;
f2count[1] = 0;
f2count[2] = 0;
g1count[0] = 0;
g1count[1] = 0;
g1count[2] = 0;
g2count[0] = 0;
g2count[1] = 0;
g2count[2] = 0;
s1 (3, 4, 5);
/* All intervening code at the same depth must be executed the same
number of times. */
if (f1count[0] != f2count[0]) abort ();
if (f1count[1] != f2count[1]) abort ();
if (f1count[2] != f2count[2]) abort ();
if (g1count[0] != f1count[0]) abort ();
if (g2count[0] != f1count[0]) abort ();
if (g1count[1] != f1count[1]) abort ();
if (g2count[1] != f1count[1]) abort ();
if (g1count[2] != f1count[2]) abort ();
if (g2count[2] != f1count[2]) abort ();
/* Intervening code must be executed at least as many times as the loop
that encloses it. */
if (f1count[0] < 3) abort ();
if (f1count[1] < 3 * 4) abort ();
/* Intervening code must not be executed more times than the number
of logical iterations. */
if (f1count[0] > 3 * 4 * 5) abort ();
if (f1count[1] > 3 * 4 * 5) abort ();
/* Check that the innermost loop body is executed exactly the number
of logical iterations expected. */
if (f1count[2] != 3 * 4 * 5) abort ();
}

View file

@ -0,0 +1,125 @@
/* { dg-do run } */
/* Like imperfect3.c, but enables offloading. */
static int f1count[3], f2count[3];
static int g1count[3], g2count[3];
#pragma omp declare target enter (f1count, f2count)
#pragma omp declare target enter (g1count, g2count)
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
int f1 (int depth, int iter)
{
#pragma omp atomic
f1count[depth]++;
return iter;
}
int f2 (int depth, int iter)
{
#pragma omp atomic
f2count[depth]++;
return iter;
}
int g1 (int depth, int iter)
{
#pragma omp atomic
g1count[depth]++;
return iter;
}
int g2 (int depth, int iter)
{
#pragma omp atomic
g2count[depth]++;
return iter;
}
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp target parallel for collapse(3) map(always, tofrom:f1count, f2count, g1count, g2count)
for (i = 0; i < a1; i++)
{
int local0 = 0;
f1 (local0, i);
{
g1 (local0, i);
for (j = 0; j < a2; j++)
{
int local1 = 1;
f1 (local1, j);
{
g1 (local1, j);
for (k = 0; k < a3; k++)
{
int local2 = 2;
f1 (local2, k);
{
g1 (local2, k);
g2 (local2, k);
}
f2 (local2, k);
}
g2 (local1, j);
}
f2 (local1, j);
}
g2 (local0, i);
}
f2 (local0, i);
}
}
int
main (void)
{
f1count[0] = 0;
f1count[1] = 0;
f1count[2] = 0;
f2count[0] = 0;
f2count[1] = 0;
f2count[2] = 0;
g1count[0] = 0;
g1count[1] = 0;
g1count[2] = 0;
g2count[0] = 0;
g2count[1] = 0;
g2count[2] = 0;
s1 (3, 4, 5);
/* All intervening code at the same depth must be executed the same
number of times. */
if (f1count[0] != f2count[0]) abort ();
if (f1count[1] != f2count[1]) abort ();
if (f1count[2] != f2count[2]) abort ();
if (g1count[0] != f1count[0]) abort ();
if (g2count[0] != f1count[0]) abort ();
if (g1count[1] != f1count[1]) abort ();
if (g2count[1] != f1count[1]) abort ();
if (g1count[2] != f1count[2]) abort ();
if (g2count[2] != f1count[2]) abort ();
/* Intervening code must be executed at least as many times as the loop
that encloses it. */
if (f1count[0] < 3) abort ();
if (f1count[1] < 3 * 4) abort ();
/* Intervening code must not be executed more times than the number
of logical iterations. */
if (f1count[0] > 3 * 4 * 5) abort ();
if (f1count[1] > 3 * 4 * 5) abort ();
/* Check that the innermost loop body is executed exactly the number
of logical iterations expected. */
if (f1count[2] != 3 * 4 * 5) abort ();
}

View file

@ -0,0 +1,122 @@
/* { dg-do run } */
/* Like imperfect4.c, but enables offloading. */
static int f1count[3], f2count[3];
static int g1count[3], g2count[3];
#pragma omp declare target enter (f1count, f2count)
#pragma omp declare target enter (g1count, g2count)
#ifndef __cplusplus
extern void abort (void);
#else
extern "C" void abort (void);
#endif
int f1 (int depth, int iter)
{
#pragma omp atomic
f1count[depth]++;
return iter;
}
int f2 (int depth, int iter)
{
#pragma omp atomic
f2count[depth]++;
return iter;
}
int g1 (int depth, int iter)
{
#pragma omp atomic
g1count[depth]++;
return iter;
}
int g2 (int depth, int iter)
{
#pragma omp atomic
g2count[depth]++;
return iter;
}
void s1 (int a1, int a2, int a3)
{
int i, j, k;
#pragma omp target parallel for collapse(3) map(always, tofrom:f1count, f2count, g1count, g2count)
for (i = 0; i < a1; i++)
{
{ f1 (0, i); }
{
g1 (0, i);
for (j = 0; j < a2; j++)
{
{ f1 (1, j); }
{
{ g1 (1, j); }
for (k = 0; k < a3; k++)
{
f1 (2, k);
{
g1 (2, k);
g2 (2, k);
}
f2 (2, k);
}
{ g2 (1, j); }
}
{ f2 (1, j); }
}
{ g2 (0, i); }
}
{ f2 (0, i); }
}
}
int
main (void)
{
f1count[0] = 0;
f1count[1] = 0;
f1count[2] = 0;
f2count[0] = 0;
f2count[1] = 0;
f2count[2] = 0;
g1count[0] = 0;
g1count[1] = 0;
g1count[2] = 0;
g2count[0] = 0;
g2count[1] = 0;
g2count[2] = 0;
s1 (3, 4, 5);
/* All intervening code at the same depth must be executed the same
number of times. */
if (f1count[0] != f2count[0]) abort ();
if (f1count[1] != f2count[1]) abort ();
if (f1count[2] != f2count[2]) abort ();
if (g1count[0] != f1count[0]) abort ();
if (g2count[0] != f1count[0]) abort ();
if (g1count[1] != f1count[1]) abort ();
if (g2count[1] != f1count[1]) abort ();
if (g1count[2] != f1count[2]) abort ();
if (g2count[2] != f1count[2]) abort ();
/* Intervening code must be executed at least as many times as the loop
that encloses it. */
if (f1count[0] < 3) abort ();
if (f1count[1] < 3 * 4) abort ();
/* Intervening code must not be executed more times than the number
of logical iterations. */
if (f1count[0] > 3 * 4 * 5) abort ();
if (f1count[1] > 3 * 4 * 5) abort ();
/* Check that the innermost loop body is executed exactly the number
of logical iterations expected. */
if (f1count[2] != 3 * 4 * 5) abort ();
}