1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -simplifycfg < %s | FileCheck %s
6 declare void @use.i1(i1)
7 declare void @use.i32(i32)
9 define void @test_phi_simple(i1 %c) {
10 ; CHECK-LABEL: @test_phi_simple(
11 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
13 ; CHECK-NEXT: call void @foo()
14 ; CHECK-NEXT: call void @foo()
15 ; CHECK-NEXT: br label [[JOIN2:%.*]]
17 ; CHECK-NEXT: call void @bar()
18 ; CHECK-NEXT: call void @bar()
19 ; CHECK-NEXT: br label [[JOIN2]]
21 ; CHECK-NEXT: ret void
23 br i1 %c, label %if, label %else
34 %c2 = phi i1 [ true, %if ], [ false, %else ]
35 br i1 %c2, label %if2, label %else2
49 define void @test_phi_extra_use(i1 %c) {
50 ; CHECK-LABEL: @test_phi_extra_use(
51 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
53 ; CHECK-NEXT: call void @foo()
54 ; CHECK-NEXT: call void @use.i1(i1 true)
55 ; CHECK-NEXT: call void @foo()
56 ; CHECK-NEXT: br label [[JOIN2:%.*]]
58 ; CHECK-NEXT: call void @bar()
59 ; CHECK-NEXT: call void @use.i1(i1 false)
60 ; CHECK-NEXT: call void @bar()
61 ; CHECK-NEXT: br label [[JOIN2]]
63 ; CHECK-NEXT: ret void
65 br i1 %c, label %if, label %else
76 %c2 = phi i1 [ true, %if ], [ false, %else ]
77 call void @use.i1(i1 %c2)
78 br i1 %c2, label %if2, label %else2
92 define void @test_phi_extra_use_different_block(i1 %c) {
93 ; CHECK-LABEL: @test_phi_extra_use_different_block(
94 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
96 ; CHECK-NEXT: call void @foo()
97 ; CHECK-NEXT: br label [[JOIN:%.*]]
99 ; CHECK-NEXT: call void @bar()
100 ; CHECK-NEXT: br label [[JOIN]]
102 ; CHECK-NEXT: [[C2:%.*]] = phi i1 [ true, [[IF]] ], [ false, [[ELSE]] ]
103 ; CHECK-NEXT: br i1 [[C2]], label [[IF2:%.*]], label [[ELSE2:%.*]]
105 ; CHECK-NEXT: call void @use.i1(i1 [[C2]])
106 ; CHECK-NEXT: call void @foo()
107 ; CHECK-NEXT: br label [[JOIN2:%.*]]
109 ; CHECK-NEXT: call void @use.i1(i1 [[C2]])
110 ; CHECK-NEXT: call void @bar()
111 ; CHECK-NEXT: br label [[JOIN2]]
113 ; CHECK-NEXT: ret void
115 br i1 %c, label %if, label %else
126 %c2 = phi i1 [ true, %if ], [ false, %else ]
127 br i1 %c2, label %if2, label %else2
130 call void @use.i1(i1 %c2)
135 call void @use.i1(i1 %c2)
143 define void @test_same_cond_simple(i1 %c) {
144 ; CHECK-LABEL: @test_same_cond_simple(
145 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
147 ; CHECK-NEXT: call void @foo()
148 ; CHECK-NEXT: br label [[JOIN:%.*]]
150 ; CHECK-NEXT: call void @bar()
151 ; CHECK-NEXT: br label [[JOIN]]
153 ; CHECK-NEXT: br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]]
155 ; CHECK-NEXT: call void @foo()
156 ; CHECK-NEXT: br label [[JOIN2:%.*]]
158 ; CHECK-NEXT: call void @bar()
159 ; CHECK-NEXT: br label [[JOIN2]]
161 ; CHECK-NEXT: ret void
163 br i1 %c, label %if, label %else
174 br i1 %c, label %if2, label %else2
188 define void @test_same_cond_extra_use(i1 %c) {
189 ; CHECK-LABEL: @test_same_cond_extra_use(
190 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
192 ; CHECK-NEXT: call void @foo()
193 ; CHECK-NEXT: br label [[JOIN:%.*]]
195 ; CHECK-NEXT: call void @bar()
196 ; CHECK-NEXT: br label [[JOIN]]
198 ; CHECK-NEXT: call void @use.i1(i1 [[C]])
199 ; CHECK-NEXT: br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]]
201 ; CHECK-NEXT: call void @foo()
202 ; CHECK-NEXT: br label [[JOIN2:%.*]]
204 ; CHECK-NEXT: call void @bar()
205 ; CHECK-NEXT: br label [[JOIN2]]
207 ; CHECK-NEXT: ret void
209 br i1 %c, label %if, label %else
220 call void @use.i1(i1 %c)
221 br i1 %c, label %if2, label %else2
235 define void @test_same_cond_extra_use_different_block(i1 %c) {
236 ; CHECK-LABEL: @test_same_cond_extra_use_different_block(
237 ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
239 ; CHECK-NEXT: call void @foo()
240 ; CHECK-NEXT: br label [[JOIN:%.*]]
242 ; CHECK-NEXT: call void @bar()
243 ; CHECK-NEXT: br label [[JOIN]]
245 ; CHECK-NEXT: br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]]
247 ; CHECK-NEXT: call void @use.i1(i1 [[C]])
248 ; CHECK-NEXT: call void @foo()
249 ; CHECK-NEXT: br label [[JOIN2:%.*]]
251 ; CHECK-NEXT: call void @use.i1(i1 [[C]])
252 ; CHECK-NEXT: call void @bar()
253 ; CHECK-NEXT: br label [[JOIN2]]
255 ; CHECK-NEXT: ret void
257 br i1 %c, label %if, label %else
268 br i1 %c, label %if2, label %else2
271 call void @use.i1(i1 %c)
276 call void @use.i1(i1 %c)
284 define void @test_multiple_threadable_preds_with_phi(i1 %cond1, i1 %cond2) {
285 ; CHECK-LABEL: @test_multiple_threadable_preds_with_phi(
286 ; CHECK-NEXT: br i1 [[COND1:%.*]], label [[IF1:%.*]], label [[IF2:%.*]]
288 ; CHECK-NEXT: call void @foo()
289 ; CHECK-NEXT: br i1 [[COND2:%.*]], label [[IF3_CRITEDGE:%.*]], label [[EXIT:%.*]]
291 ; CHECK-NEXT: call void @bar()
292 ; CHECK-NEXT: br i1 [[COND2]], label [[IF3_CRITEDGE]], label [[EXIT]]
293 ; CHECK: if3.critedge:
294 ; CHECK-NEXT: [[PHI_PH:%.*]] = phi i32 [ 2, [[IF2]] ], [ 1, [[IF1]] ]
295 ; CHECK-NEXT: call void @use.i32(i32 [[PHI_PH]])
296 ; CHECK-NEXT: call void @foo()
297 ; CHECK-NEXT: br label [[EXIT]]
299 ; CHECK-NEXT: ret void
301 br i1 %cond1, label %if1, label %if2
305 br i1 %cond2, label %join, label %exit
309 br i1 %cond2, label %join, label %exit
312 %phi = phi i32 [ 1, %if1 ], [ 2, %if2 ]
313 call void @use.i32(i32 %phi)
314 br i1 %cond2, label %if3, label %exit
324 ; This test case used to infinite loop.
326 define void @infloop(i1 %cmp.a, i1 %cmp.b, i1 %cmp.c) {
327 ; CHECK-LABEL: @infloop(
329 ; CHECK-NEXT: br label [[WHILE_COND:%.*]]
331 ; CHECK-NEXT: br i1 [[CMP_A:%.*]], label [[FOR:%.*]], label [[WHILE_BODY_THREAD:%.*]]
333 ; CHECK-NEXT: br i1 [[CMP_B:%.*]], label [[WHILE_BODY:%.*]], label [[FOR_BODY:%.*]]
335 ; CHECK-NEXT: tail call void @foo()
336 ; CHECK-NEXT: br label [[FOR_BODY]]
338 ; CHECK-NEXT: br i1 [[CMP_C:%.*]], label [[C_EXIT:%.*]], label [[LAND:%.*]]
339 ; CHECK: while.body.thread:
340 ; CHECK-NEXT: br i1 [[CMP_C]], label [[WHILE_COND]], label [[LAND]]
342 ; CHECK-NEXT: tail call void @bar()
343 ; CHECK-NEXT: br label [[WHILE_COND]]
345 ; CHECK-NEXT: br i1 [[CMP_A]], label [[FOR_D:%.*]], label [[WHILE_BODY_THREAD]]
347 ; CHECK-NEXT: ret void
352 while.cond: ; preds = %land, %while.body.thread, %entry
353 br i1 %cmp.a, label %for, label %while.body.thread
355 for.body: ; preds = %for, %for.body
356 br i1 %cmp.b, label %while.body, label %for.body
358 for: ; preds = %while.cond
359 tail call void @foo()
362 while.body: ; preds = %for.body
363 br i1 %cmp.c, label %c.exit, label %land
365 while.body.thread: ; preds = %c.exit, %while.cond
366 br i1 %cmp.c, label %while.cond, label %land
368 land: ; preds = %while.body.thread, %while.body
369 tail call void @bar()
372 c.exit: ; preds = %while.body
373 br i1 %cmp.a, label %for.d, label %while.cond
375 for.d: ; preds = %c.exit
379 ; A combination of "branch to common dest" and jump threading kept peeling
380 ; off loop iterations here.
382 define void @infloop_pr56203(i1 %c1, i1 %c2) {
383 ; CHECK-LABEL: @infloop_pr56203(
385 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[EXIT:%.*]], label [[IF:%.*]]
387 ; CHECK-NEXT: call void @foo()
388 ; CHECK-NEXT: [[C3:%.*]] = icmp eq i64 0, 0
389 ; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[C2:%.*]], [[C3]]
390 ; CHECK-NEXT: br i1 [[OR_COND]], label [[EXIT]], label [[LOOP_SPLIT:%.*]]
392 ; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i64 0, 0
393 ; CHECK-NEXT: br i1 [[C3_OLD]], label [[EXIT]], label [[LOOP_SPLIT]]
395 ; CHECK-NEXT: br i1 [[C1]], label [[LOOP_LATCH:%.*]], label [[LOOP:%.*]]
397 ; CHECK-NEXT: call void @foo()
398 ; CHECK-NEXT: br label [[LOOP]]
400 ; CHECK-NEXT: ret void
403 br i1 %c1, label %exit, label %if
407 br i1 %c2, label %exit, label %loop
410 %c3 = icmp eq i64 0, 0
411 br i1 %c3, label %exit, label %loop.split
414 br i1 %c1, label %loop.latch, label %loop
424 define void @callbr() {
425 ; CHECK-LABEL: @callbr(
427 ; CHECK-NEXT: callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
428 ; CHECK-NEXT: to label [[IF_END:%.*]] [label %target]
430 ; CHECK-NEXT: br label [[IF_END]]
432 ; CHECK-NEXT: ret void
435 callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
436 to label %join [label %target]
442 %phi = phi i1 [ false, %target ], [ false, %entry ]
443 br i1 %phi, label %if.then, label %if.end