1/* { dg-do run } */
2/* { dg-options "-O2" } */
3/* { dg-additional-options "-msse2" { target sse2_runtime } } */
4/* { dg-additional-options "-mavx" { target avx_runtime } } */
5
6extern void abort ();
7int a[32][32] __attribute__((aligned (32))) = { { 1 } };
8struct S { int s; };
9#pragma omp declare reduction (+:struct S:omp_out.s += omp_in.s)
10#pragma omp declare reduction (foo:struct S:omp_out.s += omp_in.s)
11#pragma omp declare reduction (foo:int:omp_out += omp_in)
12
13__attribute__((noinline, noclone)) int
14foo (void)
15{
16  int i, j, u = 0;
17  struct S s, t;
18  s.s = 0; t.s = 0;
19  #pragma omp simd aligned(a : 32) lastprivate (i, j) reduction(+:s) reduction(foo:t, u) collapse(2)
20  for (i = 0; i < 32; i++)
21    for (j = 0; j < 32; j++)
22      {
23	int *q = &i;
24	int *r = &j;
25	int x = a[i][j];
26	s.s += x;
27	t.s += x;
28	u += x;
29      }
30  if (t.s != s.s || u != s.s || i != 32 || j != 32)
31    abort ();
32  return s.s;
33}
34
35__attribute__((noinline, noclone)) int
36bar (void)
37{
38  int i, j, u = 0;
39  struct S s, t;
40  s.s = 0; t.s = 0;
41  #pragma omp simd aligned(a:32)reduction(+:s)reduction(foo:t,u)collapse(2)
42  for (i = 0; i < 32; i++)
43    for (j = 0; j < 32; j++)
44      {
45	int *q = &i;
46	int *r = &j;
47	int x = a[i][j];
48	s.s += x;
49	t.s += x;
50	u += x;
51      }
52  if (t.s != s.s || u != s.s || i != 32 || j != 32)
53    abort ();
54  return s.s;
55}
56
57int
58main ()
59{
60  int i, j;
61  for (i = 0; i < 32; i++)
62    for (j = 0; j < 32; j++)
63      a[i][j] = j + (i / 4);
64  int s = foo ();
65  if (s != 19456)
66    abort ();
67  if (bar () != 19456)
68    abort ();
69  return 0;
70}
71