[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / OpenMP / scan_codegen.cpp
blob024a69b479c05c561fa4f3c46140872f46428f29
1 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
2 // RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-pch -o %t %s
3 // RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
5 // RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
6 // RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-pch -o %t %s
7 // RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
8 // SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
9 //
10 // expected-no-diagnostics
11 #ifndef HEADER
12 #define HEADER
13 void foo();
14 void bar();
16 // CHECK-LABEL: baz
17 void baz() {
18 int a = 0;
20 // CHECK: store i32 0, ptr [[A_ADDR:%.+]],
21 // CHECK: store i32 0, ptr [[OMP_CNT:%.+]],
22 // CHECK: br label %[[OMP_HEADER:.+]]
24 // CHECK: [[OMP_HEADER]]:
25 // CHECK: [[CNT_VAL:%.+]] = load i32, ptr [[OMP_CNT]],
26 // CHECK: [[CMP:%.+]] = icmp slt i32 [[CNT_VAL]], 10
27 // CHECK: br i1 [[CMP]], label %[[OMP_BODY:.+]], label %[[OMP_END:.+]]
28 #pragma omp simd reduction(inscan, + : a)
29 for (int i = 0; i < 10; ++i) {
30 // CHECK: [[OMP_BODY]]:
32 // i = OMP_CNT*1 + 0;
33 // CHECK: [[CNT_VAL:%.+]] = load i32, ptr [[OMP_CNT]],
34 // CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT_VAL]], 1
35 // CHECK: [[ADD:%.+]] = add nsw i32 0, [[MUL]]
36 // CHECK: store i32 [[ADD]], ptr [[I_ADDR:%.+]],
38 // A_PRIV = 0;
39 // CHECK: store i32 0, ptr [[A_PRIV_ADDR:%.+]],
41 // goto DISPATCH;
42 // CHECK: br label %[[DISPATCH:[^,]+]]
44 // INPUT_PHASE:
45 // foo();
46 // goto REDUCE;
47 // CHECK: [[INPUT_PHASE:.+]]:
48 // CHECK: call void @{{.*}}foo{{.*}}()
49 // CHECK: br label %[[REDUCE:[^,]+]]
50 foo();
52 // DISPATCH:
53 // goto INPUT_PHASE;
54 // CHECK: [[DISPATCH]]:
55 // CHECK: br label %[[INPUT_PHASE]]
57 // REDUCE:
58 // A = A_PRIV + A;
59 // A_PRIV = A;
60 // goto SCAN_PHASE;
61 // CHECK: [[REDUCE]]:
62 // CHECK: [[A:%.+]] = load i32, ptr [[A_ADDR]],
63 // CHECK: [[A_PRIV:%.+]] = load i32, ptr [[A_PRIV_ADDR]],
64 // CHECK: [[SUM:%.+]] = add nsw i32 [[A]], [[A_PRIV]]
65 // CHECK: store i32 [[SUM]], ptr [[A_ADDR]],
66 // CHECK: [[A:%.+]] = load i32, ptr [[A_ADDR]],
67 // CHECK: store i32 [[A]], ptr [[A_PRIV_ADDR]],
68 // CHECK: br label %[[SCAN_PHASE:[^,]+]]
69 #pragma omp scan inclusive(a)
71 // SCAN_PHASE:
72 // bar();
73 // goto CONTINUE;
74 // CHECK: [[SCAN_PHASE]]:
75 // CHECK: call void @{{.*}}bar{{.*}}()
76 // CHECK: br label %[[CONTINUE:[^,]+]]
77 bar();
79 // CHECK: [[CONTINUE]]:
80 // CHECK: br label %[[INC_BLOCK:[^,]+]]
82 // ++OMP_CNT;
83 // CHECK: [[INC_BLOCK]]:
84 // CHECK: [[CNT:%.+]] = load i32, ptr [[OMP_CNT]],
85 // CHECK: [[INC:%.+]] = add nsw i32 [[CNT]], 1
86 // CHECK: store i32 [[INC]], ptr [[OMP_CNT]],
87 // CHECK: br label %[[OMP_HEADER]]
89 // CHECK: [[OMP_END]]:
92 struct S {
93 int a;
94 S() {}
95 ~S() {}
96 S& operator+(const S&);
97 S& operator=(const S&);
100 // CHECK-LABEL: xyz
101 void xyz() {
102 S s[2];
104 // CHECK: [[S_BEGIN:%.+]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ADDR:%.+]], i{{.+}} 0, i{{.+}} 0
105 // CHECK: [[S_END:%.+]] = getelementptr {{.*}}%struct.S, ptr [[S_BEGIN]], i{{.+}} 2
106 // CHECK: br label %[[ARRAY_INIT:.+]]
107 // CHECK: [[ARRAY_INIT]]:
108 // CHECK: [[S_CUR:%.+]] = phi ptr [ [[S_BEGIN]], %{{.+}} ], [ [[S_NEXT:%.+]], %[[ARRAY_INIT]] ]
109 // CHECK: call void [[CONSTR:@.+]](ptr {{[^,]*}} [[S_CUR]])
110 // CHECK: [[S_NEXT]] = getelementptr inbounds %struct.S, ptr [[S_CUR]], i{{.+}} 1
111 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[S_NEXT]], [[S_END]]
112 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_INIT]]
113 // CHECK: [[DONE]]:
114 // CHECK: store i32 0, ptr [[OMP_CNT:%.+]],
115 // CHECK: br label %[[OMP_HEADER:.+]]
117 // CHECK: [[OMP_HEADER]]:
118 // CHECK: [[CNT_VAL:%.+]] = load i32, ptr [[OMP_CNT]],
119 // CHECK: [[CMP:%.+]] = icmp slt i32 [[CNT_VAL]], 10
120 // CHECK: br i1 [[CMP]], label %[[OMP_BODY:.+]], label %[[OMP_END:.+]]
121 #pragma omp simd reduction(inscan, + : s)
122 for (int i = 0; i < 10; ++i) {
123 // CHECK: [[OMP_BODY]]:
125 // i = OMP_CNT*1 + 0;
126 // CHECK: [[CNT_VAL:%.+]] = load i32, ptr [[OMP_CNT]],
127 // CHECK: [[MUL:%.+]] = mul nsw i32 [[CNT_VAL]], 1
128 // CHECK: [[ADD:%.+]] = add nsw i32 0, [[MUL]]
129 // CHECK: store i32 [[ADD]], ptr [[I_ADDR:%.+]],
131 // S S_PRIV[2];
132 // CHECK: [[S_BEGIN:%.+]] = getelementptr inbounds [2 x %struct.S], ptr [[S_PRIV_ADDR:%.+]], i{{.+}} 0, i{{.+}} 0
133 // CHECK: [[S_END:%.+]] = getelementptr {{.*}}%struct.S, ptr [[S_BEGIN]], i{{.+}} 2
134 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[S_BEGIN]], [[S_END]]
135 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_INIT:[^,]+]]
136 // CHECK: [[ARRAY_INIT]]:
137 // CHECK: [[S_CUR:%.+]] = phi ptr [ [[S_BEGIN]], %[[OMP_BODY]] ], [ [[S_NEXT:%.+]], %[[ARRAY_INIT]] ]
138 // CHECK: call void [[CONSTR]](ptr {{[^,]*}} [[S_CUR]])
139 // CHECK: [[S_NEXT]] = getelementptr {{.*}}%struct.S, ptr [[S_CUR]], i{{.+}} 1
140 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[S_NEXT]], [[S_END]]
141 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_INIT]]
142 // CHECK: [[DONE]]:
144 // goto DISPATCH;
145 // CHECK: br label %[[DISPATCH:[^,]+]]
147 // SCAN_PHASE:
148 // foo();
149 // goto CONTINUE;
150 // CHECK: [[SCAN_PHASE:.+]]:
151 // CHECK: call void @{{.*}}foo{{.*}}()
152 // CHECK: br label %[[CONTINUE:[^,]+]]
153 foo();
155 // DISPATCH:
156 // goto INPUT_PHASE;
157 // CHECK: [[DISPATCH]]:
158 // CHECK: br label %[[INPUT_PHASE:[^,]+]]
160 // REDUCE:
161 // TEMP = S;
162 // S = S_PRIV + S;
163 // S_PRIV = TEMP;
164 // goto SCAN_PHASE;
165 // CHECK: [[REDUCE:.+]]:
167 // S TEMP[2];
168 // CHECK: [[TEMP_ARR_BEG:%.+]] = getelementptr inbounds [2 x %struct.S], ptr [[TEMP_ARR:%.+]], i32 0, i32 0
169 // CHECK: [[TEMP_ARR_END:%.+]] = getelementptr inbounds %struct.S, ptr [[TEMP_ARR_BEG]], i64 2
170 // CHECK: br label %[[BODY:[^,]+]]
171 // CHECK: [[BODY]]:
172 // CHECK: [[CUR:%.+]] = phi ptr [ [[TEMP_ARR_BEG]], %[[REDUCE]] ], [ [[NEXT:%.+]], %[[BODY]] ]
173 // CHECK: call void [[CONSTR]](ptr {{[^,]*}} [[CUR]])
174 // CHECK: [[NEXT]] = getelementptr inbounds %struct.S, ptr [[CUR]], i64 1
175 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[NEXT]], [[TEMP_ARR_END]]
176 // CHECK: br i1 [[IS_DONE]], label %[[EXIT:[^,]+]], label %[[BODY]]
177 // CHECK: [[EXIT]]:
179 // TEMP = S;
180 // CHECK: [[TEMP_ARR_BEG:%.+]] = getelementptr inbounds [2 x %struct.S], ptr [[TEMP_ARR]], i32 0, i32 0
181 // CHECK: [[TEMP_ARR_END:%.+]] = getelementptr inbounds %struct.S, ptr [[TEMP_ARR_BEG]], i64 2
182 // CHECK: [[IS_EMPTY:%.+]] = icmp eq ptr [[TEMP_ARR_BEG]], [[TEMP_ARR_END]]
183 // CHECK: br i1 [[IS_EMPTY]], label %[[EXIT:[^,]+]], label %[[BODY:[^,]+]]
184 // CHECK: [[BODY]]:
185 // CHECK: [[CUR_SRC:%.+]] = phi ptr [ [[S_ADDR]], %{{.+}} ], [ [[SRC_NEXT:%.+]], %[[BODY]] ]
186 // CHECK: [[CUR_DEST:%.+]] = phi ptr [ [[TEMP_ARR_BEG]], %{{.+}} ], [ [[DEST_NEXT:%.+]], %[[BODY]] ]
187 // CHECK: call {{.*}}ptr [[S_COPY:@.+]](ptr {{[^,]*}} [[CUR_DEST]], ptr {{.*}}[[CUR_SRC]])
188 // CHECK: [[DEST_NEXT:%.+]] = getelementptr %struct.S, ptr [[CUR_DEST]], i32 1
189 // CHECK: [[SRC_NEXT:%.+]] = getelementptr %struct.S, ptr [[CUR_SRC]], i32 1
190 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[DEST_NEXT]], [[TEMP_ARR_END]]
191 // CHECK: br i1 [[IS_DONE]], label %[[EXIT]], label %[[BODY]]
192 // CHECK: [[EXIT]]:
194 // S = S_PRIV + S;
195 // CHECK: [[LHS_END:%.+]] = getelementptr {{.*}}%struct.S, ptr [[S_ADDR]], i{{.+}} 2
196 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[S_ADDR]], [[LHS_END]]
197 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_REDUCE_COPY:[^,]+]]
198 // CHECK: [[ARRAY_REDUCE_COPY]]:
199 // CHECK: [[SRC_CUR:%.+]] = phi ptr [ [[S_PRIV_ADDR]], %[[EXIT]] ], [ [[SRC_NEXT:%.+]], %[[ARRAY_REDUCE_COPY]] ]
200 // CHECK: [[DEST_CUR:%.+]] = phi ptr [ [[S_ADDR]], %[[EXIT]] ], [ [[DEST_NEXT:%.+]], %[[ARRAY_REDUCE_COPY]] ]
201 // CHECK: [[SUM:%.+]] = call {{.*}}ptr @{{.+}}(ptr {{[^,]*}} [[DEST_CUR]], ptr {{.*}}[[SRC_CUR]])
202 // CHECK: call {{.*}}ptr [[S_COPY]](ptr {{[^,]*}} [[DEST_CUR]], ptr {{.*}}[[SUM]])
203 // CHECK: [[DEST_NEXT]] = getelementptr {{.*}}%struct.S, ptr [[DEST_CUR]], i{{.+}} 1
204 // CHECK: [[SRC_NEXT]] = getelementptr {{.*}}%struct.S, ptr [[SRC_CUR]], i{{.+}} 1
205 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[DEST_NEXT]], [[LHS_END]]
206 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_REDUCE_COPY]]
207 // CHECK: [[DONE]]:
209 // S_PRIV = TEMP;
210 // CHECK: [[RHS_END:%.+]] = getelementptr inbounds %struct.S, ptr [[S_PRIV_ADDR]], i64 2
211 // CHECK: [[IS_EMPTY:%.+]] = icmp eq ptr [[S_PRIV_ADDR]], [[RHS_END]]
212 // CHECK: br i1 [[IS_EMPTY]], label %[[EXIT:[^,]+]], label %[[BODY:[^,]+]]
213 // CHECK: [[BODY]]:
214 // CHECK: [[CUR_SRC:%.+]] = phi ptr [ [[TEMP_ARR]], %[[DONE]] ], [ [[SRC_NEXT:%.+]], %[[BODY]] ]
215 // CHECK: [[CUR_DEST:%.+]] = phi ptr [ [[S_PRIV_ADDR]], %[[DONE]] ], [ [[DEST_NEXT:%.+]], %[[BODY]] ]
216 // CHECK: call {{.*}}ptr [[S_COPY]](ptr {{[^,]*}} [[CUR_DEST]], ptr {{.*}}[[CUR_SRC]])
217 // CHECK: [[DEST_NEXT]] = getelementptr %struct.S, ptr [[CUR_DEST]], i32 1
218 // CHECK: [[SRC_NEXT]] = getelementptr %struct.S, ptr [[CUR_SRC]], i32 1
219 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[DEST_NEXT]], [[RHS_END]]
220 // CHECK: br i1 [[IS_DONE]], label %[[DONE:[^,]+]], label %[[BODY]]
221 // CHECK: [[DONE]]:
223 // TEMP.~S()
224 // CHECK: [[TEMP_ARR_BEG:%.+]] = getelementptr inbounds [2 x %struct.S], ptr [[TEMP_ARR]], i32 0, i32 0
225 // CHECK: [[TEMP_ARR_END:%.+]] = getelementptr inbounds %struct.S, ptr [[TEMP_ARR_BEG]], i64 2
226 // CHECK: br label %[[BODY:[^,]+]]
227 // CHECK: [[BODY]]:
228 // CHECK: [[CUR:%.+]] = phi ptr [ [[TEMP_ARR_END]], %[[DONE]] ], [ [[PREV:%.+]], %[[BODY]] ]
229 // CHECK: [[PREV]] = getelementptr inbounds %struct.S, ptr [[CUR]], i64 -1
230 // CHECK: call void [[DESTR:@.+]](ptr {{[^,]*}} [[PREV]])
231 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[PREV]], [[TEMP_ARR_BEG]]
232 // CHECK: br i1 [[IS_DONE]], label %[[EXIT:[^,]+]], label %[[BODY]]
233 // CHECK: [[EXIT]]:
235 // goto SCAN_PHASE;
236 // CHECK: br label %[[SCAN_PHASE]]
237 #pragma omp scan exclusive(s)
239 // INPUT_PHASE:
240 // bar();
241 // goto REDUCE;
242 // CHECK: [[INPUT_PHASE]]:
243 // CHECK: call void @{{.*}}bar{{.*}}()
244 // CHECK: br label %[[REDUCE]]
245 bar();
247 // CHECK: [[CONTINUE]]:
249 // S_PRIV[2].~S();
250 // CHECK: [[S_BEGIN:%.+]] = getelementptr inbounds [2 x %struct.S], ptr [[S_PRIV_ADDR]], i{{.+}} 0, i{{.+}} 0
251 // CHECK: [[S_END:%.+]] = getelementptr {{.*}}%struct.S, ptr [[S_BEGIN]], i{{.+}} 2
252 // CHECK: br label %[[ARRAY_DESTR:[^,]+]]
253 // CHECK: [[ARRAY_DESTR]]:
254 // CHECK: [[S_CUR:%.+]] = phi ptr [ [[S_END]], %[[CONTINUE]] ], [ [[S_PREV:%.+]], %[[ARRAY_DESTR]] ]
255 // CHECK: [[S_PREV]] = getelementptr {{.*}}%struct.S, ptr [[S_CUR]], i{{.+}} -1
256 // CHECK: call void [[DESTR]](ptr {{[^,]*}} [[S_PREV]])
257 // CHECK: [[IS_DONE:%.+]] = icmp eq ptr [[S_PREV]], [[S_BEGIN]]
258 // CHECK: br i1 [[IS_DONE]], label %[[DONE:.+]], label %[[ARRAY_DESTR]]
259 // CHECK: [[DONE]]:
260 // CHECK: br label %[[INC_BLOCK:[^,]+]]
262 // ++OMP_CNT;
263 // CHECK: [[INC_BLOCK]]:
264 // CHECK: [[CNT:%.+]] = load i32, ptr [[OMP_CNT]],
265 // CHECK: [[INC:%.+]] = add nsw i32 [[CNT]], 1
266 // CHECK: store i32 [[INC]], ptr [[OMP_CNT]],
267 // CHECK: br label %[[OMP_HEADER]]
269 // CHECK: [[OMP_END]]:
272 // CHECK-NOT: !{!"llvm.loop.parallel_accesses"
274 #endif // HEADER