1// { dg-do run }
2// { dg-set-target-env-var OMP_CANCELLATION "true" }
3
4#include <omp.h>
5#include "cancel-test.h"
6
7__attribute__((noinline, noclone)) int
8foo (int *x)
9{
10  S a, b, c, d, e;
11  int v = 0, w = 0;
12  #pragma omp parallel num_threads (32) shared (v, w) private (c, d) firstprivate (e)
13  {
14    S g;
15    int i;
16    c.bump ();
17    e.bump ();
18    #pragma omp for private (d, g) firstprivate (b)
19    for (i = 0; i < 1000; ++i)
20      {
21	b.bump ();
22	d.bump ();
23	g.bump ();
24	#pragma omp cancel for if (x[0])
25	abort ();
26      }
27    #pragma omp for private (d, g) firstprivate (b)
28    for (i = 0; i < 1000; ++i)
29      {
30	b.bump ();
31	d.bump ();
32	g.bump ();
33	#pragma omp cancel for if (x[1])
34	#pragma omp atomic
35	v++;
36      }
37    #pragma omp for private (d, g) firstprivate (b)
38    for (i = 0; i < 1000; ++i)
39      {
40	b.bump ();
41	d.bump ();
42	g.bump ();
43	#pragma omp cancel for if (x[2])
44	#pragma omp atomic
45	w += 8;
46      }
47    #pragma omp for private (d, g) firstprivate (b)
48    for (i = 0; i < 1000; ++i)
49      {
50	b.bump ();
51	d.bump ();
52	g.bump ();
53	#pragma omp cancel for if (x[3])
54	#pragma omp atomic
55	v += 2;
56      }
57  }
58  if (v != 3000 || w != 0)
59    abort ();
60  #pragma omp parallel num_threads (32) shared (v, w) private (c, d) firstprivate (e)
61  {
62    S g, h;
63    int i;
64    c.bump ();
65    e.bump ();
66    /* None of these cancel directives should actually cancel anything,
67       but the compiler shouldn't know that and thus should use cancellable
68       barriers at the end of all the workshares.  */
69    #pragma omp cancel parallel if (omp_get_thread_num () == 1 && x[4])
70    #pragma omp for private (d, g) firstprivate (b)
71    for (i = 0; i < 1000; ++i)
72      {
73	b.bump ();
74	d.bump ();
75	g.bump ();
76	#pragma omp cancel for if (x[0])
77	abort ();
78      }
79    #pragma omp cancel parallel if (omp_get_thread_num () == 2 && x[4])
80    #pragma omp for private (d, g) firstprivate (b)
81    for (i = 0; i < 1000; ++i)
82      {
83	b.bump ();
84	d.bump ();
85	g.bump ();
86	#pragma omp cancel for if (x[1])
87	#pragma omp atomic
88	v++;
89      }
90    #pragma omp cancel parallel if (omp_get_thread_num () == 3 && x[4])
91    #pragma omp for private (d, g) firstprivate (b)
92    for (i = 0; i < 1000; ++i)
93      {
94	b.bump ();
95	d.bump ();
96	g.bump ();
97	#pragma omp cancel for if (x[2])
98	#pragma omp atomic
99	w += 8;
100      }
101    #pragma omp cancel parallel if (omp_get_thread_num () == 4 && x[4])
102    #pragma omp for private (d, g) firstprivate (b)
103    for (i = 0; i < 1000; ++i)
104      {
105	b.bump ();
106	d.bump ();
107	g.bump ();
108	#pragma omp cancel for if (x[3])
109	#pragma omp atomic
110	v += 2;
111      }
112    #pragma omp cancel parallel if (omp_get_thread_num () == 5 && x[4])
113  }
114  if (v != 6000 || w != 0)
115    abort ();
116  return 0;
117}
118
119int
120main ()
121{
122  int x[] = { 1, 0, 1, 0, 0 };
123  if (omp_get_cancellation ())
124    foo (x);
125  S::verify ();
126}
127