1 extern "C" void abort ();
2 
3 struct S { S (); S (long int, long int); ~S (); static int cnt1, cnt2, cnt3; long int s, t; };
4 
5 int S::cnt1;
6 int S::cnt2;
7 int S::cnt3;
8 
S()9 S::S ()
10 {
11   #pragma omp atomic
12   cnt1++;
13 }
14 
S(long int x,long int y)15 S::S (long int x, long int y) : s (x), t (y)
16 {
17   #pragma omp atomic update
18   ++cnt2;
19 }
20 
~S()21 S::~S ()
22 {
23   #pragma omp atomic
24   cnt3 = cnt3 + 1;
25   if (t < 3 || t > 9 || (t & 1) == 0)
26     abort ();
27 }
28 
29 void
bar(S * p,S * o)30 bar (S *p, S *o)
31 {
32   p->s = 1;
33   if (o->t != 5)
34     abort ();
35   p->t = 9;
36 }
37 
38 static inline void
baz(S * o,S * i)39 baz (S *o, S *i)
40 {
41   if (o->t != 5 || i->t != 9)
42     abort ();
43   o->s *= i->s;
44 }
45 
46 #pragma omp declare reduction (+: S : omp_out.s += omp_in.s) initializer (omp_priv (0, 3))
47 #pragma omp declare reduction (*: S : baz (&omp_out, &omp_in)) initializer (bar (&omp_priv, &omp_orig))
48 
49 S as[2] = { { 0, 7 }, { 0, 7 } };
50 S (&a)[2] = as;
51 S bs[7] = { { 9, 5 }, { 11, 5 }, { 1, 5 }, { 1, 5 }, { 1, 5 }, { 13, 5 }, { 15, 5 } };
52 S (&b)[7] = bs;
53 S es[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
54 S (&e)[3] = es;
55 S fs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
56 S (&f)[5] = fs;
57 S gs[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
58 S (&g)[4] = gs;
59 S hs[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
60 S (&h)[3] = hs;
61 S ks[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
62 S (&k)[4][2] = ks;
63 S *ss;
64 S *&s = ss;
65 S (*ts)[2];
66 S (*&t)[2] = ts;
67 
68 void
foo(int & n,S * & c,S * & d,S (& m)[3],S * & r,S (& o)[4],S * & p,S (& q)[4][2])69 foo (int &n, S *&c, S *&d, S (&m)[3], S *&r, S (&o)[4], S *&p, S (&q)[4][2])
70 {
71   int i;
72   for (i = 0; i < 2; i++)
73     #pragma omp task in_reduction (+: a, c[:2]) in_reduction (*: b[2 * n:3 * n], d[0:2]) \
74 		     in_reduction (+: o[n:n*2], m[1], k[1:2][:], p[0], f[2:2]) \
75 		     in_reduction (+: q[1:2][:], g[n:n*2], e[1], h[0], r[2:2]) \
76 		     in_reduction (*: s[1:2], t[2:2][:])
77     {
78       a[0].s += 7;
79       a[1].s += 17;
80       b[2].s *= 2;
81       b[4].s *= 2;
82       c[0].s += 6;
83       d[1].s *= 2;
84       e[1].s += 19;
85       f[2].s += 21;
86       f[3].s += 23;
87       g[1].s += 25;
88       g[2].s += 27;
89       h[0].s += 29;
90       k[1][0].s += 31;
91       k[2][1].s += 33;
92       m[1].s += 19;
93       r[2].s += 21;
94       r[3].s += 23;
95       o[1].s += 25;
96       o[2].s += 27;
97       p[0].s += 29;
98       q[1][0].s += 31;
99       q[2][1].s += 33;
100       s[1].s *= 2;
101       t[2][0].s *= 2;
102       t[3][1].s *= 2;
103       if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
104 	  || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
105 	abort ();
106       for (int z = 0; z < 2; z++)
107 	if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
108 	    || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
109 	    || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
110 	    || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
111 	    || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
112 	    || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
113 	    || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
114 	  abort ();
115       for (int z = 0; z < 3; z++)
116 	if (b[z + 2].t != 5 && b[z + 2].t != 9)
117 	  abort ();
118     }
119 }
120 
121 void
test(int & n)122 test (int &n)
123 {
124   S cs[2] = { { 0, 7 }, { 0, 7 } };
125   S (&c)[2] = cs;
126   S ps[3] = { { 0, 7 }, { 1, 7 }, { 4, 7 } };
127   S (&p)[3] = ps;
128   S qs[4][2] = { { { 5, 7 }, { 6, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 0, 7 }, { 0, 7 } }, { { 7, 7 }, { 8, 7 } } };
129   S (&q)[4][2] = qs;
130   S sb[4] = { { 5, 5 }, { 1, 5 }, { 1, 5 }, { 6, 5 } };
131   S tb[5][2] = { { { 9, 5 }, { 10, 5 } }, { { 11, 5 }, { 12, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 1, 5 }, { 1, 5 } }, { { 13, 5 }, { 14, 5 } } };
132   S ms[3] = { { 5, 7 }, { 0, 7 }, { 5, 7 } };
133   S os[4] = { { 1, 7 }, { 0, 7 }, { 0, 7 }, { 2, 7 } };
134   s = sb;
135   t = tb;
136   #pragma omp parallel
137   #pragma omp single
138   {
139     S ds[] = { { 1, 5 }, { 1, 5 } };
140     S (&d)[2] = ds;
141     S (&m)[3] = ms;
142     S rs[5] = { { 6, 7 }, { 7, 7 }, { 0, 7 }, { 0, 7 }, { 9, 7 } };
143     S (&r)[5] = rs;
144     S (&o)[4] = os;
145     #pragma omp taskgroup task_reduction (+: a, c) task_reduction (*: b[2 * n:3 * n], d) \
146 			  task_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][0:2]) \
147 			  task_reduction (+: o[n:n*2], m[1], q[1:2][:], p[0], r[2:2]) \
148 			  task_reduction (*: t[2:2][:], s[1:n + 1])
149     {
150       int i;
151       for (i = 0; i < 4; i++)
152 	#pragma omp task in_reduction (+: a, c) in_reduction (*: b[2 * n:3 * n], d) \
153 			 in_reduction (+: o[n:n*2], q[1:2][:], p[0], m[1], r[2:2]) \
154 			 in_reduction (+: g[n:n * 2], e[1], k[1:2][:], h[0], f[2:2]) \
155 			 in_reduction (*: s[1:2], t[2:2][:])
156 	{
157 	  int j;
158 	  a[0].s += 2;
159 	  a[1].s += 3;
160 	  b[2].s *= 2;
161 	  f[3].s += 8;
162 	  g[1].s += 9;
163 	  g[2].s += 10;
164 	  h[0].s += 11;
165 	  k[1][1].s += 13;
166 	  k[2][1].s += 15;
167 	  m[1].s += 16;
168 	  r[2].s += 8;
169 	  s[1].s *= 2;
170 	  t[2][1].s *= 2;
171 	  t[3][1].s *= 2;
172 	  if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
173 	      || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
174 	    abort ();
175 	  for (int z = 0; z < 2; z++)
176 	    if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
177 		|| (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
178 		|| (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
179 		|| (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
180 		|| (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
181 		|| (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
182 		|| (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
183 	      abort ();
184 	  for (int z = 0; z < 3; z++)
185 	    if (b[z + 2].t != 5 && b[z + 2].t != 9)
186 	      abort ();
187 	  for (j = 0; j < 2; j++)
188 	    #pragma omp task in_reduction (+: a, c[:2]) \
189 			     in_reduction (*: b[2 * n:3 * n], d[n - 1:n + 1]) \
190 			     in_reduction (+: e[1], f[2:2], g[n:n*2], h[0], k[1:2][:2]) \
191 			     in_reduction (+: m[1], r[2:2], o[n:n*2], p[0], q[1:2][:2]) \
192 			     in_reduction (*: s[n:2], t[2:2][:])
193 	    {
194 	      m[1].s += 6;
195 	      r[2].s += 7;
196 	      q[1][0].s += 17;
197 	      q[2][0].s += 19;
198 	      a[0].s += 4;
199 	      a[1].s += 5;
200 	      b[3].s *= 2;
201 	      b[4].s *= 2;
202 	      f[3].s += 18;
203 	      g[1].s += 29;
204 	      g[2].s += 18;
205 	      h[0].s += 19;
206 	      s[2].s *= 2;
207 	      t[2][0].s *= 2;
208 	      t[3][0].s *= 2;
209 	      S *cp = c;
210 	      S *dp = d;
211 	      S *rp = r;
212 	      S *pp = p;
213 	      if ((e[1].t != 7 && e[1].t != 3) || (h[0].t != 7 && h[0].t != 3)
214 		  || (m[1].t != 7 && m[1].t != 3) || (p[0].t != 7 && p[0].t != 3))
215 		abort ();
216 	      for (int z = 0; z < 2; z++)
217 		if ((a[z].t != 7 && a[z].t != 3) || (c[z].t != 7 && c[z].t != 3)
218 		    || (d[z].t != 5 && d[z].t != 9) || (f[z + 2].t != 7 && f[z + 2].t != 3)
219 		    || (g[z + 1].t != 7 && g[z + 1].t != 3) || (r[z + 2].t != 7 && r[z + 2].t != 3)
220 		    || (s[z + 1].t != 5 && s[z + 1].t != 9) || (o[z + 1].t != 7 && o[z + 1].t != 3)
221 		    || (k[z + 1][0].t != 7 && k[z + 1][0].t != 3) || (k[z + 1][1].t != 7 && k[z + 1][1].t != 3)
222 		    || (q[z + 1][0].t != 7 && q[z + 1][0].t != 3) || (q[z + 1][1].t != 7 && q[z + 1][1].t != 3)
223 		    || (t[z + 2][0].t != 5 && t[z + 2][0].t != 9) || (t[z + 2][1].t != 5 && t[z + 2][1].t != 9))
224 		  abort ();
225 	      for (int z = 0; z < 3; z++)
226 		if (b[z + 2].t != 5 && b[z + 2].t != 9)
227 		  abort ();
228 	      foo (n, cp, dp, m, rp, o, pp, q);
229 	      r[3].s += 18;
230 	      o[1].s += 29;
231 	      o[2].s += 18;
232 	      p[0].s += 19;
233 	      c[0].s += 4;
234 	      c[1].s += 5;
235 	      d[0].s *= 2;
236 	      e[1].s += 6;
237 	      f[2].s += 7;
238 	      k[1][0].s += 17;
239 	      k[2][0].s += 19;
240 	    }
241 	  r[3].s += 8;
242 	  o[1].s += 9;
243 	  o[2].s += 10;
244 	  p[0].s += 11;
245 	  q[1][1].s += 13;
246 	  q[2][1].s += 15;
247 	  b[3].s *= 2;
248 	  c[0].s += 4;
249 	  c[1].s += 9;
250 	  d[0].s *= 2;
251 	  e[1].s += 16;
252 	  f[2].s += 8;
253 	}
254     }
255     if (d[0].s != 1LL << (8 + 4)
256 	|| d[1].s != 1LL << 16
257 	|| m[0].s != 5
258 	|| m[1].s != 19 * 16 + 6 * 8 + 16 * 4
259 	|| m[2].s != 5
260 	|| r[0].s != 6
261 	|| r[1].s != 7
262 	|| r[2].s != 21 * 16 + 7 * 8 + 8 * 4
263 	|| r[3].s != 23 * 16 + 18 * 8 + 8 * 4
264 	|| r[4].s != 9
265 	|| o[0].s != 1
266 	|| o[1].s != 25 * 16 + 29 * 8 + 9 * 4
267 	|| o[2].s != 27 * 16 + 18 * 8 + 10 * 4
268 	|| o[3].s != 2)
269       abort ();
270     if (e[1].t != 7 || h[0].t != 7 || m[1].t != 7 || p[0].t != 7)
271       abort ();
272     for (int z = 0; z < 2; z++)
273       if (a[z].t != 7 || c[z].t != 7 || d[z].t != 5 || f[z + 2].t != 7
274 	  || g[z + 1].t != 7 || r[z + 2].t != 7 || s[z + 1].t != 5 || o[z + 1].t != 7
275 	  || k[z + 1][0].t != 7 || k[z + 1][1].t != 7 || q[z + 1][0].t != 7 || q[z + 1][1].t != 7
276 	  || t[z + 2][0].t != 5 || t[z + 2][1].t != 5)
277 	abort ();
278     for (int z = 0; z < 3; z++)
279       if (b[z + 2].t != 5)
280 	abort ();
281   }
282   if (a[0].s != 7 * 16 + 4 * 8 + 2 * 4
283       || a[1].s != 17 * 16 + 5 * 8 + 3 * 4
284       || b[0].s != 9 || b[1].s != 11
285       || b[2].s != 1LL << (16 + 4)
286       || b[3].s != 1LL << (8 + 4)
287       || b[4].s != 1LL << (16 + 8)
288       || b[5].s != 13 || b[6].s != 15
289       || c[0].s != 6 * 16 + 4 * 8 + 4 * 4
290       || c[1].s != 5 * 8 + 9 * 4
291       || e[0].s != 5
292       || e[1].s != 19 * 16 + 6 * 8 + 16 * 4
293       || e[2].s != 5
294       || f[0].s != 6
295       || f[1].s != 7
296       || f[2].s != 21 * 16 + 7 * 8 + 8 * 4
297       || f[3].s != 23 * 16 + 18 * 8 + 8 * 4
298       || f[4].s != 9
299       || g[0].s != 1
300       || g[1].s != 25 * 16 + 29 * 8 + 9 * 4
301       || g[2].s != 27 * 16 + 18 * 8 + 10 * 4
302       || g[3].s != 2
303       || h[0].s != 29 * 16 + 19 * 8 + 11 * 4
304       || h[1].s != 1 || h[2].s != 4
305       || k[0][0].s != 5 || k[0][1].s != 6
306       || k[1][0].s != 31 * 16 + 17 * 8
307       || k[1][1].s != 13 * 4
308       || k[2][0].s != 19 * 8
309       || k[2][1].s != 33 * 16 + 15 * 4
310       || k[3][0].s != 7 || k[3][1].s != 8
311       || p[0].s != 29 * 16 + 19 * 8 + 11 * 4
312       || p[1].s != 1 || p[2].s != 4
313       || q[0][0].s != 5 || q[0][1].s != 6
314       || q[1][0].s != 31 * 16 + 17 * 8
315       || q[1][1].s != 13 * 4
316       || q[2][0].s != 19 * 8
317       || q[2][1].s != 33 * 16 + 15 * 4
318       || q[3][0].s != 7 || q[3][1].s != 8
319       || sb[0].s != 5
320       || sb[1].s != 1LL << (16 + 4)
321       || sb[2].s != 1LL << 8
322       || sb[3].s != 6
323       || tb[0][0].s != 9 || tb[0][1].s != 10 || tb[1][0].s != 11 || tb[1][1].s != 12
324       || tb[2][0].s != 1LL << (16 + 8)
325       || tb[2][1].s != 1LL << 4
326       || tb[3][0].s != 1LL << 8
327       || tb[3][1].s != 1LL << (16 + 4)
328       || tb[4][0].s != 13 || tb[4][1].s != 14)
329     abort ();
330 }
331 
332 int
main()333 main ()
334 {
335   int c1 = S::cnt1, c2 = S::cnt2, c3 = S::cnt3;
336   int n = 1;
337   test (n);
338   if (S::cnt1 + S::cnt2 - c1 - c2 != S::cnt3 - c3)
339     abort ();
340   return 0;
341 }
342