Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / openmp / tools / archer / tests / task / omp_task_depend_all.c
blob7a8063cc925d75362467c6b6af3686671ef6e7ee
1 // RUN--: %libarcher-compile-and-run | FileCheck %s --check-prefix=NOENV
2 // RUN: %libarcher-compile && env ARCHER_OPTIONS="all_memory=1" \
3 // RUN: %libarcher-run | FileCheck %s --check-prefix=ENV
4 // REQUIRES: tsan
6 // The runtime currently does not get dependency information from GCC.
7 // UNSUPPORTED: gcc
9 // Tests OMP 5.x task dependence "omp_all_memory",
10 // emulates compiler codegen versions for new dep kind
12 // Task tree created:
13 // task0 - task1 (in: i1, i2)
14 // \
15 // task2 (inoutset: i2), (in: i1)
16 // /
17 // task3 (omp_all_memory) via flag=0x80
18 // /
19 // task4 - task5 (in: i1, i2)
20 // /
21 // task6 (omp_all_memory) via addr=-1
22 // /
23 // task7 (omp_all_memory) via flag=0x80
24 // /
25 // task8 (in: i3)
28 #include <omp.h>
29 #include <stdio.h>
31 #ifdef _WIN32
32 #include <windows.h>
33 #define mysleep(n) Sleep(n)
34 #else
35 #include <unistd.h>
36 #define mysleep(n) usleep((n)*1000)
37 #endif
39 // to check the # of concurrent tasks (must be 1 for MTX, <3 for other kinds)
40 static int checker = 0;
41 static int err = 0;
42 #ifndef DELAY
43 #define DELAY 100
44 #endif
46 // ---------------------------------------------------------------------------
47 // internal data to emulate compiler codegen
48 typedef struct DEP {
49 size_t addr;
50 size_t len;
51 unsigned char flags;
52 } dep;
53 #define DEP_ALL_MEM 0x80
54 typedef struct task {
55 void **shareds;
56 void *entry;
57 int part_id;
58 void *destr_thunk;
59 int priority;
60 long long device_id;
61 int f_priv;
62 } task_t;
63 #define TIED 1
64 typedef int (*entry_t)(int, task_t *);
65 typedef struct ID {
66 int reserved_1;
67 int flags;
68 int reserved_2;
69 int reserved_3;
70 char *psource;
71 } id;
72 // thunk routine for tasks with ALL dependency
73 int thunk_m(int gtid, task_t *ptask) {
74 int lcheck, th;
75 #pragma omp atomic capture
76 lcheck = ++checker;
77 th = omp_get_thread_num();
78 printf("task m_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);
79 if (lcheck != 1) { // no more than 1 task at a time
80 err++;
81 printf("Error m1, checker %d != 1\n", lcheck);
83 mysleep(DELAY);
84 #pragma omp atomic read
85 lcheck = checker; // must still be equal to 1
86 if (lcheck != 1) {
87 err++;
88 printf("Error m2, checker %d != 1\n", lcheck);
90 #pragma omp atomic
91 --checker;
92 return 0;
94 // thunk routine for tasks with inoutset dependency
95 int thunk_s(int gtid, task_t *ptask) {
96 int lcheck, th;
97 #pragma omp atomic capture
98 lcheck = ++checker; // 1
99 th = omp_get_thread_num();
100 printf("task 2_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);
101 if (lcheck != 1) { // no more than 1 task at a time
102 err++;
103 printf("Error s1, checker %d != 1\n", lcheck);
105 mysleep(DELAY);
106 #pragma omp atomic read
107 lcheck = checker; // must still be equal to 1
108 if (lcheck != 1) {
109 err++;
110 printf("Error s2, checker %d != 1\n", lcheck);
112 #pragma omp atomic
113 --checker;
114 return 0;
117 #ifdef __cplusplus
118 extern "C" {
119 #endif
120 int __kmpc_global_thread_num(id *);
121 task_t *__kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz,
122 size_t shar, entry_t rtn);
123 int __kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int ndeps,
124 dep *dep_lst, int nd_noalias, dep *noalias_lst);
125 static id loc = {0, 2, 0, 0, ";file;func;0;0;;"};
126 #ifdef __cplusplus
127 } // extern "C"
128 #endif
129 // End of internal data
130 // ---------------------------------------------------------------------------
132 int main() {
133 char *ompx_all_memory = (void *)0xffffffffffffffff;
134 int i1, i2, i3;
135 omp_set_num_threads(8);
136 omp_set_dynamic(0);
137 #pragma omp parallel
139 #pragma omp single nowait
141 dep sdep[2];
142 task_t *ptr;
143 int gtid = __kmpc_global_thread_num(&loc);
144 int t = omp_get_thread_num();
145 #pragma omp task depend(in : i1, i2)
146 { // task 0
147 int lcheck, th;
148 #pragma omp atomic capture
149 lcheck = ++checker; // 1 or 2
150 th = omp_get_thread_num();
151 printf("task 0_%d, th %d, checker %d\n", t, th, lcheck);
152 if (lcheck > 2 || lcheck < 1) {
153 err++; // no more than 2 tasks concurrently
154 printf("Error1, checker %d, not 1 or 2\n", lcheck);
156 mysleep(DELAY);
157 #pragma omp atomic read
158 lcheck = checker; // 1 or 2
159 if (lcheck > 2 || lcheck < 1) {
160 #pragma omp atomic
161 err++;
162 printf("Error2, checker %d, not 1 or 2\n", lcheck);
164 #pragma omp atomic
165 --checker;
167 #pragma omp task depend(in : i1, i2)
168 { // task 1
169 int lcheck, th;
170 #pragma omp atomic capture
171 lcheck = ++checker; // 1 or 2
172 th = omp_get_thread_num();
173 printf("task 1_%d, th %d, checker %d\n", t, th, lcheck);
174 if (lcheck > 2 || lcheck < 1) {
175 err++; // no more than 2 tasks concurrently
176 printf("Error3, checker %d, not 1 or 2\n", lcheck);
178 mysleep(DELAY);
179 #pragma omp atomic read
180 lcheck = checker; // 1 or 2
181 if (lcheck > 2 || lcheck < 1) {
182 err++;
183 printf("Error4, checker %d, not 1 or 2\n", lcheck);
185 #pragma omp atomic
186 --checker;
188 // compiler codegen start
189 // task2
190 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_s);
191 sdep[0].addr = (size_t)&i1;
192 sdep[0].len = 0; // not used
193 sdep[0].flags = 1; // IN
194 sdep[1].addr = (size_t)&i2;
195 sdep[1].len = 0; // not used
196 sdep[1].flags = 8; // INOUTSET
197 ptr->f_priv = t + 10; // init single first-private variable
198 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);
200 // task3
201 #pragma omp task depend(in : i1) depend(inout : ompx_all_memory[0])
203 int lcheck, th;
204 #pragma omp atomic capture
205 lcheck = ++checker;
206 th = omp_get_thread_num();
207 printf("task 3_%d, th %d, checker %d\n", t, th, lcheck);
208 if (lcheck != 1) { // no more than 1 task at a time
209 err++;
210 printf("Error m1, checker %d != 1\n", lcheck);
212 mysleep(DELAY);
213 #pragma omp atomic read
214 lcheck = checker; // must still be equal to 1
215 if (lcheck != 1) {
216 err++;
217 printf("Error m2, checker %d != 1\n", lcheck);
219 #pragma omp atomic
220 --checker;
222 // compiler codegen end
223 #pragma omp task depend(in : i1, i2)
224 { // task 4
225 int lcheck, th;
226 #pragma omp atomic capture
227 lcheck = ++checker; // 1 or 2
228 th = omp_get_thread_num();
229 printf("task 4_%d, th %d, checker %d\n", t, th, lcheck);
230 if (lcheck > 2 || lcheck < 1) {
231 err++; // no more than 2 tasks concurrently
232 printf("Error5, checker %d, not 1 or 2\n", lcheck);
234 mysleep(DELAY);
235 #pragma omp atomic read
236 lcheck = checker; // 1 or 2
237 if (lcheck > 2 || lcheck < 1) {
238 err++;
239 printf("Error6, checker %d, not 1 or 2\n", lcheck);
241 #pragma omp atomic
242 --checker;
244 #pragma omp task depend(in : i1, i2)
245 { // task 5
246 int lcheck, th;
247 #pragma omp atomic capture
248 lcheck = ++checker; // 1 or 2
249 th = omp_get_thread_num();
250 printf("task 5_%d, th %d, checker %d\n", t, th, lcheck);
251 if (lcheck > 2 || lcheck < 1) {
252 err++; // no more than 2 tasks concurrently
253 printf("Error7, checker %d, not 1 or 2\n", lcheck);
255 mysleep(DELAY);
256 #pragma omp atomic read
257 lcheck = checker; // 1 or 2
258 if (lcheck > 2 || lcheck < 1) {
259 err++;
260 printf("Error8, checker %d, not 1 or 2\n", lcheck);
262 #pragma omp atomic
263 --checker;
265 // task6
266 #pragma omp task depend(inout : ompx_all_memory[0])
268 int lcheck, th;
269 #pragma omp atomic capture
270 lcheck = ++checker;
271 th = omp_get_thread_num();
272 printf("task 6_%d, th %d, checker %d\n", t, th, lcheck);
273 if (lcheck != 1) { // no more than 1 task at a time
274 err++;
275 printf("Error m1, checker %d != 1\n", lcheck);
277 mysleep(DELAY);
278 #pragma omp atomic read
279 lcheck = checker; // must still be equal to 1
280 if (lcheck != 1) {
281 err++;
282 printf("Error m2, checker %d != 1\n", lcheck);
284 #pragma omp atomic
285 --checker;
287 // task7
288 #pragma omp task depend(inout : ompx_all_memory[0]) depend(mutexinoutset : i3)
290 int lcheck, th;
291 #pragma omp atomic capture
292 lcheck = ++checker;
293 th = omp_get_thread_num();
294 printf("task 7_%d, th %d, checker %d\n", t, th, lcheck);
295 if (lcheck != 1) { // no more than 1 task at a time
296 err++;
297 printf("Error m1, checker %d != 1\n", lcheck);
299 mysleep(DELAY);
300 #pragma omp atomic read
301 lcheck = checker; // must still be equal to 1
302 if (lcheck != 1) {
303 err++;
304 printf("Error m2, checker %d != 1\n", lcheck);
306 #pragma omp atomic
307 --checker;
309 #pragma omp task depend(in : i3)
310 { // task 8
311 int lcheck, th;
312 #pragma omp atomic capture
313 lcheck = ++checker; // 1
314 th = omp_get_thread_num();
315 printf("task 8_%d, th %d, checker %d\n", t, th, lcheck);
316 if (lcheck != 1) {
317 err++;
318 printf("Error9, checker %d, != 1\n", lcheck);
320 mysleep(DELAY);
321 #pragma omp atomic read
322 lcheck = checker;
323 if (lcheck != 1) {
324 err++;
325 printf("Error10, checker %d, != 1\n", lcheck);
327 #pragma omp atomic
328 --checker;
330 } // single
331 } // parallel
332 if (err == 0 && checker == 0) {
333 printf("passed\n");
334 return 0;
335 } else {
336 printf("failed, err = %d, checker = %d\n", err, checker);
337 return 1;
341 // NOENV-NOT: ThreadSanitizer: data race
342 // NOENV-NOT: ThreadSanitizer: reported
343 // NOENV: omp_all_memory
344 // NOENV-NOT: ThreadSanitizer: data race
345 // NOENV-NOT: ThreadSanitizer: reported
346 // NOENV: passed
348 // ENV-NOT: ThreadSanitizer: data race
349 // ENV-NOT: ThreadSanitizer: reported
350 // ENV: passed