Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGenCXX / attr-likelihood-if-branch-weights.cpp
bloba77593f5df738a80a4eeecfa67e483182a950718
1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2 // RUN: %clang_cc1 -O1 -disable-llvm-passes -emit-llvm %s -o - -triple=x86_64-- | FileCheck %s
4 extern volatile bool b;
5 extern volatile int i;
6 extern bool A();
7 extern bool B();
9 // CHECK-LABEL: @_Z1fv(
10 // CHECK-NEXT: entry:
11 // CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
12 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2:![0-9]+]], !range [[RNG6:![0-9]+]]
13 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
14 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 true)
15 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
16 // CHECK: if.then:
17 // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Av()
18 // CHECK-NEXT: store i1 [[CALL]], ptr [[RETVAL]], align 1
19 // CHECK-NEXT: br label [[RETURN:%.*]]
20 // CHECK: if.end:
21 // CHECK-NEXT: [[CALL1:%.*]] = call noundef zeroext i1 @_Z1Bv()
22 // CHECK-NEXT: store i1 [[CALL1]], ptr [[RETVAL]], align 1
23 // CHECK-NEXT: br label [[RETURN]]
24 // CHECK: return:
25 // CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr [[RETVAL]], align 1
26 // CHECK-NEXT: ret i1 [[TMP1]]
28 bool f() {
29 if (b)
30 [[likely]] {
31 return A();
33 return B();
36 // CHECK-LABEL: @_Z1gv(
37 // CHECK-NEXT: entry:
38 // CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
39 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
40 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
41 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
42 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
43 // CHECK: if.then:
44 // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Av()
45 // CHECK-NEXT: store i1 [[CALL]], ptr [[RETVAL]], align 1
46 // CHECK-NEXT: br label [[RETURN:%.*]]
47 // CHECK: if.end:
48 // CHECK-NEXT: [[CALL1:%.*]] = call noundef zeroext i1 @_Z1Bv()
49 // CHECK-NEXT: store i1 [[CALL1]], ptr [[RETVAL]], align 1
50 // CHECK-NEXT: br label [[RETURN]]
51 // CHECK: return:
52 // CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr [[RETVAL]], align 1
53 // CHECK-NEXT: ret i1 [[TMP1]]
55 bool g() {
56 if (b)
57 [[unlikely]] {
58 return A();
61 return B();
64 // CHECK-LABEL: @_Z1hv(
65 // CHECK-NEXT: entry:
66 // CHECK-NEXT: [[RETVAL:%.*]] = alloca i1, align 1
67 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
68 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
69 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
70 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
71 // CHECK: if.then:
72 // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Av()
73 // CHECK-NEXT: store i1 [[CALL]], ptr [[RETVAL]], align 1
74 // CHECK-NEXT: br label [[RETURN:%.*]]
75 // CHECK: if.end:
76 // CHECK-NEXT: [[CALL1:%.*]] = call noundef zeroext i1 @_Z1Bv()
77 // CHECK-NEXT: store i1 [[CALL1]], ptr [[RETVAL]], align 1
78 // CHECK-NEXT: br label [[RETURN]]
79 // CHECK: return:
80 // CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr [[RETVAL]], align 1
81 // CHECK-NEXT: ret i1 [[TMP1]]
83 bool h() {
84 if (b)
85 [[unlikely]] return A();
87 return B();
90 // CHECK-LABEL: @_Z8NullStmtv(
91 // CHECK-NEXT: entry:
92 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
93 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
94 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
95 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
96 // CHECK: if.then:
97 // CHECK-NEXT: br label [[IF_END:%.*]]
98 // CHECK: if.else:
99 // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]]
100 // CHECK-NEXT: br label [[IF_END]]
101 // CHECK: if.end:
102 // CHECK-NEXT: ret void
104 void NullStmt() {
105 if (b)
106 [[unlikely]];
107 else {
108 // Make sure the branches aren't optimized away.
109 b = true;
113 // CHECK-LABEL: @_Z6IfStmtv(
114 // CHECK-NEXT: entry:
115 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
116 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
117 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
118 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END2:%.*]]
119 // CHECK: if.then:
120 // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Bv()
121 // CHECK-NEXT: br i1 [[CALL]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
122 // CHECK: if.then1:
123 // CHECK-NEXT: br label [[IF_END]]
124 // CHECK: if.end:
125 // CHECK-NEXT: br label [[IF_END2]]
126 // CHECK: if.end2:
127 // CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
128 // CHECK-NEXT: [[TOBOOL3:%.*]] = trunc i8 [[TMP1]] to i1
129 // CHECK-NEXT: br i1 [[TOBOOL3]], label [[IF_THEN4:%.*]], label [[IF_END8:%.*]]
130 // CHECK: if.then4:
131 // CHECK-NEXT: [[CALL5:%.*]] = call noundef zeroext i1 @_Z1Bv()
132 // CHECK-NEXT: [[CALL5_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[CALL5]], i1 false)
133 // CHECK-NEXT: br i1 [[CALL5_EXPVAL]], label [[IF_THEN6:%.*]], label [[IF_END7:%.*]]
134 // CHECK: if.then6:
135 // CHECK-NEXT: store volatile i8 0, ptr @b, align 1, !tbaa [[TBAA2]]
136 // CHECK-NEXT: br label [[IF_END7]]
137 // CHECK: if.end7:
138 // CHECK-NEXT: br label [[IF_END8]]
139 // CHECK: if.end8:
140 // CHECK-NEXT: ret void
142 void IfStmt() {
143 if (b)
144 [[unlikely]] if (B()) {}
146 if (b) {
147 if (B())
148 [[unlikely]] { b = false; }
152 // CHECK-LABEL: @_Z9WhileStmtv(
153 // CHECK-NEXT: entry:
154 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
155 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
156 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
157 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
158 // CHECK: if.then:
159 // CHECK-NEXT: br label [[WHILE_COND:%.*]]
160 // CHECK: while.cond:
161 // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Bv()
162 // CHECK-NEXT: br i1 [[CALL]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]
163 // CHECK: while.body:
164 // CHECK-NEXT: br label [[WHILE_COND]], !llvm.loop [[LOOP7:![0-9]+]]
165 // CHECK: while.end:
166 // CHECK-NEXT: br label [[IF_END]]
167 // CHECK: if.end:
168 // CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
169 // CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1
170 // CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]]
171 // CHECK: if.then2:
172 // CHECK-NEXT: br label [[WHILE_COND3:%.*]]
173 // CHECK: while.cond3:
174 // CHECK-NEXT: [[CALL4:%.*]] = call noundef zeroext i1 @_Z1Bv()
175 // CHECK-NEXT: [[CALL4_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[CALL4]], i1 false)
176 // CHECK-NEXT: br i1 [[CALL4_EXPVAL]], label [[WHILE_BODY5:%.*]], label [[WHILE_END6:%.*]]
177 // CHECK: while.body5:
178 // CHECK-NEXT: store volatile i8 0, ptr @b, align 1, !tbaa [[TBAA2]]
179 // CHECK-NEXT: br label [[WHILE_COND3]], !llvm.loop [[LOOP10:![0-9]+]]
180 // CHECK: while.end6:
181 // CHECK-NEXT: br label [[IF_END7]]
182 // CHECK: if.end7:
183 // CHECK-NEXT: ret void
185 void WhileStmt() {
186 if (b)
187 [[unlikely]] while (B()) {}
189 if (b)
190 while (B())
191 [[unlikely]] { b = false; }
194 // CHECK-LABEL: @_Z6DoStmtv(
195 // CHECK-NEXT: entry:
196 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
197 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
198 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
199 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
200 // CHECK: if.then:
201 // CHECK-NEXT: br label [[DO_BODY:%.*]]
202 // CHECK: do.body:
203 // CHECK-NEXT: br label [[DO_COND:%.*]]
204 // CHECK: do.cond:
205 // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Bv()
206 // CHECK-NEXT: br i1 [[CALL]], label [[DO_BODY]], label [[DO_END:%.*]], !llvm.loop [[LOOP11:![0-9]+]]
207 // CHECK: do.end:
208 // CHECK-NEXT: br label [[IF_END]]
209 // CHECK: if.end:
210 // CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
211 // CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1
212 // CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]]
213 // CHECK: if.then2:
214 // CHECK-NEXT: br label [[DO_BODY3:%.*]]
215 // CHECK: do.body3:
216 // CHECK-NEXT: br label [[DO_COND4:%.*]]
217 // CHECK: do.cond4:
218 // CHECK-NEXT: [[CALL5:%.*]] = call noundef zeroext i1 @_Z1Bv()
219 // CHECK-NEXT: br i1 [[CALL5]], label [[DO_BODY3]], label [[DO_END6:%.*]], !llvm.loop [[LOOP12:![0-9]+]]
220 // CHECK: do.end6:
221 // CHECK-NEXT: br label [[IF_END7]]
222 // CHECK: if.end7:
223 // CHECK-NEXT: ret void
225 void DoStmt() {
226 if (b)
227 [[unlikely]] do {}
228 while (B())
231 if (b)
233 [[unlikely]] {}
234 while (B());
237 // CHECK-LABEL: @_Z7ForStmtv(
238 // CHECK-NEXT: entry:
239 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
240 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
241 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
242 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
243 // CHECK: if.then:
244 // CHECK-NEXT: br label [[FOR_COND:%.*]]
245 // CHECK: for.cond:
246 // CHECK-NEXT: [[CALL:%.*]] = call noundef zeroext i1 @_Z1Bv()
247 // CHECK-NEXT: br i1 [[CALL]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
248 // CHECK: for.body:
249 // CHECK-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP13:![0-9]+]]
250 // CHECK: for.end:
251 // CHECK-NEXT: br label [[IF_END]]
252 // CHECK: if.end:
253 // CHECK-NEXT: [[TMP1:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
254 // CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP1]] to i1
255 // CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END7:%.*]]
256 // CHECK: if.then2:
257 // CHECK-NEXT: br label [[FOR_COND3:%.*]]
258 // CHECK: for.cond3:
259 // CHECK-NEXT: [[CALL4:%.*]] = call noundef zeroext i1 @_Z1Bv()
260 // CHECK-NEXT: [[CALL4_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[CALL4]], i1 false)
261 // CHECK-NEXT: br i1 [[CALL4_EXPVAL]], label [[FOR_BODY5:%.*]], label [[FOR_END6:%.*]]
262 // CHECK: for.body5:
263 // CHECK-NEXT: br label [[FOR_COND3]], !llvm.loop [[LOOP14:![0-9]+]]
264 // CHECK: for.end6:
265 // CHECK-NEXT: br label [[IF_END7]]
266 // CHECK: if.end7:
267 // CHECK-NEXT: ret void
269 void ForStmt() {
270 if (b)
271 [[unlikely]] for (; B();) {}
273 if (b)
274 for (; B();)
275 [[unlikely]] {}
278 // CHECK-LABEL: @_Z8GotoStmtv(
279 // CHECK-NEXT: entry:
280 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
281 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
282 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
283 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
284 // CHECK: if.then:
285 // CHECK-NEXT: br label [[END:%.*]]
286 // CHECK: if.else:
287 // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]]
288 // CHECK-NEXT: br label [[IF_END:%.*]]
289 // CHECK: if.end:
290 // CHECK-NEXT: br label [[END]]
291 // CHECK: end:
292 // CHECK-NEXT: ret void
294 void GotoStmt() {
295 if (b)
296 [[unlikely]] goto end;
297 else {
298 // Make sure the branches aren't optimized away.
299 b = true;
301 end:;
304 // CHECK-LABEL: @_Z10ReturnStmtv(
305 // CHECK-NEXT: entry:
306 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
307 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
308 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
309 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
310 // CHECK: if.then:
311 // CHECK-NEXT: br label [[IF_END:%.*]]
312 // CHECK: if.else:
313 // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]]
314 // CHECK-NEXT: br label [[IF_END]]
315 // CHECK: if.end:
316 // CHECK-NEXT: ret void
318 void ReturnStmt() {
319 if (b)
320 [[unlikely]] return;
321 else {
322 // Make sure the branches aren't optimized away.
323 b = true;
327 // CHECK-LABEL: @_Z10SwitchStmtv(
328 // CHECK-NEXT: entry:
329 // CHECK-NEXT: [[TMP0:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
330 // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP0]] to i1
331 // CHECK-NEXT: [[TOBOOL_EXPVAL:%.*]] = call i1 @llvm.expect.i1(i1 [[TOBOOL]], i1 false)
332 // CHECK-NEXT: br i1 [[TOBOOL_EXPVAL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
333 // CHECK: if.then:
334 // CHECK-NEXT: [[TMP1:%.*]] = load volatile i32, ptr @i, align 4, !tbaa [[TBAA15:![0-9]+]]
335 // CHECK-NEXT: switch i32 [[TMP1]], label [[SW_EPILOG:%.*]] [
336 // CHECK-NEXT: ]
337 // CHECK: sw.epilog:
338 // CHECK-NEXT: br label [[IF_END:%.*]]
339 // CHECK: if.else:
340 // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]]
341 // CHECK-NEXT: br label [[IF_END]]
342 // CHECK: if.end:
343 // CHECK-NEXT: [[TMP2:%.*]] = load volatile i8, ptr @b, align 1, !tbaa [[TBAA2]], !range [[RNG6]]
344 // CHECK-NEXT: [[TOBOOL1:%.*]] = trunc i8 [[TMP2]] to i1
345 // CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_ELSE4:%.*]]
346 // CHECK: if.then2:
347 // CHECK-NEXT: [[TMP3:%.*]] = load volatile i32, ptr @i, align 4, !tbaa [[TBAA15]]
348 // CHECK-NEXT: switch i32 [[TMP3]], label [[SW_EPILOG3:%.*]] [
349 // CHECK-NEXT: ]
350 // CHECK: sw.epilog3:
351 // CHECK-NEXT: br label [[IF_END5:%.*]]
352 // CHECK: if.else4:
353 // CHECK-NEXT: store volatile i8 1, ptr @b, align 1, !tbaa [[TBAA2]]
354 // CHECK-NEXT: br label [[IF_END5]]
355 // CHECK: if.end5:
356 // CHECK-NEXT: ret void
358 void SwitchStmt() {
359 if (b)
360 [[unlikely]] switch (i) {}
361 else {
362 // Make sure the branches aren't optimized away.
363 b = true;
365 if (b)
366 switch (i)
367 [[unlikely]] {}
368 else {
369 // Make sure the branches aren't optimized away.
370 b = true;