1 // REQUIRES: ompx_taskgraph
2 // RUN: %libomp-cxx-compile-and-run
3 #include <iostream>
4 #include <fstream>
5 #include <sstream>
6 #include <cassert>
7
8 // Compiler-generated code (emulation)
9 typedef struct ident {
10 void* dummy;
11 } ident_t;
12
13 #ifdef __cplusplus
14 extern "C" {
15 int __kmpc_global_thread_num(ident_t *);
16 int __kmpc_start_record_task(ident_t *, int, int, int);
17 void __kmpc_end_record_task(ident_t *, int, int , int);
18 }
19 #endif
20
func(int * num_exec)21 void func(int *num_exec) {
22 #pragma omp atomic
23 (*num_exec)++;
24 }
25
26 std::string tdg_string= "digraph TDG {\n"
27 " compound=true\n"
28 " subgraph cluster {\n"
29 " label=TDG_0\n"
30 " 0[style=bold]\n"
31 " 1[style=bold]\n"
32 " 2[style=bold]\n"
33 " 3[style=bold]\n"
34 " }\n"
35 " 0 -> 1 \n"
36 " 1 -> 2 \n"
37 " 1 -> 3 \n"
38 "}";
39
main()40 int main() {
41 int num_exec = 0;
42 int x, y;
43
44 setenv("KMP_TDG_DOT","TRUE",1);
45 remove("tdg_0.dot");
46
47 #pragma omp parallel
48 #pragma omp single
49 {
50 int gtid = __kmpc_global_thread_num(nullptr);
51 int res = __kmpc_start_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */ 0);
52 if (res) {
53 #pragma omp task depend(out : x)
54 func(&num_exec);
55 #pragma omp task depend(in : x) depend(out : y)
56 func(&num_exec);
57 #pragma omp task depend(in : y)
58 func(&num_exec);
59 #pragma omp task depend(in : y)
60 func(&num_exec);
61 }
62
63 __kmpc_end_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */ 0);
64 }
65
66 assert(num_exec == 4);
67
68 std::ifstream tdg_file("tdg_0.dot");
69 assert(tdg_file.is_open());
70
71 std::stringstream tdg_file_stream;
72 tdg_file_stream << tdg_file.rdbuf();
73 int equal = tdg_string.compare(tdg_file_stream.str());
74
75 assert(equal == 0);
76
77 std::cout << "Passed" << std::endl;
78 return 0;
79 }
80 // CHECK: Passed
81