[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / SimplifyCFG / fold-branch-to-common-dest.ll
blob2ff04182607716d5a6f6e2eb4bc359c3d36eb5b1
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()
7 declare void @use8(i8)
8 declare i1 @gen1()
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(
15 ; CHECK-NEXT:  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:%.*]]
20 ; CHECK:       common.ret:
21 ; CHECK-NEXT:    ret void
22 ; CHECK:       final_left:
23 ; CHECK-NEXT:    call void @sideeffect0()
24 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
25 ; CHECK:       final_right:
26 ; CHECK-NEXT:    call void @sideeffect1()
27 ; CHECK-NEXT:    br label [[COMMON_RET]]
29 pred:
30   %c0 = icmp eq i8 %v0, 0
31   br i1 %c0, label %dispatch, label %final_right
32 dispatch:
33   %c1 = icmp eq i8 %v1, 0
34   br i1 %c1, label %final_left, label %final_right
35 final_left:
36   call void @sideeffect0()
37   ret void
38 final_right:
39   call void @sideeffect1()
40   ret void
43 define void @two_preds(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
44 ; CHECK-LABEL: @two_preds(
45 ; CHECK-NEXT:  entry:
46 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
47 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
48 ; CHECK:       pred0:
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:%.*]]
53 ; CHECK:       pred1:
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]]
58 ; CHECK:       common.ret:
59 ; CHECK-NEXT:    ret void
60 ; CHECK:       final_left:
61 ; CHECK-NEXT:    call void @sideeffect0()
62 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
63 ; CHECK:       final_right:
64 ; CHECK-NEXT:    call void @sideeffect1()
65 ; CHECK-NEXT:    br label [[COMMON_RET]]
67 entry:
68   %c0 = icmp eq i8 %v0, 0
69   br i1 %c0, label %pred0, label %pred1
70 pred0:
71   %c1 = icmp eq i8 %v1, 0
72   br i1 %c1, label %final_left, label %dispatch
73 pred1:
74   %c2 = icmp eq i8 %v2, 0
75   br i1 %c2, label %dispatch, label %final_right
76 dispatch:
77   %c3 = icmp eq i8 %v3, 0
78   br i1 %c3, label %final_left, label %final_right
79 final_left:
80   call void @sideeffect0()
81   ret void
82 final_right:
83   call void @sideeffect1()
84   ret void
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(
91 ; CHECK-NEXT:  pred:
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:%.*]]
97 ; CHECK:       common.ret:
98 ; CHECK-NEXT:    ret void
99 ; CHECK:       final_left:
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]]
106 pred:
107   %c0 = icmp eq i8 %v0, 0
108   br i1 %c0, label %dispatch, label %final_right
109 dispatch:
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
113 final_left:
114   call void @sideeffect0()
115   ret void
116 final_right:
117   call void @sideeffect1()
118   ret void
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(
126 ; CHECK-NEXT:  pred:
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:%.*]]
132 ; CHECK:       common.ret:
133 ; CHECK-NEXT:    ret void
134 ; CHECK:       final_right:
135 ; CHECK-NEXT:    call void @sideeffect0()
136 ; CHECK-NEXT:    br label [[COMMON_RET]]
138 pred:
139   %c0 = icmp ne i32* %p, null
140   br i1 %c0, label %dispatch, label %final_right
142 dispatch:
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
147 final_left:
148   ret void
150 final_right:
151   call void @sideeffect0()
152   ret void
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(
158 ; CHECK-NEXT:  pred:
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:%.*]]
164 ; CHECK:       common.ret:
165 ; CHECK-NEXT:    ret void
166 ; CHECK:       final_right:
167 ; CHECK-NEXT:    call void @sideeffect0()
168 ; CHECK-NEXT:    br label [[COMMON_RET]]
170 pred:
171   %c0 = icmp ne i32* %p, null
172   br i1 %c0, label %dispatch, label %final_right
174 dispatch:
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
179 final_left:
180   ret void
182 final_right:
183   call void @sideeffect0()
184   ret void
187 define void @two_preds_with_extra_op(i8 %v0, i8 %v1, i8 %v2, i8 %v3) {
188 ; CHECK-LABEL: @two_preds_with_extra_op(
189 ; CHECK-NEXT:  entry:
190 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
191 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
192 ; CHECK:       pred0:
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:%.*]]
198 ; CHECK:       pred1:
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]]
204 ; CHECK:       common.ret:
205 ; CHECK-NEXT:    ret void
206 ; CHECK:       final_left:
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]]
213 entry:
214   %c0 = icmp eq i8 %v0, 0
215   br i1 %c0, label %pred0, label %pred1
216 pred0:
217   %c1 = icmp eq i8 %v1, 0
218   br i1 %c1, label %final_left, label %dispatch
219 pred1:
220   %c2 = icmp eq i8 %v2, 0
221   br i1 %c2, label %dispatch, label %final_right
222 dispatch:
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
226 final_left:
227   call void @sideeffect0()
228   ret void
229 final_right:
230   call void @sideeffect1()
231   ret void
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(
238 ; CHECK-NEXT:  pred:
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:%.*]]
245 ; CHECK:       common.ret:
246 ; CHECK-NEXT:    ret void
247 ; CHECK:       final_left:
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]]
254 pred:
255   %c0 = icmp eq i8 %v0, 0
256   br i1 %c0, label %dispatch, label %final_right
257 dispatch:
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
262 final_left:
263   call void @sideeffect0()
264   ret void
265 final_right:
266   call void @sideeffect1()
267   ret void
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(
272 ; CHECK-NEXT:  entry:
273 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
274 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
275 ; CHECK:       pred0:
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:%.*]]
282 ; CHECK:       pred1:
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]]
289 ; CHECK:       common.ret:
290 ; CHECK-NEXT:    ret void
291 ; CHECK:       final_left:
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]]
298 entry:
299   %c0 = icmp eq i8 %v0, 0
300   br i1 %c0, label %pred0, label %pred1
301 pred0:
302   %c1 = icmp eq i8 %v1, 0
303   br i1 %c1, label %final_left, label %dispatch
304 pred1:
305   %c2 = icmp eq i8 %v2, 0
306   br i1 %c2, label %dispatch, label %final_right
307 dispatch:
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
312 final_left:
313   call void @sideeffect0()
314   ret void
315 final_right:
316   call void @sideeffect1()
317   ret void
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(
325 ; CHECK-NEXT:  pred:
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:%.*]]
331 ; CHECK:       common.ret:
332 ; CHECK-NEXT:    ret void
333 ; CHECK:       final_left:
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]]
341 pred:
342   %c0 = icmp eq i8 %v0, 0
343   br i1 %c0, label %dispatch, label %final_right
344 dispatch:
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
348 final_left:
349   call void @sideeffect0()
350   call void @use8(i8 %v1_adj)
351   ret void
352 final_right:
353   call void @sideeffect1()
354   ret void
356 define void @one_pred_with_extra_op_liveout_multiuse(i8 %v0, i8 %v1) {
357 ; CHECK-LABEL: @one_pred_with_extra_op_liveout_multiuse(
358 ; CHECK-NEXT:  pred:
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:%.*]]
364 ; CHECK:       common.ret:
365 ; CHECK-NEXT:    ret void
366 ; CHECK:       final_left:
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]]
375 pred:
376   %c0 = icmp eq i8 %v0, 0
377   br i1 %c0, label %dispatch, label %final_right
378 dispatch:
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
382 final_left:
383   call void @sideeffect0()
384   call void @use8(i8 %v1_adj)
385   call void @use8(i8 %v1_adj)
386   ret void
387 final_right:
388   call void @sideeffect1()
389   ret void
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(
394 ; CHECK-NEXT:  entry:
395 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
396 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED:%.*]], label [[LEFT_END:%.*]]
397 ; CHECK:       pred:
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:%.*]]
403 ; CHECK:       final_left:
404 ; CHECK-NEXT:    call void @sideeffect0()
405 ; CHECK-NEXT:    call void @use8(i8 [[V2_ADJ]])
406 ; CHECK-NEXT:    br label [[LEFT_END]]
407 ; CHECK:       common.ret:
408 ; CHECK-NEXT:    ret void
409 ; CHECK:       left_end:
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]]
418 entry:
419   %c0 = icmp eq i8 %v0, 0
420   br i1 %c0, label %pred, label %left_end
421 pred:
422   %c1 = icmp eq i8 %v1, 0
423   br i1 %c1, label %dispatch, label %final_right
424 dispatch:
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
428 final_left:
429   call void @sideeffect0()
430   call void @use8(i8 %v2_adj)
431   br label %left_end
432 left_end:
433   %merge_left = phi i8 [ %v2_adj, %final_left ], [ 0, %entry ]
434   call void @sideeffect1()
435   call void @use8(i8 %merge_left)
436   ret void
437 final_right:
438   call void @sideeffect2()
439   ret void
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(
444 ; CHECK-NEXT:  entry:
445 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
446 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
447 ; CHECK:       pred0:
448 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
449 ; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
450 ; CHECK:       pred1:
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:%.*]]
456 ; CHECK:       dispatch:
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]]
460 ; CHECK:       common.ret:
461 ; CHECK-NEXT:    ret void
462 ; CHECK:       final_left:
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]]
471 entry:
472   %c0 = icmp eq i8 %v0, 0
473   br i1 %c0, label %pred0, label %pred1
474 pred0:
475   %c1 = icmp eq i8 %v1, 0
476   br i1 %c1, label %final_left, label %dispatch
477 pred1:
478   %c2 = icmp eq i8 %v2, 0
479   br i1 %c2, label %dispatch, label %final_right
480 dispatch:
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
484 final_left:
485   %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
486   call void @use8(i8 %merge_left)
487   call void @sideeffect0()
488   ret void
489 final_right:
490   call void @sideeffect1()
491   ret void
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(
496 ; CHECK-NEXT:  entry:
497 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
498 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
499 ; CHECK:       pred0:
500 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
501 ; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
502 ; CHECK:       pred1:
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:%.*]]
508 ; CHECK:       dispatch:
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]]
512 ; CHECK:       common.ret:
513 ; CHECK-NEXT:    ret void
514 ; CHECK:       final_left:
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]]
525 entry:
526   %c0 = icmp eq i8 %v0, 0
527   br i1 %c0, label %pred0, label %pred1
528 pred0:
529   %c1 = icmp eq i8 %v1, 0
530   br i1 %c1, label %final_left, label %dispatch
531 pred1:
532   %c2 = icmp eq i8 %v2, 0
533   br i1 %c2, label %dispatch, label %final_right
534 dispatch:
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
538 final_left:
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()
544   ret void
545 final_right:
546   call void @sideeffect1()
547   ret void
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(
555 ; CHECK-NEXT:  pred:
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:%.*]]
561 ; CHECK:       common.ret:
562 ; CHECK-NEXT:    ret void
563 ; CHECK:       final_left:
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]]
571 pred:
572   %c0 = icmp eq i8 %v0, 0
573   br i1 %c0, label %dispatch, label %final_right
574 dispatch:
575   %v1_adj = add i8 %v0, %v1
576   %c1 = icmp eq i8 %v1, 0
577   br i1 %c1, label %final_left, label %final_right
578 final_left:
579   call void @sideeffect0()
580   call void @use8(i8 %v1_adj)
581   ret void
582 final_right:
583   call void @sideeffect1()
584   ret void
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(
588 ; CHECK-NEXT:  pred:
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:%.*]]
594 ; CHECK:       common.ret:
595 ; CHECK-NEXT:    ret void
596 ; CHECK:       final_left:
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]]
605 pred:
606   %c0 = icmp eq i8 %v0, 0
607   br i1 %c0, label %dispatch, label %final_right
608 dispatch:
609   %v1_adj = add i8 %v0, %v1
610   %c1 = icmp eq i8 %v1, 0
611   br i1 %c1, label %final_left, label %final_right
612 final_left:
613   call void @sideeffect0()
614   call void @use8(i8 %v1_adj)
615   call void @use8(i8 %v1_adj)
616   ret void
617 final_right:
618   call void @sideeffect1()
619   ret void
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(
624 ; CHECK-NEXT:  entry:
625 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
626 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
627 ; CHECK:       pred0:
628 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
629 ; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
630 ; CHECK:       pred1:
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:%.*]]
636 ; CHECK:       dispatch:
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]]
640 ; CHECK:       common.ret:
641 ; CHECK-NEXT:    ret void
642 ; CHECK:       final_left:
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]]
651 entry:
652   %c0 = icmp eq i8 %v0, 0
653   br i1 %c0, label %pred0, label %pred1
654 pred0:
655   %c1 = icmp eq i8 %v1, 0
656   br i1 %c1, label %final_left, label %dispatch
657 pred1:
658   %c2 = icmp eq i8 %v2, 0
659   br i1 %c2, label %dispatch, label %final_right
660 dispatch:
661   %v3_adj = add i8 %v1, %v2
662   %c3 = icmp eq i8 %v3, 0
663   br i1 %c3, label %final_left, label %final_right
664 final_left:
665   %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
666   call void @use8(i8 %merge_left)
667   call void @sideeffect0()
668   ret void
669 final_right:
670   call void @sideeffect1()
671   ret void
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(
676 ; CHECK-NEXT:  entry:
677 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
678 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
679 ; CHECK:       pred0:
680 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
681 ; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
682 ; CHECK:       pred1:
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:%.*]]
688 ; CHECK:       dispatch:
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]]
692 ; CHECK:       common.ret:
693 ; CHECK-NEXT:    ret void
694 ; CHECK:       final_left:
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]]
705 entry:
706   %c0 = icmp eq i8 %v0, 0
707   br i1 %c0, label %pred0, label %pred1
708 pred0:
709   %c1 = icmp eq i8 %v1, 0
710   br i1 %c1, label %final_left, label %dispatch
711 pred1:
712   %c2 = icmp eq i8 %v2, 0
713   br i1 %c2, label %dispatch, label %final_right
714 dispatch:
715   %v3_adj = add i8 %v1, %v2
716   %c3 = icmp eq i8 %v3, 0
717   br i1 %c3, label %final_left, label %final_right
718 final_left:
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()
724   ret void
725 final_right:
726   call void @sideeffect1()
727   ret void
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(
733 ; CHECK-NEXT:  entry:
734 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
735 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED:%.*]], label [[LEFT_END:%.*]]
736 ; CHECK:       pred:
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:%.*]]
742 ; CHECK:       final_left:
743 ; CHECK-NEXT:    call void @sideeffect0()
744 ; CHECK-NEXT:    call void @use8(i8 [[V2_ADJ]])
745 ; CHECK-NEXT:    br label [[LEFT_END]]
746 ; CHECK:       common.ret:
747 ; CHECK-NEXT:    ret void
748 ; CHECK:       left_end:
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]]
757 entry:
758   %c0 = icmp eq i8 %v0, 0
759   br i1 %c0, label %pred, label %left_end
760 pred:
761   %c1 = icmp eq i8 %v1, 0
762   br i1 %c1, label %dispatch, label %final_right
763 dispatch:
764   %c3 = icmp eq i8 %v3, 0
765   %v2_adj = add i8 %v4, %v5
766   br i1 %c3, label %final_left, label %final_right
767 final_left:
768   call void @sideeffect0()
769   call void @use8(i8 %v2_adj)
770   br label %left_end
771 left_end:
772   %merge_left = phi i8 [ %v2_adj, %final_left ], [ 0, %entry ]
773   call void @sideeffect1()
774   call void @use8(i8 %merge_left)
775   ret void
776 final_right:
777   call void @sideeffect2()
778   ret void
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(
782 ; CHECK-NEXT:  entry:
783 ; CHECK-NEXT:    [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
784 ; CHECK-NEXT:    br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
785 ; CHECK:       pred0:
786 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
787 ; CHECK-NEXT:    br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
788 ; CHECK:       pred1:
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:%.*]]
794 ; CHECK:       dispatch:
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]]
798 ; CHECK:       common.ret:
799 ; CHECK-NEXT:    ret void
800 ; CHECK:       final_left:
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]]
809 entry:
810   %c0 = icmp eq i8 %v0, 0
811   br i1 %c0, label %pred0, label %pred1
812 pred0:
813   %c1 = icmp eq i8 %v1, 0
814   br i1 %c1, label %final_left, label %dispatch
815 pred1:
816   %c2 = icmp eq i8 %v2, 0
817   br i1 %c2, label %dispatch, label %final_right
818 dispatch:
819   %c3 = icmp eq i8 %v3, 0
820   %v3_adj = add i8 %v4, %v5
821   br i1 %c3, label %final_left, label %final_right
822 final_left:
823   %merge_left = phi i8 [ %v3_adj, %dispatch ], [ 0, %pred0 ]
824   call void @use8(i8 %merge_left)
825   call void @sideeffect0()
826   ret void
827 final_right:
828   call void @sideeffect1()
829   ret void
832 define void @pr48450() {
833 ; CHECK-LABEL: @pr48450(
834 ; CHECK-NEXT:  entry:
835 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
836 ; CHECK:       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:%.*]]
840 ; CHECK:       for.inc:
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]]
844 ; CHECK:       if.then:
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
858 entry:
859   br label %for.body
861 for.body:
862   %countdown = phi i8 [ 8, %entry ], [ %dec, %for.bodythread-pre-split ]
863   %c = call i1 @gen1()
864   br i1 %c, label %for.inc, label %if.then
866 for.inc:
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
871 if.then:
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()
877   br label %for.body
879 if.end.loopexit:
880   ret void
883 define void @pr48450_2(i1 %enable_loopback) {
884 ; CHECK-LABEL: @pr48450_2(
885 ; CHECK-NEXT:  entry:
886 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
887 ; CHECK:       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:%.*]]
891 ; CHECK:       for.inc:
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]]
895 ; CHECK:       if.then:
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
914 entry:
915   br label %for.body
917 for.body:
918   %countdown = phi i8 [ 8, %entry ], [ %dec, %for.bodythread-pre-split ]
919   %c = call i1 @gen1()
920   br i1 %c, label %for.inc, label %if.then
922 for.inc:
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
927 if.then:
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
941 if.end.loopexit:
942   ret void
945 @f.b = external global i8, align 1
946 define void @pr48450_3() {
947 ; CHECK-LABEL: @pr48450_3(
948 ; CHECK-NEXT:  entry:
949 ; CHECK-NEXT:    br label [[FOR_COND1:%.*]]
950 ; CHECK:       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]]
956 entry:
957   br label %for.cond1
959 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
964 for.body:
965   br label %for.cond1
967 for.end:
968   %tobool = icmp ne i8 %v, 0
969   br i1 %tobool, label %if.then, label %if.end
971 if.then:
972   unreachable
974 if.end:
975   br label %for.cond2
977 for.cond2:
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
982 for.cond.cleanup:
983   br label %cleanup
985 for.body4:
986   br i1 undef, label %if.then6, label %if.end7
988 if.then6:
989   br label %cleanup
991 if.end7:
992   %inc = add nsw i8 %c.0, 1
993   br label %for.cond2
995 cleanup:
996   unreachable
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:%.*]]
1007 ; CHECK:       land.rhs:
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]]
1014 ; CHECK:       for.end:
1015 ; CHECK-NEXT:    ret void
1017 entry:
1018   br label %for.cond
1020 for.cond:
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
1025 land.rhs:
1026   %cmp = icmp slt i16 %0, 0
1027   br i1 %cmp, label %for.cond, label %for.end
1029 for.end:
1030   ret void
1033 ; FIXME:
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:%.*]]
1045 ; CHECK:       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]]
1053 ; CHECK:       exit:
1054 ; CHECK-NEXT:    [[R:%.*]] = phi i32 [ [[LD]], [[L2]] ], [ [[LD_OLD]], [[ENTRY]] ]
1055 ; CHECK-NEXT:    ret i32 [[R]]
1057 entry:
1058   br label %L
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
1070 exit:
1071   %r = phi i32 [ %ld, %L2 ], [ %ld, %L ]
1072   ret i32 %r
1075 attributes #0 = { nounwind argmemonly speculatable }