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
foo(int * x)8 foo (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 
119 int
main()120 main ()
121 {
122   int x[] = { 1, 0, 1, 0, 0 };
123   if (omp_get_cancellation ())
124     foo (x);
125   S::verify ();
126 }
127