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 "C" void abort ();
7int a[1024] __attribute__((aligned (32))) = { 1 };
8struct S
9{
10  int s;
11  S () : s (0) {}
12  S (int x) : s (x) {}
13  ~S () {}
14};
15#pragma omp declare reduction (+:S:omp_out.s += omp_in.s) \
16		    initializer (omp_priv (0))
17#pragma omp declare reduction (foo:S:omp_out.s += omp_in.s) \
18		    initializer (omp_priv (0))
19#pragma omp declare reduction (foo:int:omp_out += omp_in) \
20		    initializer (omp_priv = 0)
21
22__attribute__((noinline, noclone)) S
23foo (S s)
24{
25  int i, v = 0, &u = v;
26  S t;
27  #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
28  for (i = 0; i < 1024; i++)
29    {
30      int x = a[i];
31      s.s += x;
32      t.s += x;
33      u += x;
34    }
35  if (t.s != s.s || u != s.s)
36    abort ();
37  return t;
38}
39
40__attribute__((noinline, noclone)) int
41bar (S &s, S &t)
42{
43  int i, v = 0, &u = v;
44  #pragma omp simd aligned(a : 32) reduction(+:s) reduction(foo:t, u)
45  for (i = 0; i < 1024; i++)
46    {
47      int x = a[i];
48      s.s += x;
49      t.s += x;
50      u += x;
51    }
52  if (t.s != s.s || u != s.s)
53    abort ();
54  return s.s;
55}
56
57int
58main ()
59{
60  int i;
61  for (i = 0; i < 1024; i++)
62    a[i] = (i & 31) + (i / 128);
63  S q;
64  int s = foo (q).s;
65  if (s != 19456)
66    abort ();
67  S r, v;
68  if (bar (r, v) != s)
69    abort ();
70}
71