1 // { dg-require-effective-target size32plus }
2 
3 extern "C" void abort ();
4 
5 struct S {
6   inline S ();
7   inline ~S ();
8   inline S (const S &);
9   inline S & operator= (const S &);
10   int s;
11 };
12 
S()13 S::S () : s (0)
14 {
15 }
16 
~S()17 S::~S ()
18 {
19 }
20 
S(const S & x)21 S::S (const S &x)
22 {
23   s = x.s;
24 }
25 
26 S &
27 S::operator= (const S &x)
28 {
29   s = x.s;
30   return *this;
31 }
32 
33 static inline void
ini(S & x)34 ini (S &x)
35 {
36   x.s = 0;
37 }
38 
39 S r, a[1024], b[1024];
40 
41 #pragma omp declare reduction (+: S: omp_out.s += omp_in.s)
42 #pragma omp declare reduction (plus: S: omp_out.s += omp_in.s) initializer (ini (omp_priv))
43 
44 __attribute__((noipa)) void
foo(S * a,S * b,S & r)45 foo (S *a, S *b, S &r)
46 {
47   #pragma omp for reduction (inscan, +:r)
48   for (int i = 0; i < 1024; i++)
49     {
50       b[i] = r;
51       #pragma omp scan exclusive(r)
52       r.s += a[i].s;
53     }
54 }
55 
56 __attribute__((noipa)) S
bar(void)57 bar (void)
58 {
59   S s;
60   #pragma omp parallel
61   #pragma omp for reduction (inscan, plus:s)
62   for (int i = 0; i < 1024; i++)
63     {
64       b[i] = s;
65       #pragma omp scan exclusive(s)
66       s.s += 2 * a[i].s;
67     }
68   return s;
69 }
70 
71 __attribute__((noipa)) void
baz(S * a,S * b,S & r)72 baz (S *a, S *b, S &r)
73 {
74   #pragma omp parallel for reduction (inscan, +:r)
75   for (int i = 0; i < 1024; i++)
76     {
77       b[i] = r;
78       #pragma omp scan exclusive(r)
79       r.s += a[i].s;
80     }
81 }
82 
83 __attribute__((noipa)) S
qux(void)84 qux (void)
85 {
86   S s;
87   #pragma omp parallel for reduction (inscan, plus:s)
88   for (int i = 0; i < 1024; i++)
89     {
90       b[i] = s;
91       #pragma omp scan exclusive(s)
92       s.s += 2 * a[i].s;
93     }
94   return s;
95 }
96 
97 int
main()98 main ()
99 {
100   S s;
101   for (int i = 0; i < 1024; ++i)
102     {
103       a[i].s = i;
104       b[i].s = -1;
105       asm ("" : "+g" (i));
106     }
107   #pragma omp parallel
108   foo (a, b, r);
109   if (r.s != 1024 * 1023 / 2)
110     abort ();
111   for (int i = 0; i < 1024; ++i)
112     {
113       if (b[i].s != s.s)
114 	abort ();
115       else
116 	b[i].s = 25;
117       s.s += i;
118     }
119   if (bar ().s != 1024 * 1023)
120     abort ();
121   s.s = 0;
122   for (int i = 0; i < 1024; ++i)
123     {
124       if (b[i].s != s.s)
125 	abort ();
126       s.s += 2 * i;
127     }
128   r.s = 0;
129   baz (a, b, r);
130   if (r.s != 1024 * 1023 / 2)
131     abort ();
132   s.s = 0;
133   for (int i = 0; i < 1024; ++i)
134     {
135       if (b[i].s != s.s)
136 	abort ();
137       else
138 	b[i].s = 25;
139       s.s += i;
140     }
141   if (qux ().s != 1024 * 1023)
142     abort ();
143   s.s = 0;
144   for (int i = 0; i < 1024; ++i)
145     {
146       if (b[i].s != s.s)
147 	abort ();
148       s.s += 2 * i;
149     }
150 }
151