1 // REQUIRES: ompx_taskgraph
2 // RUN: %libomp-cxx-compile-and-run
3 #include <iostream>
4 #include <cassert>
5 #define NT 20
6 #define MULTIPLIER 100
7 #define DECREMENT 5
8
9 // Compiler-generated code (emulation)
10 typedef struct ident {
11 void* dummy;
12 } ident_t;
13
14 int val;
15 #ifdef __cplusplus
16 extern "C" {
17 int __kmpc_global_thread_num(ident_t *);
18 int __kmpc_start_record_task(ident_t *, int, int, int);
19 void __kmpc_end_record_task(ident_t *, int, int , int);
20 }
21 #endif
22
sub()23 void sub() {
24 #pragma omp atomic
25 val -= DECREMENT;
26 }
27
add()28 void add() {
29 #pragma omp atomic
30 val += DECREMENT;
31 }
32
mult()33 void mult() {
34 // no atomicity needed, can only be executed by 1 thread
35 // and no concurrency with other tasks possible
36 val *= MULTIPLIER;
37 }
38
main()39 int main() {
40 int num_tasks = 0;
41 int *x, *y;
42 #pragma omp parallel
43 #pragma omp single
44 for (int iter = 0; iter < NT; ++iter) {
45 int gtid = __kmpc_global_thread_num(nullptr);
46 int res = __kmpc_start_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */0);
47 if (res) {
48 num_tasks++;
49 #pragma omp task depend(out:y)
50 add();
51 #pragma omp task depend(out:x)
52 sub();
53 #pragma omp task depend(in:x,y)
54 mult();
55 }
56 __kmpc_end_record_task(nullptr, gtid, /* kmp_tdg_flags */0, /* tdg_id */0);
57 res = __kmpc_start_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */1);
58 if (res) {
59 num_tasks++;
60 #pragma omp task depend(out:y)
61 add();
62 #pragma omp task depend(out:x)
63 sub();
64 #pragma omp task depend(in:x,y)
65 mult();
66 }
67 __kmpc_end_record_task(nullptr, gtid, /* kmp_tdg_flags */0, /* tdg_id */1);
68 }
69
70 assert(num_tasks==2);
71 assert(val==0);
72
73 std::cout << "Passed" << std::endl;
74 return 0;
75 }
76 // CHECK: Passed
77