1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -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(i32 *) #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, i32* %p) {
125 ; CHECK-LABEL: @one_pred_with_spec_call(
127 ; CHECK-NEXT: [[C0:%.*]] = icmp ne i32* [[P:%.*]], null
128 ; CHECK-NEXT: [[X:%.*]] = call i32 @speculate_call(i32* 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 i32* %p, null
140 br i1 %c0, label %dispatch, label %final_right
143 %x = call i32 @speculate_call(i32* 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, i32* %p) {
157 ; CHECK-LABEL: @one_pred_with_spec_call_deref(
159 ; CHECK-NEXT: [[C0:%.*]] = icmp ne i32* [[P:%.*]], null
160 ; CHECK-NEXT: [[X:%.*]] = call i32 @speculate_call(i32* [[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 i32* %p, null
172 br i1 %c0, label %dispatch, label %final_right
175 %x = call i32 @speculate_call(i32* 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: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
328 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
329 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
330 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
332 ; CHECK-NEXT: ret void
334 ; CHECK-NEXT: call void @sideeffect0()
335 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
336 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
337 ; CHECK: final_right:
338 ; CHECK-NEXT: call void @sideeffect1()
339 ; CHECK-NEXT: br label [[COMMON_RET]]
342 %c0 = icmp eq i8 %v0, 0
343 br i1 %c0, label %dispatch, label %final_right
345 %v1_adj = add i8 %v0, %v1
346 %c1 = icmp eq i8 %v1_adj, 0
347 br i1 %c1, label %final_left, label %final_right
349 call void @sideeffect0()
350 call void @use8(i8 %v1_adj)
353 call void @sideeffect1()
356 define void @one_pred_with_extra_op_liveout_multiuse(i8 %v0, i8 %v1) {
357 ; CHECK-LABEL: @one_pred_with_extra_op_liveout_multiuse(
359 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
360 ; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
361 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
362 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
363 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
365 ; CHECK-NEXT: ret void
367 ; CHECK-NEXT: call void @sideeffect0()
368 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
369 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
370 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
371 ; CHECK: final_right:
372 ; CHECK-NEXT: call void @sideeffect1()
373 ; CHECK-NEXT: br label [[COMMON_RET]]
376 %c0 = icmp eq i8 %v0, 0
377 br i1 %c0, label %dispatch, label %final_right
379 %v1_adj = add i8 %v0, %v1
380 %c1 = icmp eq i8 %v1_adj, 0
381 br i1 %c1, label %final_left, label %final_right
383 call void @sideeffect0()
384 call void @use8(i8 %v1_adj)
385 call void @use8(i8 %v1_adj)
388 call void @sideeffect1()
392 define void @one_pred_with_extra_op_liveout_distant_phi(i8 %v0, i8 %v1) {
393 ; CHECK-LABEL: @one_pred_with_extra_op_liveout_distant_phi(
395 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
396 ; CHECK-NEXT: br i1 [[C0]], label [[PRED:%.*]], label [[LEFT_END:%.*]]
398 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
399 ; CHECK-NEXT: [[V2_ADJ:%.*]] = add i8 [[V0]], [[V1]]
400 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2_ADJ]], 0
401 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false
402 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
404 ; CHECK-NEXT: call void @sideeffect0()
405 ; CHECK-NEXT: call void @use8(i8 [[V2_ADJ]])
406 ; CHECK-NEXT: br label [[LEFT_END]]
408 ; CHECK-NEXT: ret void
410 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V2_ADJ]], [[FINAL_LEFT]] ], [ 0, [[ENTRY:%.*]] ]
411 ; CHECK-NEXT: call void @sideeffect1()
412 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
413 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
414 ; CHECK: final_right:
415 ; CHECK-NEXT: call void @sideeffect2()
416 ; CHECK-NEXT: br label [[COMMON_RET]]
419 %c0 = icmp eq i8 %v0, 0
420 br i1 %c0, label %pred, label %left_end
422 %c1 = icmp eq i8 %v1, 0
423 br i1 %c1, label %dispatch, label %final_right
425 %v2_adj = add i8 %v0, %v1
426 %c2 = icmp eq i8 %v2_adj, 0
427 br i1 %c2, label %final_left, label %final_right
429 call void @sideeffect0()
430 call void @use8(i8 %v2_adj)
433 %merge_left = phi i8 [ %v2_adj, %final_left ], [ 0, %entry ]
434 call void @sideeffect1()
435 call void @use8(i8 %merge_left)
438 call void @sideeffect2()
442 define void @two_preds_with_extra_op_liveout(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
443 ; CHECK-LABEL: @two_preds_with_extra_op_liveout(
445 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
446 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
448 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
449 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
451 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
452 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
453 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
454 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
455 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
457 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
458 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0
459 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
461 ; CHECK-NEXT: ret void
463 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
464 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
465 ; CHECK-NEXT: call void @sideeffect0()
466 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
467 ; CHECK: final_right:
468 ; CHECK-NEXT: call void @sideeffect1()
469 ; CHECK-NEXT: br label [[COMMON_RET]]
472 %c0 = icmp eq i8 %v0, 0
473 br i1 %c0, label %pred0, label %pred1
475 %c1 = icmp eq i8 %v1, 0
476 br i1 %c1, label %final_left, label %dispatch
478 %c2 = icmp eq i8 %v2, 0
479 br i1 %c2, label %dispatch, label %final_right
481 %v3_adj = add i8 %v1, %v2
482 %c3 = icmp eq i8 %v3_adj, 0
483 br i1 %c3, label %final_left, label %final_right
485 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
486 call void @use8(i8 %merge_left)
487 call void @sideeffect0()
490 call void @sideeffect1()
494 define void @two_preds_with_extra_op_liveout_multiuse(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
495 ; CHECK-LABEL: @two_preds_with_extra_op_liveout_multiuse(
497 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
498 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
500 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
501 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
503 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
504 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
505 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
506 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
507 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
509 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
510 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0
511 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
513 ; CHECK-NEXT: ret void
515 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
516 ; CHECK-NEXT: [[MERGE_LEFT_2:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 42, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
517 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
518 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT_2]])
519 ; CHECK-NEXT: call void @sideeffect0()
520 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
521 ; CHECK: final_right:
522 ; CHECK-NEXT: call void @sideeffect1()
523 ; CHECK-NEXT: br label [[COMMON_RET]]
526 %c0 = icmp eq i8 %v0, 0
527 br i1 %c0, label %pred0, label %pred1
529 %c1 = icmp eq i8 %v1, 0
530 br i1 %c1, label %final_left, label %dispatch
532 %c2 = icmp eq i8 %v2, 0
533 br i1 %c2, label %dispatch, label %final_right
535 %v3_adj = add i8 %v1, %v2
536 %c3 = icmp eq i8 %v3_adj, 0
537 br i1 %c3, label %final_left, label %final_right
539 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
540 %merge_left_2 = phi i8 [ %v3_adj, %dispatch ], [ 42, %pred0 ]
541 call void @use8(i8 %merge_left)
542 call void @use8(i8 %merge_left_2)
543 call void @sideeffect0()
546 call void @sideeffect1()
550 ; More complex case, there's an op that is safe to execute unconditionally,
551 ; and said op is live-out, and it is only used externally.
553 define void @one_pred_with_extra_op_eexternally_used_only(i8 %v0, i8 %v1) {
554 ; CHECK-LABEL: @one_pred_with_extra_op_eexternally_used_only(
556 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
557 ; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
558 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1]], 0
559 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
560 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
562 ; CHECK-NEXT: ret void
564 ; CHECK-NEXT: call void @sideeffect0()
565 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
566 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
567 ; CHECK: final_right:
568 ; CHECK-NEXT: call void @sideeffect1()
569 ; CHECK-NEXT: br label [[COMMON_RET]]
572 %c0 = icmp eq i8 %v0, 0
573 br i1 %c0, label %dispatch, label %final_right
575 %v1_adj = add i8 %v0, %v1
576 %c1 = icmp eq i8 %v1, 0
577 br i1 %c1, label %final_left, label %final_right
579 call void @sideeffect0()
580 call void @use8(i8 %v1_adj)
583 call void @sideeffect1()
586 define void @one_pred_with_extra_op_externally_used_only_multiuse(i8 %v0, i8 %v1) {
587 ; CHECK-LABEL: @one_pred_with_extra_op_externally_used_only_multiuse(
589 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
590 ; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
591 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1]], 0
592 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C0]], i1 [[C1]], i1 false
593 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
595 ; CHECK-NEXT: ret void
597 ; CHECK-NEXT: call void @sideeffect0()
598 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
599 ; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
600 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
601 ; CHECK: final_right:
602 ; CHECK-NEXT: call void @sideeffect1()
603 ; CHECK-NEXT: br label [[COMMON_RET]]
606 %c0 = icmp eq i8 %v0, 0
607 br i1 %c0, label %dispatch, label %final_right
609 %v1_adj = add i8 %v0, %v1
610 %c1 = icmp eq i8 %v1, 0
611 br i1 %c1, label %final_left, label %final_right
613 call void @sideeffect0()
614 call void @use8(i8 %v1_adj)
615 call void @use8(i8 %v1_adj)
618 call void @sideeffect1()
622 define void @two_preds_with_extra_op_externally_used_only(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
623 ; CHECK-LABEL: @two_preds_with_extra_op_externally_used_only(
625 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
626 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
628 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
629 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
631 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
632 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
633 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
634 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
635 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
637 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
638 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
639 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
641 ; CHECK-NEXT: ret void
643 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
644 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
645 ; CHECK-NEXT: call void @sideeffect0()
646 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
647 ; CHECK: final_right:
648 ; CHECK-NEXT: call void @sideeffect1()
649 ; CHECK-NEXT: br label [[COMMON_RET]]
652 %c0 = icmp eq i8 %v0, 0
653 br i1 %c0, label %pred0, label %pred1
655 %c1 = icmp eq i8 %v1, 0
656 br i1 %c1, label %final_left, label %dispatch
658 %c2 = icmp eq i8 %v2, 0
659 br i1 %c2, label %dispatch, label %final_right
661 %v3_adj = add i8 %v1, %v2
662 %c3 = icmp eq i8 %v3, 0
663 br i1 %c3, label %final_left, label %final_right
665 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
666 call void @use8(i8 %merge_left)
667 call void @sideeffect0()
670 call void @sideeffect1()
674 define void @two_preds_with_extra_op_externally_used_only_multiuse(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
675 ; CHECK-LABEL: @two_preds_with_extra_op_externally_used_only_multiuse(
677 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
678 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
680 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
681 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
683 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
684 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
685 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
686 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
687 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
689 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]]
690 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
691 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
693 ; CHECK-NEXT: ret void
695 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
696 ; CHECK-NEXT: [[MERGE_LEFT_2:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 42, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
697 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
698 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT_2]])
699 ; CHECK-NEXT: call void @sideeffect0()
700 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
701 ; CHECK: final_right:
702 ; CHECK-NEXT: call void @sideeffect1()
703 ; CHECK-NEXT: br label [[COMMON_RET]]
706 %c0 = icmp eq i8 %v0, 0
707 br i1 %c0, label %pred0, label %pred1
709 %c1 = icmp eq i8 %v1, 0
710 br i1 %c1, label %final_left, label %dispatch
712 %c2 = icmp eq i8 %v2, 0
713 br i1 %c2, label %dispatch, label %final_right
715 %v3_adj = add i8 %v1, %v2
716 %c3 = icmp eq i8 %v3, 0
717 br i1 %c3, label %final_left, label %final_right
719 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
720 %merge_left_2 = phi i8 [ %v3_adj, %dispatch ], [ 42, %pred0 ]
721 call void @use8(i8 %merge_left)
722 call void @use8(i8 %merge_left_2)
723 call void @sideeffect0()
726 call void @sideeffect1()
730 ; The liveout instruction can be located after the branch condition.
731 define void @one_pred_with_extra_op_externally_used_only_after_cond_distant_phi(i8 %v0, i8 %v1, i8 %v3, i8 %v4, i8 %v5) {
732 ; CHECK-LABEL: @one_pred_with_extra_op_externally_used_only_after_cond_distant_phi(
734 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
735 ; CHECK-NEXT: br i1 [[C0]], label [[PRED:%.*]], label [[LEFT_END:%.*]]
737 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
738 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
739 ; CHECK-NEXT: [[V2_ADJ:%.*]] = add i8 [[V4:%.*]], [[V5:%.*]]
740 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C1]], i1 [[C3]], i1 false
741 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
743 ; CHECK-NEXT: call void @sideeffect0()
744 ; CHECK-NEXT: call void @use8(i8 [[V2_ADJ]])
745 ; CHECK-NEXT: br label [[LEFT_END]]
747 ; CHECK-NEXT: ret void
749 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V2_ADJ]], [[FINAL_LEFT]] ], [ 0, [[ENTRY:%.*]] ]
750 ; CHECK-NEXT: call void @sideeffect1()
751 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
752 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
753 ; CHECK: final_right:
754 ; CHECK-NEXT: call void @sideeffect2()
755 ; CHECK-NEXT: br label [[COMMON_RET]]
758 %c0 = icmp eq i8 %v0, 0
759 br i1 %c0, label %pred, label %left_end
761 %c1 = icmp eq i8 %v1, 0
762 br i1 %c1, label %dispatch, label %final_right
764 %c3 = icmp eq i8 %v3, 0
765 %v2_adj = add i8 %v4, %v5
766 br i1 %c3, label %final_left, label %final_right
768 call void @sideeffect0()
769 call void @use8(i8 %v2_adj)
772 %merge_left = phi i8 [ %v2_adj, %final_left ], [ 0, %entry ]
773 call void @sideeffect1()
774 call void @use8(i8 %merge_left)
777 call void @sideeffect2()
780 define void @two_preds_with_extra_op_externally_used_only_after_cond(i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) {
781 ; CHECK-LABEL: @two_preds_with_extra_op_externally_used_only_after_cond(
783 ; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
784 ; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
786 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
787 ; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
789 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
790 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
791 ; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V4:%.*]], [[V5:%.*]]
792 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false
793 ; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
795 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
796 ; CHECK-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V4]], [[V5]]
797 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
799 ; CHECK-NEXT: ret void
801 ; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ_OLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
802 ; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
803 ; CHECK-NEXT: call void @sideeffect0()
804 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
805 ; CHECK: final_right:
806 ; CHECK-NEXT: call void @sideeffect1()
807 ; CHECK-NEXT: br label [[COMMON_RET]]
810 %c0 = icmp eq i8 %v0, 0
811 br i1 %c0, label %pred0, label %pred1
813 %c1 = icmp eq i8 %v1, 0
814 br i1 %c1, label %final_left, label %dispatch
816 %c2 = icmp eq i8 %v2, 0
817 br i1 %c2, label %dispatch, label %final_right
819 %c3 = icmp eq i8 %v3, 0
820 %v3_adj = add i8 %v4, %v5
821 br i1 %c3, label %final_left, label %final_right
823 %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
824 call void @use8(i8 %merge_left)
825 call void @sideeffect0()
828 call void @sideeffect1()
832 define void @pr48450() {
833 ; CHECK-LABEL: @pr48450(
835 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
837 ; CHECK-NEXT: [[COUNTDOWN:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[DEC_MERGE:%.*]], [[FOR_BODYTHREAD_PRE_SPLIT:%.*]] ]
838 ; CHECK-NEXT: [[C:%.*]] = call i1 @gen1()
839 ; CHECK-NEXT: br i1 [[C]], label [[FOR_INC:%.*]], label [[IF_THEN:%.*]]
841 ; CHECK-NEXT: [[DEC_OLD:%.*]] = add i8 [[COUNTDOWN]], -1
842 ; CHECK-NEXT: [[CMP_NOT_OLD:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
843 ; CHECK-NEXT: br i1 [[CMP_NOT_OLD]], label [[IF_END_LOOPEXIT:%.*]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
845 ; CHECK-NEXT: [[C2:%.*]] = call i1 @gen1()
846 ; CHECK-NEXT: [[C2_NOT:%.*]] = xor i1 [[C2]], true
847 ; CHECK-NEXT: [[DEC:%.*]] = add i8 [[COUNTDOWN]], -1
848 ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
849 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2_NOT]], i1 true, i1 [[CMP_NOT]]
850 ; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_END_LOOPEXIT]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
851 ; CHECK: for.bodythread-pre-split:
852 ; CHECK-NEXT: [[DEC_MERGE]] = phi i8 [ [[DEC]], [[IF_THEN]] ], [ [[DEC_OLD]], [[FOR_INC]] ]
853 ; CHECK-NEXT: call void @sideeffect0()
854 ; CHECK-NEXT: br label [[FOR_BODY]]
855 ; CHECK: if.end.loopexit:
856 ; CHECK-NEXT: ret void
862 %countdown = phi i8 [ 8, %entry ], [ %dec, %for.bodythread-pre-split ]
864 br i1 %c, label %for.inc, label %if.then
867 %dec = add i8 %countdown, -1
868 %cmp.not = icmp eq i8 %countdown, 0
869 br i1 %cmp.not, label %if.end.loopexit, label %for.bodythread-pre-split
872 %c2 = call i1 @gen1()
873 br i1 %c2, label %for.inc, label %if.end.loopexit
875 for.bodythread-pre-split:
876 call void @sideeffect0()
883 define void @pr48450_2(i1 %enable_loopback) {
884 ; CHECK-LABEL: @pr48450_2(
886 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
888 ; CHECK-NEXT: [[COUNTDOWN:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[DEC_MERGE:%.*]], [[FOR_BODYTHREAD_PRE_SPLIT:%.*]] ]
889 ; CHECK-NEXT: [[C:%.*]] = call i1 @gen1()
890 ; CHECK-NEXT: br i1 [[C]], label [[FOR_INC:%.*]], label [[IF_THEN:%.*]]
892 ; CHECK-NEXT: [[DEC_OLD:%.*]] = add i8 [[COUNTDOWN]], -1
893 ; CHECK-NEXT: [[CMP_NOT_OLD:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
894 ; CHECK-NEXT: br i1 [[CMP_NOT_OLD]], label [[IF_END_LOOPEXIT:%.*]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
896 ; CHECK-NEXT: [[C2:%.*]] = call i1 @gen1()
897 ; CHECK-NEXT: [[C2_NOT:%.*]] = xor i1 [[C2]], true
898 ; CHECK-NEXT: [[DEC:%.*]] = add i8 [[COUNTDOWN]], -1
899 ; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i8 [[COUNTDOWN]], 0
900 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2_NOT]], i1 true, i1 [[CMP_NOT]]
901 ; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_END_LOOPEXIT]], label [[FOR_BODYTHREAD_PRE_SPLIT]]
902 ; CHECK: for.bodythread-pre-split:
903 ; CHECK-NEXT: [[DEC_MERGE]] = phi i8 [ [[DEC_OLD]], [[FOR_INC]] ], [ [[DEC_MERGE]], [[FOR_BODYTHREAD_PRE_SPLIT_LOOPBACK:%.*]] ], [ [[DEC]], [[IF_THEN]] ]
904 ; CHECK-NEXT: [[SHOULD_LOOPBACK:%.*]] = phi i1 [ true, [[FOR_INC]] ], [ false, [[FOR_BODYTHREAD_PRE_SPLIT_LOOPBACK]] ], [ true, [[IF_THEN]] ]
905 ; CHECK-NEXT: [[DO_LOOPBACK:%.*]] = and i1 [[SHOULD_LOOPBACK]], [[ENABLE_LOOPBACK:%.*]]
906 ; CHECK-NEXT: call void @sideeffect0()
907 ; CHECK-NEXT: br i1 [[DO_LOOPBACK]], label [[FOR_BODYTHREAD_PRE_SPLIT_LOOPBACK]], label [[FOR_BODY]]
908 ; CHECK: for.bodythread-pre-split.loopback:
909 ; CHECK-NEXT: call void @sideeffect0()
910 ; CHECK-NEXT: br label [[FOR_BODYTHREAD_PRE_SPLIT]]
911 ; CHECK: if.end.loopexit:
912 ; CHECK-NEXT: ret void
918 %countdown = phi i8 [ 8, %entry ], [ %dec, %for.bodythread-pre-split ]
920 br i1 %c, label %for.inc, label %if.then
923 %dec = add i8 %countdown, -1
924 %cmp.not = icmp eq i8 %countdown, 0
925 br i1 %cmp.not, label %if.end.loopexit, label %for.bodythread-pre-split
928 %c2 = call i1 @gen1()
929 br i1 %c2, label %for.inc, label %if.end.loopexit
931 for.bodythread-pre-split:
932 %should_loopback = phi i1 [ 1, %for.inc ], [ 0, %for.bodythread-pre-split.loopback ]
933 %do_loopback = and i1 %should_loopback, %enable_loopback
934 call void @sideeffect0()
935 br i1 %do_loopback, label %for.bodythread-pre-split.loopback, label %for.body
937 for.bodythread-pre-split.loopback:
938 call void @sideeffect0()
939 br label %for.bodythread-pre-split
945 @f.b = external global i8, align 1
946 define void @pr48450_3() {
947 ; CHECK-LABEL: @pr48450_3(
949 ; CHECK-NEXT: br label [[FOR_COND1:%.*]]
951 ; CHECK-NEXT: [[V:%.*]] = load i8, i8* @f.b, align 1
952 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[V]], 1
953 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
954 ; CHECK-NEXT: br label [[FOR_COND1]]
960 %v = load i8, i8* @f.b, align 1
961 %cmp = icmp slt i8 %v, 1
962 br i1 %cmp, label %for.body, label %for.end
968 %tobool = icmp ne i8 %v, 0
969 br i1 %tobool, label %if.then, label %if.end
978 %c.0 = phi i8 [ undef, %if.end ], [ %inc, %if.end7 ]
979 %cmp3 = icmp slt i8 %c.0, 1
980 br i1 %cmp3, label %for.body4, label %for.cond.cleanup
986 br i1 undef, label %if.then6, label %if.end7
992 %inc = add nsw i8 %c.0, 1
999 @global_pr49510 = external global i16, align 1
1001 define void @pr49510() {
1002 ; CHECK-LABEL: @pr49510(
1003 ; CHECK-NEXT: entry:
1004 ; CHECK-NEXT: [[DOTOLD:%.*]] = load i16, i16* @global_pr49510, align 1
1005 ; CHECK-NEXT: [[TOBOOL_OLD:%.*]] = icmp ne i16 [[DOTOLD]], 0
1006 ; CHECK-NEXT: br i1 [[TOBOOL_OLD]], label [[LAND_RHS:%.*]], label [[FOR_END:%.*]]
1008 ; CHECK-NEXT: [[DOTMERGE:%.*]] = phi i16 [ [[TMP0:%.*]], [[LAND_RHS]] ], [ [[DOTOLD]], [[ENTRY:%.*]] ]
1009 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[DOTMERGE]], 0
1010 ; CHECK-NEXT: [[TMP0]] = load i16, i16* @global_pr49510, align 1
1011 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i16 [[TMP0]], 0
1012 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 [[TOBOOL]], i1 false
1013 ; CHECK-NEXT: br i1 [[OR_COND]], label [[LAND_RHS]], label [[FOR_END]]
1015 ; CHECK-NEXT: ret void
1021 %0 = load i16, i16* @global_pr49510, align 1
1022 %tobool = icmp ne i16 %0, 0
1023 br i1 %tobool, label %land.rhs, label %for.end
1026 %cmp = icmp slt i16 %0, 0
1027 br i1 %cmp, label %for.cond, label %for.end
1034 ; This is a miscompile if we replace a phi incoming value
1035 ; with an updated loaded value *after* it was stored.
1037 @global_pr51125 = global i32 1, align 4
1039 define i32 @pr51125() {
1040 ; CHECK-LABEL: @pr51125(
1041 ; CHECK-NEXT: entry:
1042 ; CHECK-NEXT: [[LD_OLD:%.*]] = load i32, i32* @global_pr51125, align 4
1043 ; CHECK-NEXT: [[ISZERO_OLD:%.*]] = icmp eq i32 [[LD_OLD]], 0
1044 ; CHECK-NEXT: br i1 [[ISZERO_OLD]], label [[EXIT:%.*]], label [[L2:%.*]]
1046 ; CHECK-NEXT: [[LD_MERGE:%.*]] = phi i32 [ [[LD:%.*]], [[L2]] ], [ [[LD_OLD]], [[ENTRY:%.*]] ]
1047 ; CHECK-NEXT: store i32 -1, i32* @global_pr51125, align 4
1048 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[LD_MERGE]], -1
1049 ; CHECK-NEXT: [[LD]] = load i32, i32* @global_pr51125, align 4
1050 ; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[LD]], 0
1051 ; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[CMP]], i1 true, i1 [[ISZERO]]
1052 ; CHECK-NEXT: br i1 [[OR_COND]], label [[EXIT]], label [[L2]]
1054 ; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[LD]], [[L2]] ], [ [[LD_OLD]], [[ENTRY]] ]
1055 ; CHECK-NEXT: ret i32 [[R]]
1061 %ld = load i32, i32* @global_pr51125, align 4
1062 %iszero = icmp eq i32 %ld, 0
1063 br i1 %iszero, label %exit, label %L2
1066 store i32 -1, i32* @global_pr51125, align 4
1067 %cmp = icmp eq i32 %ld, -1
1068 br i1 %cmp, label %L, label %exit
1071 %r = phi i32 [ %ld, %L2 ], [ %ld, %L ]
1075 attributes #0 = { nounwind argmemonly speculatable }