1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -bonus-inst-threshold=10 | FileCheck %s
4 declare void @sideeffect0()
5 declare void @sideeffect1()
6 declare void @sideeffect2()
9 declare i32 @speculate_call(ptr) #0
11 ; Basic cases, blocks have nothing other than the comparison itself.
13 define void @one_pred(i8 %v0, i8 %v1) {
14 ; CHECK-LABEL: @one_pred(
16 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
17 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
18 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
19 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
21 ; CHECK-NEXT: ret void
23 ; CHECK-NEXT: call void @sideeffect0()
24 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
26 ; CHECK-NEXT: call void @sideeffect1()
27 ; CHECK-NEXT: br label [[COMMON_RET]]
30 %c0 = icmp eq i8 %v0, 0
31 br i1 %c0, label %dispatch, label %final_right
33 %c1 = icmp eq i8 %v1, 0
34 br i1 %c1, label %final_left, label %final_right
36 call void @sideeffect0()
39 call void @sideeffect1()
43 define void @two_preds(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
44 ; CHECK-LABEL: @two_preds(
46 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
47 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
49 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
50 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3:%.*]], 0
51 ; CHECK-NEXT: [[OR_COND1:%.*]] = select i1 [[C1]], i1 true, i1 [[C3_OLD]]
52 ; CHECK-NEXT: br i1 [[OR_COND1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
54 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
55 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3]], 0
56 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
57 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
59 ; CHECK-NEXT: ret void
61 ; CHECK-NEXT: call void @sideeffect0()
62 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
64 ; CHECK-NEXT: call void @sideeffect1()
65 ; CHECK-NEXT: br label [[COMMON_RET]]
68 %c0 = icmp eq i8 %v0, 0
69 br i1 %c0, label %pred0, label %pred1
71 %c1 = icmp eq i8 %v1, 0
72 br i1 %c1, label %final_left, label %dispatch
74 %c2 = icmp eq i8 %v2, 0
75 br i1 %c2, label %dispatch, label %final_right
77 %c3 = icmp eq i8 %v3, 0
78 br i1 %c3, label %final_left, label %final_right
80 call void @sideeffect0()
83 call void @sideeffect1()
87 ; More complex case, there's an extra op that is safe to execute unconditionally.
89 define void @one_pred_with_extra_op(i8 %v0, i8 %v1) {
90 ; CHECK-LABEL: @one_pred_with_extra_op(
92 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
93 ; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
94 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
95 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
96 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
98 ; CHECK-NEXT: ret void
100 ; CHECK-NEXT: call void @sideeffect0()
101 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
102 ; CHECK: final_right:
103 ; CHECK-NEXT: call void @sideeffect1()
104 ; CHECK-NEXT: br label [[COMMON_RET]]
107 %c0 = icmp eq i8 %v0, 0
108 br i1 %c0, label %dispatch, label %final_right
110 %v1_adj = add i8 %v0, %v1
111 %c1 = icmp eq i8 %v1_adj, 0
112 br i1 %c1, label %final_left, label %final_right
114 call void @sideeffect0()
117 call void @sideeffect1()
121 ; When we fold the dispatch block into pred, the call is moved to pred
122 ; and the attribute nonnull propagates poison paramater. However, since the
123 ; function is speculatable, it can never cause UB. So, we need not technically drop it.
124 define void @one_pred_with_spec_call(i8 %v0, i8 %v1, ptr %p) {
125 ; CHECK-LABEL: @one_pred_with_spec_call(
127 ; CHECK-NEXT: [[C0:%.*]] = icmp ne ptr [[P:%.*]], null
128 ; CHECK-NEXT: [[X:%.*]] = call i32 @speculate_call(ptr nonnull [[P]])
129 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
130 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
131 ; CHECK-NEXT: br i1 [[OR_COND]], label [[COMMON_RET:%.*]], label [[FINAL_RIGHT:%.*]]
133 ; CHECK-NEXT: ret void
134 ; CHECK: final_right:
135 ; CHECK-NEXT: call void @sideeffect0()
136 ; CHECK-NEXT: br label [[COMMON_RET]]
139 %c0 = icmp ne ptr %p, null
140 br i1 %c0, label %dispatch, label %final_right
143 %x = call i32 @speculate_call(ptr nonnull %p)
144 %c1 = icmp eq i8 %v1, 0
145 br i1 %c1, label %final_left, label %final_right
151 call void @sideeffect0()
155 ; Drop dereferenceable on the parameter
156 define void @one_pred_with_spec_call_deref(i8 %v0, i8 %v1, ptr %p) {
157 ; CHECK-LABEL: @one_pred_with_spec_call_deref(
159 ; CHECK-NEXT: [[C0:%.*]] = icmp ne ptr [[P:%.*]], null
160 ; CHECK-NEXT: [[X:%.*]] = call i32 @speculate_call(ptr [[P]])
161 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
162 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
163 ; CHECK-NEXT: br i1 [[OR_COND]], label [[COMMON_RET:%.*]], label [[FINAL_RIGHT:%.*]]
165 ; CHECK-NEXT: ret void
166 ; CHECK: final_right:
167 ; CHECK-NEXT: call void @sideeffect0()
168 ; CHECK-NEXT: br label [[COMMON_RET]]
171 %c0 = icmp ne ptr %p, null
172 br i1 %c0, label %dispatch, label %final_right
175 %x = call i32 @speculate_call(ptr dereferenceable(12) %p)
176 %c1 = icmp eq i8 %v1, 0
177 br i1 %c1, label %final_left, label %final_right
183 call void @sideeffect0()
187 define void @two_preds_with_extra_op(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
188 ; CHECK-LABEL: @two_preds_with_extra_op(
190 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
191 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
193 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
194 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2:%.*]]
195 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0
196 ; CHECK-NEXT: [[OR_COND1:%.*]] = select i1 [[C1]], i1 true, i1 [[C3_OLD]]
197 ; CHECK-NEXT: br i1 [[OR_COND1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
199 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2]], 0
200 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
201 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
202 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
203 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
205 ; CHECK-NEXT: ret void
207 ; CHECK-NEXT: call void @sideeffect0()
208 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
209 ; CHECK: final_right:
210 ; CHECK-NEXT: call void @sideeffect1()
211 ; CHECK-NEXT: br label [[COMMON_RET]]
214 %c0 = icmp eq i8 %v0, 0
215 br i1 %c0, label %pred0, label %pred1
217 %c1 = icmp eq i8 %v1, 0
218 br i1 %c1, label %final_left, label %dispatch
220 %c2 = icmp eq i8 %v2, 0
221 br i1 %c2, label %dispatch, label %final_right
223 %v3_adj = add i8 %v1, %v2
224 %c3 = icmp eq i8 %v3_adj, 0
225 br i1 %c3, label %final_left, label %final_right
227 call void @sideeffect0()
230 call void @sideeffect1()
234 ; More complex case, there's an extra op that is safe to execute unconditionally, and it has multiple uses.
236 define void @one_pred_with_extra_op_multiuse(i8 %v0, i8 %v1) {
237 ; CHECK-LABEL: @one_pred_with_extra_op_multiuse(
239 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
240 ; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
241 ; CHECK-NEXT: [[V1_ADJ_ADJ:%.*]] = add i8 [[V1_ADJ]], [[V1_ADJ]]
242 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1_ADJ_ADJ]], 0
243 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
244 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
246 ; CHECK-NEXT: ret void
248 ; CHECK-NEXT: call void @sideeffect0()
249 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
250 ; CHECK: final_right:
251 ; CHECK-NEXT: call void @sideeffect1()
252 ; CHECK-NEXT: br label [[COMMON_RET]]
255 %c0 = icmp eq i8 %v0, 0
256 br i1 %c0, label %dispatch, label %final_right
258 %v1_adj = add i8 %v0, %v1
259 %v1_adj_adj = add i8 %v1_adj, %v1_adj
260 %c1 = icmp eq i8 %v1_adj_adj, 0
261 br i1 %c1, label %final_left, label %final_right
263 call void @sideeffect0()
266 call void @sideeffect1()
270 define void @two_preds_with_extra_op_multiuse(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
271 ; CHECK-LABEL: @two_preds_with_extra_op_multiuse(
273 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
274 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
276 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
277 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2:%.*]]
278 ; CHECK-NEXT: [[V3_ADJ_ADJ_OLD:%.*]] = add i8 [[V3_ADJ_OLD]], [[V3_ADJ_OLD]]
279 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_ADJ_OLD]], 0
280 ; CHECK-NEXT: [[OR_COND1:%.*]] = select i1 [[C1]], i1 true, i1 [[C3_OLD]]
281 ; CHECK-NEXT: br i1 [[OR_COND1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
283 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2]], 0
284 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
285 ; CHECK-NEXT: [[V3_ADJ_ADJ:%.*]] = add i8 [[V3_ADJ]], [[V3_ADJ]]
286 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ_ADJ]], 0
287 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
288 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
290 ; CHECK-NEXT: ret void
292 ; CHECK-NEXT: call void @sideeffect0()
293 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
294 ; CHECK: final_right:
295 ; CHECK-NEXT: call void @sideeffect1()
296 ; CHECK-NEXT: br label [[COMMON_RET]]
299 %c0 = icmp eq i8 %v0, 0
300 br i1 %c0, label %pred0, label %pred1
302 %c1 = icmp eq i8 %v1, 0
303 br i1 %c1, label %final_left, label %dispatch
305 %c2 = icmp eq i8 %v2, 0
306 br i1 %c2, label %dispatch, label %final_right
308 %v3_adj = add i8 %v1, %v2
309 %v3_adj_adj = add i8 %v3_adj, %v3_adj
310 %c3 = icmp eq i8 %v3_adj_adj, 0
311 br i1 %c3, label %final_left, label %final_right
313 call void @sideeffect0()
316 call void @sideeffect1()
320 ; More complex case, there's an op that is safe to execute unconditionally,
321 ; and said op is live-out.
323 define void @one_pred_with_extra_op_liveout(i8 %v0, i8 %v1) {
324 ; CHECK-LABEL: @one_pred_with_extra_op_liveout(
326 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
327 ; CHECK-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
329 ; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
330 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
331 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
333 ; CHECK-NEXT: ret void
335 ; CHECK-NEXT: call void @sideeffect0()
336 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
337 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
338 ; CHECK: final_right:
339 ; CHECK-NEXT: call void @sideeffect1()
340 ; CHECK-NEXT: br label [[COMMON_RET]]
343 %c0 = icmp eq i8 %v0, 0
344 br i1 %c0, label %dispatch, label %final_right
346 %v1_adj = add i8 %v0, %v1
347 %c1 = icmp eq i8 %v1_adj, 0
348 br i1 %c1, label %final_left, label %final_right
350 call void @sideeffect0()
351 call void @use8(i8 %v1_adj)
354 call void @sideeffect1()
357 define void @one_pred_with_extra_op_liveout_multiuse(i8 %v0, i8 %v1) {
358 ; CHECK-LABEL: @one_pred_with_extra_op_liveout_multiuse(
360 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
361 ; CHECK-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
363 ; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
364 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
365 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
367 ; CHECK-NEXT: ret void
369 ; CHECK-NEXT: call void @sideeffect0()
370 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
371 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
372 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
373 ; CHECK: final_right:
374 ; CHECK-NEXT: call void @sideeffect1()
375 ; CHECK-NEXT: br label [[COMMON_RET]]
378 %c0 = icmp eq i8 %v0, 0
379 br i1 %c0, label %dispatch, label %final_right
381 %v1_adj = add i8 %v0, %v1
382 %c1 = icmp eq i8 %v1_adj, 0
383 br i1 %c1, label %final_left, label %final_right
385 call void @sideeffect0()
386 call void @use8(i8 %v1_adj)
387 call void @use8(i8 %v1_adj)
390 call void @sideeffect1()
394 define void @one_pred_with_extra_op_liveout_distant_phi(i8 %v0, i8 %v1) {
395 ; CHECK-LABEL: @one_pred_with_extra_op_liveout_distant_phi(
397 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
398 ; CHECK-NEXT: br i1 [[C0]], label [[PRED:%.*]], label [[LEFT_END:%.*]]
400 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
401 ; CHECK-NEXT: br i1 [[C1]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
403 ; CHECK-NEXT: [[V2_ADJ:%.*]] = add i8 [[V0]], [[V1]]
404 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2_ADJ]], 0
405 ; CHECK-NEXT: br i1 [[C2]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
407 ; CHECK-NEXT: call void @sideeffect0()
408 ; CHECK-NEXT: call void @use8(i8 [[V2_ADJ]])
409 ; CHECK-NEXT: br label [[LEFT_END]]
411 ; CHECK-NEXT: ret void
413 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V2_ADJ]], [[FINAL_LEFT]] ], [ 0, [[ENTRY:%.*]] ]
414 ; CHECK-NEXT: call void @sideeffect1()
415 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
416 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
417 ; CHECK: final_right:
418 ; CHECK-NEXT: call void @sideeffect2()
419 ; CHECK-NEXT: br label [[COMMON_RET]]
422 %c0 = icmp eq i8 %v0, 0
423 br i1 %c0, label %pred, label %left_end
425 %c1 = icmp eq i8 %v1, 0
426 br i1 %c1, label %dispatch, label %final_right
428 %v2_adj = add i8 %v0, %v1
429 %c2 = icmp eq i8 %v2_adj, 0
430 br i1 %c2, label %final_left, label %final_right
432 call void @sideeffect0()
433 call void @use8(i8 %v2_adj)
436 %merge_left = phi i8 [ %v2_adj, %final_left ], [ 0, %entry ]
437 call void @sideeffect1()
438 call void @use8(i8 %merge_left)
441 call void @sideeffect2()
445 define void @two_preds_with_extra_op_liveout(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
446 ; CHECK-LABEL: @two_preds_with_extra_op_liveout(
448 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
449 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
451 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
452 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
454 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
455 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
456 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
457 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
458 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
460 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
461 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0
462 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
464 ; CHECK-NEXT: ret void
466 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
467 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
468 ; CHECK-NEXT: call void @sideeffect0()
469 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
470 ; CHECK: final_right:
471 ; CHECK-NEXT: call void @sideeffect1()
472 ; CHECK-NEXT: br label [[COMMON_RET]]
475 %c0 = icmp eq i8 %v0, 0
476 br i1 %c0, label %pred0, label %pred1
478 %c1 = icmp eq i8 %v1, 0
479 br i1 %c1, label %final_left, label %dispatch
481 %c2 = icmp eq i8 %v2, 0
482 br i1 %c2, label %dispatch, label %final_right
484 %v3_adj = add i8 %v1, %v2
485 %c3 = icmp eq i8 %v3_adj, 0
486 br i1 %c3, label %final_left, label %final_right
488 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
489 call void @use8(i8 %merge_left)
490 call void @sideeffect0()
493 call void @sideeffect1()
497 define void @two_preds_with_extra_op_liveout_multiuse(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
498 ; CHECK-LABEL: @two_preds_with_extra_op_liveout_multiuse(
500 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
501 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
503 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
504 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
506 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
507 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
508 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
509 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
510 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
512 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
513 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0
514 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
516 ; CHECK-NEXT: ret void
518 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
519 ; CHECK-NEXT: [[MERGE_LEFT_2:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 42, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
520 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
521 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT_2]])
522 ; CHECK-NEXT: call void @sideeffect0()
523 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
524 ; CHECK: final_right:
525 ; CHECK-NEXT: call void @sideeffect1()
526 ; CHECK-NEXT: br label [[COMMON_RET]]
529 %c0 = icmp eq i8 %v0, 0
530 br i1 %c0, label %pred0, label %pred1
532 %c1 = icmp eq i8 %v1, 0
533 br i1 %c1, label %final_left, label %dispatch
535 %c2 = icmp eq i8 %v2, 0
536 br i1 %c2, label %dispatch, label %final_right
538 %v3_adj = add i8 %v1, %v2
539 %c3 = icmp eq i8 %v3_adj, 0
540 br i1 %c3, label %final_left, label %final_right
542 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
543 %merge_left_2 = phi i8 [ %v3_adj, %dispatch ], [ 42, %pred0 ]
544 call void @use8(i8 %merge_left)
545 call void @use8(i8 %merge_left_2)
546 call void @sideeffect0()
549 call void @sideeffect1()
553 ; More complex case, there's an op that is safe to execute unconditionally,
554 ; and said op is live-out, and it is only used externally.
556 define void @one_pred_with_extra_op_eexternally_used_only(i8 %v0, i8 %v1) {
557 ; CHECK-LABEL: @one_pred_with_extra_op_eexternally_used_only(
559 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
560 ; CHECK-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
562 ; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
563 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1]], 0
564 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
566 ; CHECK-NEXT: ret void
568 ; CHECK-NEXT: call void @sideeffect0()
569 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
570 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
571 ; CHECK: final_right:
572 ; CHECK-NEXT: call void @sideeffect1()
573 ; CHECK-NEXT: br label [[COMMON_RET]]
576 %c0 = icmp eq i8 %v0, 0
577 br i1 %c0, label %dispatch, label %final_right
579 %v1_adj = add i8 %v0, %v1
580 %c1 = icmp eq i8 %v1, 0
581 br i1 %c1, label %final_left, label %final_right
583 call void @sideeffect0()
584 call void @use8(i8 %v1_adj)
587 call void @sideeffect1()
590 define void @one_pred_with_extra_op_externally_used_only_multiuse(i8 %v0, i8 %v1) {
591 ; CHECK-LABEL: @one_pred_with_extra_op_externally_used_only_multiuse(
593 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
594 ; CHECK-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
596 ; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
597 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1]], 0
598 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
600 ; CHECK-NEXT: ret void
602 ; CHECK-NEXT: call void @sideeffect0()
603 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
604 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
605 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
606 ; CHECK: final_right:
607 ; CHECK-NEXT: call void @sideeffect1()
608 ; CHECK-NEXT: br label [[COMMON_RET]]
611 %c0 = icmp eq i8 %v0, 0
612 br i1 %c0, label %dispatch, label %final_right
614 %v1_adj = add i8 %v0, %v1
615 %c1 = icmp eq i8 %v1, 0
616 br i1 %c1, label %final_left, label %final_right
618 call void @sideeffect0()
619 call void @use8(i8 %v1_adj)
620 call void @use8(i8 %v1_adj)
623 call void @sideeffect1()
627 define void @two_preds_with_extra_op_externally_used_only(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
628 ; CHECK-LABEL: @two_preds_with_extra_op_externally_used_only(
630 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
631 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
633 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
634 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
636 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
637 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
638 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
639 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
640 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
642 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
643 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
644 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
646 ; CHECK-NEXT: ret void
648 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
649 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
650 ; CHECK-NEXT: call void @sideeffect0()
651 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
652 ; CHECK: final_right:
653 ; CHECK-NEXT: call void @sideeffect1()
654 ; CHECK-NEXT: br label [[COMMON_RET]]
657 %c0 = icmp eq i8 %v0, 0
658 br i1 %c0, label %pred0, label %pred1
660 %c1 = icmp eq i8 %v1, 0
661 br i1 %c1, label %final_left, label %dispatch
663 %c2 = icmp eq i8 %v2, 0
664 br i1 %c2, label %dispatch, label %final_right
666 %v3_adj = add i8 %v1, %v2
667 %c3 = icmp eq i8 %v3, 0
668 br i1 %c3, label %final_left, label %final_right
670 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
671 call void @use8(i8 %merge_left)
672 call void @sideeffect0()
675 call void @sideeffect1()
679 define void @two_preds_with_extra_op_externally_used_only_multiuse(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
680 ; CHECK-LABEL: @two_preds_with_extra_op_externally_used_only_multiuse(
682 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
683 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
685 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
686 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
688 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
689 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
690 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
691 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
692 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
694 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
695 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
696 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
698 ; CHECK-NEXT: ret void
700 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
701 ; CHECK-NEXT: [[MERGE_LEFT_2:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 42, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
702 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
703 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT_2]])
704 ; CHECK-NEXT: call void @sideeffect0()
705 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
706 ; CHECK: final_right:
707 ; CHECK-NEXT: call void @sideeffect1()
708 ; CHECK-NEXT: br label [[COMMON_RET]]
711 %c0 = icmp eq i8 %v0, 0
712 br i1 %c0, label %pred0, label %pred1
714 %c1 = icmp eq i8 %v1, 0
715 br i1 %c1, label %final_left, label %dispatch
717 %c2 = icmp eq i8 %v2, 0
718 br i1 %c2, label %dispatch, label %final_right
720 %v3_adj = add i8 %v1, %v2
721 %c3 = icmp eq i8 %v3, 0
722 br i1 %c3, label %final_left, label %final_right
724 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
725 %merge_left_2 = phi i8 [ %v3_adj, %dispatch ], [ 42, %pred0 ]
726 call void @use8(i8 %merge_left)
727 call void @use8(i8 %merge_left_2)
728 call void @sideeffect0()
731 call void @sideeffect1()
735 ; The liveout instruction can be located after the branch condition.
736 define void @one_pred_with_extra_op_externally_used_only_after_cond_distant_phi(i8 %v0, i8 %v1, i8 %v3, i8 %v4, i8 %v5) {
737 ; CHECK-LABEL: @one_pred_with_extra_op_externally_used_only_after_cond_distant_phi(
739 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
740 ; CHECK-NEXT: br i1 [[C0]], label [[PRED:%.*]], label [[LEFT_END:%.*]]
742 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
743 ; CHECK-NEXT: br i1 [[C1]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
745 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
746 ; CHECK-NEXT: [[V2_ADJ:%.*]] = add i8 [[V4:%.*]], [[V5:%.*]]
747 ; CHECK-NEXT: br i1 [[C3]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
749 ; CHECK-NEXT: call void @sideeffect0()
750 ; CHECK-NEXT: call void @use8(i8 [[V2_ADJ]])
751 ; CHECK-NEXT: br label [[LEFT_END]]
753 ; CHECK-NEXT: ret void
755 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V2_ADJ]], [[FINAL_LEFT]] ], [ 0, [[ENTRY:%.*]] ]
756 ; CHECK-NEXT: call void @sideeffect1()
757 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
758 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
759 ; CHECK: final_right:
760 ; CHECK-NEXT: call void @sideeffect2()
761 ; CHECK-NEXT: br label [[COMMON_RET]]
764 %c0 = icmp eq i8 %v0, 0
765 br i1 %c0, label %pred, label %left_end
767 %c1 = icmp eq i8 %v1, 0
768 br i1 %c1, label %dispatch, label %final_right
770 %c3 = icmp eq i8 %v3, 0
771 %v2_adj = add i8 %v4, %v5
772 br i1 %c3, label %final_left, label %final_right
774 call void @sideeffect0()
775 call void @use8(i8 %v2_adj)
778 %merge_left = phi i8 [ %v2_adj, %final_left ], [ 0, %entry ]
779 call void @sideeffect1()
780 call void @use8(i8 %merge_left)
783 call void @sideeffect2()
786 define void @two_preds_with_extra_op_externally_used_only_after_cond(i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
787 ; CHECK-LABEL: @two_preds_with_extra_op_externally_used_only_after_cond(
789 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
790 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
792 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
793 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
795 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
796 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
797 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V4:%.*]], [[V5:%.*]]
798 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
799 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
801 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
802 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V4]], [[V5]]
803 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
805 ; CHECK-NEXT: ret void
807 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
808 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
809 ; CHECK-NEXT: call void @sideeffect0()
810 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
811 ; CHECK: final_right:
812 ; CHECK-NEXT: call void @sideeffect1()
813 ; CHECK-NEXT: br label [[COMMON_RET]]
816 %c0 = icmp eq i8 %v0, 0
817 br i1 %c0, label %pred0, label %pred1
819 %c1 = icmp eq i8 %v1, 0
820 br i1 %c1, label %final_left, label %dispatch
822 %c2 = icmp eq i8 %v2, 0
823 br i1 %c2, label %dispatch, label %final_right
825 %c3 = icmp eq i8 %v3, 0
826 %v3_adj = add i8 %v4, %v5
827 br i1 %c3, label %final_left, label %final_right
829 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
830 call void @use8(i8 %merge_left)
831 call void @sideeffect0()
834 call void @sideeffect1()
838 define void @pr48450() {
839 ; CHECK-LABEL: @pr48450(
841 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
843 ; CHECK-NEXT: [[COUNTDOWN:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[DEC:%.*]], [[FOR_BODYTHREAD_PRE_SPLIT:%.*]] ]
844 ; CHECK-NEXT: [[C:%.*]] = call i1 @gen1()
845 ; CHECK-NEXT: br i1 [[C]], label [[FOR_INC:%.*]], label [[IF_THEN:%.*]]
847 ; CHECK-NEXT: [[DEC]] = add i8 [[COUNTDOWN]], -1
848 ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
849 ; CHECK-NEXT: br i1 [[CMP_NOT]], label [[IF_END_LOOPEXIT:%.*]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
851 ; CHECK-NEXT: [[C2:%.*]] = call i1 @gen1()
852 ; CHECK-NEXT: br i1 [[C2]], label [[FOR_INC]], label [[IF_END_LOOPEXIT]]
853 ; CHECK: for.bodythread-pre-split:
854 ; CHECK-NEXT: call void @sideeffect0()
855 ; CHECK-NEXT: br label [[FOR_BODY]]
856 ; CHECK: if.end.loopexit:
857 ; CHECK-NEXT: ret void
863 %countdown = phi i8 [ 8, %entry ], [ %dec, %for.bodythread-pre-split ]
865 br i1 %c, label %for.inc, label %if.then
868 %dec = add i8 %countdown, -1
869 %cmp.not = icmp eq i8 %countdown, 0
870 br i1 %cmp.not, label %if.end.loopexit, label %for.bodythread-pre-split
873 %c2 = call i1 @gen1()
874 br i1 %c2, label %for.inc, label %if.end.loopexit
876 for.bodythread-pre-split:
877 call void @sideeffect0()
884 define void @pr48450_2(i1 %enable_loopback) {
885 ; CHECK-LABEL: @pr48450_2(
887 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
889 ; CHECK-NEXT: [[COUNTDOWN:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[DEC:%.*]], [[FOR_BODYTHREAD_PRE_SPLIT:%.*]] ]
890 ; CHECK-NEXT: [[C:%.*]] = call i1 @gen1()
891 ; CHECK-NEXT: br i1 [[C]], label [[FOR_INC:%.*]], label [[IF_THEN:%.*]]
893 ; CHECK-NEXT: [[DEC]] = add i8 [[COUNTDOWN]], -1
894 ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
895 ; CHECK-NEXT: br i1 [[CMP_NOT]], label [[IF_END_LOOPEXIT:%.*]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
897 ; CHECK-NEXT: [[C2:%.*]] = call i1 @gen1()
898 ; CHECK-NEXT: br i1 [[C2]], label [[FOR_INC]], label [[IF_END_LOOPEXIT]]
899 ; CHECK: for.bodythread-pre-split:
900 ; CHECK-NEXT: [[SHOULD_LOOPBACK:%.*]] = phi i1 [ true, [[FOR_INC]] ], [ false, [[FOR_BODYTHREAD_PRE_SPLIT_LOOPBACK:%.*]] ]
901 ; CHECK-NEXT: [[DO_LOOPBACK:%.*]] = and i1 [[SHOULD_LOOPBACK]], [[ENABLE_LOOPBACK:%.*]]
902 ; CHECK-NEXT: call void @sideeffect0()
903 ; CHECK-NEXT: br i1 [[DO_LOOPBACK]], label [[FOR_BODYTHREAD_PRE_SPLIT_LOOPBACK]], label [[FOR_BODY]]
904 ; CHECK: for.bodythread-pre-split.loopback:
905 ; CHECK-NEXT: call void @sideeffect0()
906 ; CHECK-NEXT: br label [[FOR_BODYTHREAD_PRE_SPLIT]]
907 ; CHECK: if.end.loopexit:
908 ; CHECK-NEXT: ret void
914 %countdown = phi i8 [ 8, %entry ], [ %dec, %for.bodythread-pre-split ]
916 br i1 %c, label %for.inc, label %if.then
919 %dec = add i8 %countdown, -1
920 %cmp.not = icmp eq i8 %countdown, 0
921 br i1 %cmp.not, label %if.end.loopexit, label %for.bodythread-pre-split
924 %c2 = call i1 @gen1()
925 br i1 %c2, label %for.inc, label %if.end.loopexit
927 for.bodythread-pre-split:
928 %should_loopback = phi i1 [ 1, %for.inc ], [ 0, %for.bodythread-pre-split.loopback ]
929 %do_loopback = and i1 %should_loopback, %enable_loopback
930 call void @sideeffect0()
931 br i1 %do_loopback, label %for.bodythread-pre-split.loopback, label %for.body
933 for.bodythread-pre-split.loopback:
934 call void @sideeffect0()
935 br label %for.bodythread-pre-split
941 @f.b = external global i8, align 1
942 define void @pr48450_3() {
943 ; CHECK-LABEL: @pr48450_3(
945 ; CHECK-NEXT: br label [[FOR_COND1:%.*]]
947 ; CHECK-NEXT: [[V:%.*]] = load i8, ptr @f.b, align 1
948 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[V]], 1
949 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
950 ; CHECK-NEXT: br label [[FOR_COND1]]
956 %v = load i8, ptr @f.b, align 1
957 %cmp = icmp slt i8 %v, 1
958 br i1 %cmp, label %for.body, label %for.end
964 %tobool = icmp ne i8 %v, 0
965 br i1 %tobool, label %if.then, label %if.end
974 %c.0 = phi i8 [ undef, %if.end ], [ %inc, %if.end7 ]
975 %cmp3 = icmp slt i8 %c.0, 1
976 br i1 %cmp3, label %for.body4, label %for.cond.cleanup
982 br i1 undef, label %if.then6, label %if.end7
988 %inc = add nsw i8 %c.0, 1
995 @global_pr49510 = external global i16, align 1
997 define void @pr49510() {
998 ; CHECK-LABEL: @pr49510(
1000 ; CHECK-NEXT: br label [[FOR_COND:%.*]]
1002 ; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @global_pr49510, align 1
1003 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i16 [[TMP0]], 0
1004 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[TMP0]], 0
1005 ; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[TOBOOL]], [[CMP]]
1006 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FOR_COND]], label [[FOR_END:%.*]]
1008 ; CHECK-NEXT: ret void
1014 %0 = load i16, ptr @global_pr49510, align 1
1015 %tobool = icmp ne i16 %0, 0
1016 br i1 %tobool, label %land.rhs, label %for.end
1019 %cmp = icmp slt i16 %0, 0
1020 br i1 %cmp, label %for.cond, label %for.end
1027 ; This is a miscompile if we replace a phi incoming value
1028 ; with an updated loaded value *after* it was stored.
1030 @global_pr51125 = global i32 1, align 4
1032 define i32 @pr51125() {
1033 ; CHECK-LABEL: @pr51125(
1034 ; CHECK-NEXT: entry:
1035 ; CHECK-NEXT: br label [[L:%.*]]
1037 ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr @global_pr51125, align 4
1038 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[LD]], 0
1039 ; CHECK-NEXT: br i1 [[ISZERO]], label [[EXIT:%.*]], label [[L2:%.*]]
1041 ; CHECK-NEXT: store i32 -1, ptr @global_pr51125, align 4
1042 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[LD]], -1
1043 ; CHECK-NEXT: br i1 [[CMP]], label [[L]], label [[EXIT]]
1045 ; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[LD]], [[L2]] ], [ [[LD]], [[L]] ]
1046 ; CHECK-NEXT: ret i32 [[R]]
1052 %ld = load i32, ptr @global_pr51125, align 4
1053 %iszero = icmp eq i32 %ld, 0
1054 br i1 %iszero, label %exit, label %L2
1057 store i32 -1, ptr @global_pr51125, align 4
1058 %cmp = icmp eq i32 %ld, -1
1059 br i1 %cmp, label %L, label %exit
1062 %r = phi i32 [ %ld, %L2 ], [ %ld, %L ]
1066 ; https://github.com/llvm/llvm-project/issues/53861
1067 define i32 @firewall(ptr %data) {
1068 ; CHECK-LABEL: @firewall(
1069 ; CHECK-NEXT: entry:
1070 ; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[DATA:%.*]], align 1
1071 ; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[DATA]], i64 64
1072 ; CHECK-NEXT: [[I2:%.*]] = load i16, ptr [[ADD_PTR]], align 2
1073 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[I]], 17
1074 ; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i16 [[I2]], 1
1075 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[CMP3]], i1 false
1076 ; CHECK-NEXT: [[CMP10:%.*]] = icmp eq i16 [[I2]], 2
1077 ; CHECK-NEXT: [[OR_COND33:%.*]] = select i1 [[CMP]], i1 [[CMP10]], i1 false
1078 ; CHECK-NEXT: [[OR_COND1:%.*]] = select i1 [[OR_COND]], i1 true, i1 [[OR_COND33]]
1079 ; CHECK-NEXT: [[CMP19:%.*]] = icmp eq i16 [[I2]], 3
1080 ; CHECK-NEXT: [[OR_COND34:%.*]] = select i1 [[CMP]], i1 [[CMP19]], i1 false
1081 ; CHECK-NEXT: [[OR_COND2:%.*]] = select i1 [[OR_COND1]], i1 true, i1 [[OR_COND34]]
1082 ; CHECK-NEXT: [[CMP28:%.*]] = icmp eq i16 [[I2]], 4
1083 ; CHECK-NEXT: [[OR_COND35:%.*]] = select i1 [[CMP]], i1 [[CMP28]], i1 false
1084 ; CHECK-NEXT: [[DOT:%.*]] = zext i1 [[OR_COND35]] to i32
1085 ; CHECK-NEXT: [[RETVAL_0:%.*]] = select i1 [[OR_COND2]], i32 1, i32 [[DOT]]
1086 ; CHECK-NEXT: ret i32 [[RETVAL_0]]
1089 %i = load i8, ptr %data, align 1
1090 %add.ptr = getelementptr inbounds i8, ptr %data, i64 64
1091 %i2 = load i16, ptr %add.ptr, align 2
1092 %cmp = icmp eq i8 %i, 17
1093 %cmp3 = icmp eq i16 %i2, 1
1094 %or.cond = select i1 %cmp, i1 %cmp3, i1 false
1095 br i1 %or.cond, label %cleanup, label %if.end
1098 %cmp10 = icmp eq i16 %i2, 2
1099 %or.cond33 = select i1 %cmp, i1 %cmp10, i1 false
1100 br i1 %or.cond33, label %cleanup, label %if.end13
1103 %cmp19 = icmp eq i16 %i2, 3
1104 %or.cond34 = select i1 %cmp, i1 %cmp19, i1 false
1105 br i1 %or.cond34, label %cleanup, label %if.end22
1108 %cmp28 = icmp eq i16 %i2, 4
1109 %or.cond35 = select i1 %cmp, i1 %cmp28, i1 false
1110 %. = zext i1 %or.cond35 to i32
1114 %retval.0 = phi i32 [ 1, %entry ], [ 1, %if.end ], [ 1, %if.end13 ], [ %., %if.end22 ]
1118 define i32 @test_builtin_fpclassify(float %x) {
1119 ; CHECK-LABEL: @test_builtin_fpclassify(
1120 ; CHECK-NEXT: entry:
1121 ; CHECK-NEXT: [[ISZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
1122 ; CHECK-NEXT: br i1 [[ISZERO]], label [[FPCLASSIFY_END:%.*]], label [[FPCLASSIFY_NOT_ZERO:%.*]]
1123 ; CHECK: fpclassify_end:
1124 ; CHECK-NEXT: [[FPCLASSIFY_RESULT:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ 0, [[FPCLASSIFY_NOT_ZERO]] ], [ 1, [[FPCLASSIFY_NOT_NAN:%.*]] ], [ [[NORMAL_OR_SUBNORMAL:%.*]], [[FPCLASSIFY_NOT_INF:%.*]] ]
1125 ; CHECK-NEXT: ret i32 [[FPCLASSIFY_RESULT]]
1126 ; CHECK: fpclassify_not_zero:
1127 ; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[X]], 0.000000e+00
1128 ; CHECK-NEXT: br i1 [[CMP]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_NAN]]
1129 ; CHECK: fpclassify_not_nan:
1130 ; CHECK-NEXT: [[X_ABS:%.*]] = tail call float @llvm.fabs.f32(float [[X]])
1131 ; CHECK-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X_ABS]], 0x7FF0000000000000
1132 ; CHECK-NEXT: br i1 [[ISINF]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_INF]]
1133 ; CHECK: fpclassify_not_inf:
1134 ; CHECK-NEXT: [[ISNORMAL:%.*]] = fcmp uge float [[X_ABS]], 0x3810000000000000
1135 ; CHECK-NEXT: [[NORMAL_OR_SUBNORMAL]] = select i1 [[ISNORMAL]], i32 4, i32 3
1136 ; CHECK-NEXT: br label [[FPCLASSIFY_END]]
1139 %iszero = fcmp oeq float %x, 0.000000e+00
1140 br i1 %iszero, label %fpclassify_end, label %fpclassify_not_zero
1143 %fpclassify_result = phi i32 [ 2, %entry ], [ 0, %fpclassify_not_zero ], [ 1, %fpclassify_not_nan ], [ %normal_or_subnormal, %fpclassify_not_inf ]
1144 ret i32 %fpclassify_result
1146 fpclassify_not_zero:
1147 %cmp = fcmp uno float %x, 0.000000e+00
1148 br i1 %cmp, label %fpclassify_end, label %fpclassify_not_nan
1151 %x.abs = tail call float @llvm.fabs.f32(float %x)
1152 %isinf = fcmp oeq float %x.abs, 0x7FF0000000000000
1153 br i1 %isinf, label %fpclassify_end, label %fpclassify_not_inf
1156 %isnormal = fcmp uge float %x.abs, 0x3810000000000000
1157 %normal_or_subnormal = select i1 %isnormal, i32 4, i32 3
1158 br label %fpclassify_end
1161 declare float @llvm.fabs.f32(float)
1163 attributes #0 = { nounwind argmemonly speculatable }