Clang Project

clang_source_code/test/OpenMP/ordered_doacross_codegen.cpp
1// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s
2// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
3// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
4
5// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
6// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
7// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
8// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
9// expected-no-diagnostics
10
11#ifndef HEADER
12#define HEADER
13
14// CHECK: [[KMP_DIM:%.+]] = type { i64, i64, i64 }
15extern int n;
16int a[10], b[10], c[10], d[10];
17void foo();
18
19// CHECK-LABEL:bar
20void bar() {
21  int i,j;
22// CHECK: call void @__kmpc_doacross_init(
23// CHECK: call void @__kmpc_doacross_fini(
24#pragma omp parallel for ordered(2)
25  for (i = 0; i < n; ++i)
26  for (j = 0; j < n; ++j)
27    a[i] = b[i] + 1;
28}
29
30// CHECK-LABEL: @main()
31int main() {
32  int i;
33// CHECK: [[DIMS:%.+]] = alloca [1 x [[KMP_DIM]]],
34// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]])
35// CHECK: icmp
36// CHECK-NEXT: br i1 %
37// CHECK: [[CAST:%.+]] = bitcast [1 x [[KMP_DIM]]]* [[DIMS]] to i8*
38// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 24, i1 false)
39// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
40// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
41// CHECK: store i64 %{{.+}}, i64* %
42// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
43// CHECK: store i64 1, i64* %
44// CHECK: [[DIM:%.+]] = getelementptr inbounds [1 x [[KMP_DIM]]], [1 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
45// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8*
46// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 1, i8* [[CAST]])
47// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* @{{.+}}, i32 [[GTID]], i32 33, i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
48#pragma omp for ordered(1)
49  for (int i = 0; i < n; ++i) {
50    a[i] = b[i] + 1;
51    foo();
52// CHECK: invoke void [[FOO:.+]](
53// CHECK: load i32, i32* [[I:%.+]],
54// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
55// CHECK-NEXT: sdiv i32 %{{.+}}, 1
56// CHECK-NEXT: sext i32 %{{.+}} to i64
57// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
58// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
59// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
60// CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]])
61#pragma omp ordered depend(source)
62    c[i] = c[i] + 1;
63    foo();
64// CHECK: invoke void [[FOO]]
65// CHECK: load i32, i32* [[I]],
66// CHECK-NEXT: sub nsw i32 %{{.+}}, 2
67// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
68// CHECK-NEXT: sdiv i32 %{{.+}}, 1
69// CHECK-NEXT: sext i32 %{{.+}} to i64
70// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT:%.+]], i64 0, i64 0
71// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
72// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [1 x i64], [1 x i64]* [[CNT]], i64 0, i64 0
73// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
74#pragma omp ordered depend(sink : i - 2)
75    d[i] = a[i - 2];
76  }
77  // CHECK: landingpad
78  // CHECK: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
79  // CHECK: br label %
80
81  // CHECK: call void @__kmpc_for_static_fini(
82  // CHECK: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
83  // CHECK: ret i32 0
84  return 0;
85}
86
87// CHECK: define {{.+}}TestStruct
88template <typename T>
89struct TestStruct {
90  static const int M = 10;
91  static const int N = 20;
92  T i;
93  T a[N][M];
94  T b[N][M];
95  T foo(T, T);
96  T bar(T, T, T);
97  void baz(T, T);
98  TestStruct() {
99// CHECK: [[DIMS:%.+]] = alloca [2 x [[KMP_DIM]]],
100// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT:%.+]])
101// CHECK: [[CAST:%.+]] = bitcast [2 x [[KMP_DIM]]]* [[DIMS]] to i8*
102// CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 [[CAST]], i8 0, i64 48, i1 false)
103// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
104// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
105// CHECK: store i64 10, i64* %
106// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
107// CHECK: store i64 1, i64* %
108// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 1
109// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 1
110// CHECK: store i64 %{{.+}}, i64* %
111// CHECK: getelementptr inbounds [[KMP_DIM]], [[KMP_DIM]]* [[DIM]], i32 0, i32 2
112// CHECK: store i64 1, i64* %
113// CHECK: [[DIM:%.+]] = getelementptr inbounds [2 x [[KMP_DIM]]], [2 x [[KMP_DIM]]]* [[DIMS]], i64 0, i64 0
114// CHECK: [[CAST:%.+]] = bitcast [[KMP_DIM]]* [[DIM]] to i8*
115// CHECK: call void @__kmpc_doacross_init([[IDENT]], i32 [[GTID]], i32 2, i8* [[CAST]])
116// CHECK: call void @__kmpc_for_static_init_4(%struct.ident_t* @{{.+}}, i32 [[GTID]], i32 33, i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32* %{{.+}}, i32 1, i32 1)
117#pragma omp for ordered(2)
118    for (T j = 0; j < M; j++)
119      for (i = 0; i < n; i += 2) {
120        a[i][j] = foo(i, j);
121// CHECK: invoke {{.+TestStruct.+foo}}
122// CHECK: load i32*, i32** %
123// CHECK: load i32, i32* %
124// CHECK: load i32, i32* %
125// CHECK: load i32, i32* [[J:%.+]],
126// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
127// CHECK-NEXT: sdiv i32 %{{.+}}, 1
128// CHECK-NEXT: sext i32 %{{.+}} to i64
129// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0
130// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
131// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF:%.+]],
132// CHECK-NEXT: load i32, i32* [[I]],
133// CHECK-NEXT: sub nsw i32 %{{.+}}, 2
134// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
135// CHECK-NEXT: sdiv i32 %{{.+}}, 2
136// CHECK-NEXT: sext i32 %{{.+}} to i64
137// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1
138// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
139// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0
140// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
141// CHECK-NEXT: load i32, i32* [[J:%.+]],
142// CHECK-NEXT: sub nsw i32 %{{.+}}, 1
143// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
144// CHECK-NEXT: sdiv i32 %{{.+}}, 1
145// CHECK-NEXT: sext i32 %{{.+}} to i64
146// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0
147// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
148// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF]],
149// CHECK-NEXT: load i32, i32* [[I]],
150// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
151// CHECK-NEXT: sdiv i32 %{{.+}}, 2
152// CHECK-NEXT: sext i32 %{{.+}} to i64
153// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1
154// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
155// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0
156// CHECK-NEXT: call void @__kmpc_doacross_wait([[IDENT]], i32 [[GTID]], i64* [[TMP]])
157#pragma omp ordered depend(sink : j, i - 2) depend(sink : j - 1, i)
158        b[i][j] = bar(a[i][j], b[i - 1][j], b[i][j - 1]);
159// CHECK: invoke {{.+TestStruct.+bar}}
160// CHECK: load i32*, i32** %
161// CHECK: load i32, i32* %
162// CHECK: load i32, i32* %
163// CHECK: load i32, i32* [[J]],
164// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
165// CHECK-NEXT: sdiv i32 %{{.+}}, 1
166// CHECK-NEXT: sext i32 %{{.+}} to i64
167// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT:%.+]], i64 0, i64 0
168// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP:%.+]],
169// CHECK-NEXT: [[I:%.+]] = load i32*, i32** [[I_REF]],
170// CHECK-NEXT: load i32, i32* [[I]],
171// CHECK-NEXT: sub nsw i32 %{{.+}}, 0
172// CHECK-NEXT: sdiv i32 %{{.+}}, 2
173// CHECK-NEXT: sext i32 %{{.+}} to i64
174// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 1
175// CHECK-NEXT: store i64 %{{.+}}, i64* [[TMP]],
176// CHECK-NEXT: [[TMP:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[CNT]], i64 0, i64 0
177// CHECK-NEXT: call void @__kmpc_doacross_post([[IDENT]], i32 [[GTID]], i64* [[TMP]])
178#pragma omp ordered depend(source)
179        baz(a[i][j], b[i][j]);
180      }
181  }
182  // CHECK: landingpad
183  // CHECK: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
184  // CHECK: br label %
185
186  // CHECK: call void @__kmpc_for_static_fini(
187  // CHECK: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
188  // CHECK: ret
189};
190
191TestStruct<int> s;
192#endif // HEADER
193