1ae044467SAndreyChurbanov // RUN: %libomp-compile-and-run
2ae044467SAndreyChurbanov
38289f289SJoachim Protze // Parsing error until gcc8:
48289f289SJoachim Protze // UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7, gcc-8
58289f289SJoachim Protze
6f2261714SJoachim Protze // Parsing error until clang11:
7f2261714SJoachim Protze // UNSUPPORTED: clang-10, clang-9, clang-8, clang-7
8f2261714SJoachim Protze
9*44575657SPeyton, Jonathan L // No icc compiler support yet
10*44575657SPeyton, Jonathan L // XFAIL: icc
118289f289SJoachim Protze
12ae044467SAndreyChurbanov #include <stdio.h>
13ae044467SAndreyChurbanov #include <omp.h>
14ae044467SAndreyChurbanov
15ae044467SAndreyChurbanov int r;
16ae044467SAndreyChurbanov
work(int k,int l)17ae044467SAndreyChurbanov int work(int k, int l)
18ae044467SAndreyChurbanov {
19ae044467SAndreyChurbanov return k + l + 1;
20ae044467SAndreyChurbanov }
bar(int i)21ae044467SAndreyChurbanov void bar(int i) {
22ae044467SAndreyChurbanov #pragma omp taskgroup task_reduction(+:r)
23ae044467SAndreyChurbanov { int th_gen = omp_get_thread_num();
24ae044467SAndreyChurbanov #pragma omp task in_reduction(+:r) firstprivate(i, th_gen)
25ae044467SAndreyChurbanov {
26ae044467SAndreyChurbanov r += work(i, 0);
27ae044467SAndreyChurbanov printf("executing task (%d, 0), th %d (gen by th %d)\n", i, omp_get_thread_num(), th_gen);
28ae044467SAndreyChurbanov }
29ae044467SAndreyChurbanov #pragma omp task in_reduction(+:r) firstprivate(i, th_gen)
30ae044467SAndreyChurbanov {
31ae044467SAndreyChurbanov r += work(i, 1);
32ae044467SAndreyChurbanov printf("executing task (%d, 1), th %d (gen by th %d)\n", i, omp_get_thread_num(), th_gen);
33ae044467SAndreyChurbanov }
34ae044467SAndreyChurbanov }
35ae044467SAndreyChurbanov }
foo()36ae044467SAndreyChurbanov int foo() {
37ae044467SAndreyChurbanov int i;
38ae044467SAndreyChurbanov int th_gen = omp_get_thread_num();
39ae044467SAndreyChurbanov #pragma omp taskgroup task_reduction(+:r)
40ae044467SAndreyChurbanov {
41ae044467SAndreyChurbanov bar(0);
42ae044467SAndreyChurbanov }
43ae044467SAndreyChurbanov printf("th %d passed bar0\n", th_gen);
44ae044467SAndreyChurbanov #pragma omp taskloop reduction(+:r) firstprivate(th_gen)
45ae044467SAndreyChurbanov for (i = 1; i < 4; ++i) {
46ae044467SAndreyChurbanov bar(i);
47ae044467SAndreyChurbanov printf("th %d (gen by th %d) passed bar%d in taskloop\n", omp_get_thread_num(), th_gen, i);
480fca7664SAlexey Bataev #pragma omp task in_reduction(+:r)
49ae044467SAndreyChurbanov r += i;
50ae044467SAndreyChurbanov }
51ae044467SAndreyChurbanov return 0;
52ae044467SAndreyChurbanov }
53dab5d6c2SAndreyChurbanov // res = ((1+2)+(2+3)+(3+4)+(4+5)+1+2+3) = 30
54dab5d6c2SAndreyChurbanov #define res 30
main()55ae044467SAndreyChurbanov int main()
56ae044467SAndreyChurbanov {
57ae044467SAndreyChurbanov r = 0;
58ae044467SAndreyChurbanov #pragma omp parallel num_threads(2)
59dab5d6c2SAndreyChurbanov { // barrier ensures threads have started before tasks creation
60dab5d6c2SAndreyChurbanov #pragma omp barrier
61dab5d6c2SAndreyChurbanov // single ensures no race condition between taskgroup reductions
62dab5d6c2SAndreyChurbanov #pragma omp single nowait
63ae044467SAndreyChurbanov foo();
64dab5d6c2SAndreyChurbanov }
65ae044467SAndreyChurbanov if (r == res) {
66ae044467SAndreyChurbanov return 0;
67ae044467SAndreyChurbanov } else {
68ae044467SAndreyChurbanov printf("error r = %d (!= %d)\n", r, res);
69ae044467SAndreyChurbanov return 1;
70ae044467SAndreyChurbanov }
71ae044467SAndreyChurbanov }
72