xref: /llvm-project/clang/test/OpenMP/scan_codegen.cpp (revision 0c6f2f629cc0017361310fa4c132090413a874db)
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
4 
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();
15 
16 // CHECK-LABEL: baz
baz()17 void baz() {
18   int a = 0;
19 
20   // CHECK: store i32 0, ptr [[A_ADDR:%.+]],
21   // CHECK: store i32 0, ptr [[OMP_CNT:%.+]],
22   // CHECK: br label %[[OMP_HEADER:.+]]
23 
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]]:
31 
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:%.+]],
37 
38     // A_PRIV = 0;
39     // CHECK: store i32 0, ptr [[A_PRIV_ADDR:%.+]],
40 
41     // goto DISPATCH;
42     // CHECK: br label %[[DISPATCH:[^,]+]]
43 
44     // INPUT_PHASE:
45     // foo();
46     // goto REDUCE;
47     // CHECK: [[INPUT_PHASE:.+]]:
48     // CHECK: call void @{{.*}}foo{{.*}}()
49     // CHECK: br label %[[REDUCE:[^,]+]]
50     foo();
51 
52     // DISPATCH:
53     // goto INPUT_PHASE;
54     // CHECK: [[DISPATCH]]:
55     // CHECK: br label %[[INPUT_PHASE]]
56 
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)
70 
71     // SCAN_PHASE:
72     // bar();
73     // goto CONTINUE;
74     // CHECK: [[SCAN_PHASE]]:
75     // CHECK: call void @{{.*}}bar{{.*}}()
76     // CHECK: br label %[[CONTINUE:[^,]+]]
77     bar();
78 
79     // CHECK: [[CONTINUE]]:
80     // CHECK: br label %[[INC_BLOCK:[^,]+]]
81 
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]]
88   }
89   // CHECK: [[OMP_END]]:
90 }
91 
92 struct S {
93   int a;
SS94   S() {}
~SS95   ~S() {}
96   S& operator+(const S&);
97   S& operator=(const S&);
98 };
99 
100 // CHECK-LABEL: xyz
xyz()101 void xyz() {
102   S s[2];
103 
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:.+]]
116 
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]]:
124 
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:%.+]],
130 
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]]:
143 
144     // goto DISPATCH;
145     // CHECK: br label %[[DISPATCH:[^,]+]]
146 
147     // SCAN_PHASE:
148     // foo();
149     // goto CONTINUE;
150     // CHECK: [[SCAN_PHASE:.+]]:
151     // CHECK: call void @{{.*}}foo{{.*}}()
152     // CHECK: br label %[[CONTINUE:[^,]+]]
153     foo();
154 
155     // DISPATCH:
156     // goto INPUT_PHASE;
157     // CHECK: [[DISPATCH]]:
158     // CHECK: br label %[[INPUT_PHASE:[^,]+]]
159 
160     // REDUCE:
161     // TEMP = S;
162     // S = S_PRIV + S;
163     // S_PRIV = TEMP;
164     // goto SCAN_PHASE;
165     // CHECK: [[REDUCE:.+]]:
166 
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]]:
178 
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]]:
193 
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]]:
208 
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]]:
222 
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]]:
234 
235     // goto SCAN_PHASE;
236     // CHECK: br label %[[SCAN_PHASE]]
237 #pragma omp scan exclusive(s)
238 
239     // INPUT_PHASE:
240     // bar();
241     // goto REDUCE;
242     // CHECK: [[INPUT_PHASE]]:
243     // CHECK: call void @{{.*}}bar{{.*}}()
244     // CHECK: br label %[[REDUCE]]
245     bar();
246 
247     // CHECK: [[CONTINUE]]:
248 
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:[^,]+]]
261 
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]]
268   }
269   // CHECK: [[OMP_END]]:
270 }
271 
272 // CHECK-NOT: !{!"llvm.loop.parallel_accesses"
273 
274 #endif // HEADER
275