Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / SimplifyCFG / jump-threading.ll
blob50a32413a055130575d43de84e6823240c7f3306
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=simplifycfg < %s | FileCheck %s
4 declare void @foo()
5 declare void @bar()
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:%.*]]
12 ; CHECK:       if:
13 ; CHECK-NEXT:    call void @foo()
14 ; CHECK-NEXT:    call void @foo()
15 ; CHECK-NEXT:    br label [[JOIN2:%.*]]
16 ; CHECK:       else:
17 ; CHECK-NEXT:    call void @bar()
18 ; CHECK-NEXT:    call void @bar()
19 ; CHECK-NEXT:    br label [[JOIN2]]
20 ; CHECK:       join2:
21 ; CHECK-NEXT:    ret void
23   br i1 %c, label %if, label %else
25 if:
26   call void @foo()
27   br label %join
29 else:
30   call void @bar()
31   br label %join
33 join:
34   %c2 = phi i1 [ true, %if ], [ false, %else ]
35   br i1 %c2, label %if2, label %else2
37 if2:
38   call void @foo()
39   br label %join2
41 else2:
42   call void @bar()
43   br label %join2
45 join2:
46   ret void
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:%.*]]
52 ; CHECK:       if:
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:%.*]]
57 ; CHECK:       else:
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]]
62 ; CHECK:       join2:
63 ; CHECK-NEXT:    ret void
65   br i1 %c, label %if, label %else
67 if:
68   call void @foo()
69   br label %join
71 else:
72   call void @bar()
73   br label %join
75 join:
76   %c2 = phi i1 [ true, %if ], [ false, %else ]
77   call void @use.i1(i1 %c2)
78   br i1 %c2, label %if2, label %else2
80 if2:
81   call void @foo()
82   br label %join2
84 else2:
85   call void @bar()
86   br label %join2
88 join2:
89   ret void
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:%.*]]
95 ; CHECK:       if:
96 ; CHECK-NEXT:    call void @foo()
97 ; CHECK-NEXT:    br label [[JOIN:%.*]]
98 ; CHECK:       else:
99 ; CHECK-NEXT:    call void @bar()
100 ; CHECK-NEXT:    br label [[JOIN]]
101 ; CHECK:       join:
102 ; CHECK-NEXT:    [[C2:%.*]] = phi i1 [ true, [[IF]] ], [ false, [[ELSE]] ]
103 ; CHECK-NEXT:    br i1 [[C2]], label [[IF2:%.*]], label [[ELSE2:%.*]]
104 ; CHECK:       if2:
105 ; CHECK-NEXT:    call void @use.i1(i1 [[C2]])
106 ; CHECK-NEXT:    call void @foo()
107 ; CHECK-NEXT:    br label [[JOIN2:%.*]]
108 ; CHECK:       else2:
109 ; CHECK-NEXT:    call void @use.i1(i1 [[C2]])
110 ; CHECK-NEXT:    call void @bar()
111 ; CHECK-NEXT:    br label [[JOIN2]]
112 ; CHECK:       join2:
113 ; CHECK-NEXT:    ret void
115   br i1 %c, label %if, label %else
118   call void @foo()
119   br label %join
121 else:
122   call void @bar()
123   br label %join
125 join:
126   %c2 = phi i1 [ true, %if ], [ false, %else ]
127   br i1 %c2, label %if2, label %else2
129 if2:
130   call void @use.i1(i1 %c2)
131   call void @foo()
132   br label %join2
134 else2:
135   call void @use.i1(i1 %c2)
136   call void @bar()
137   br label %join2
139 join2:
140   ret void
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:%.*]]
146 ; CHECK:       if:
147 ; CHECK-NEXT:    call void @foo()
148 ; CHECK-NEXT:    br label [[JOIN:%.*]]
149 ; CHECK:       else:
150 ; CHECK-NEXT:    call void @bar()
151 ; CHECK-NEXT:    br label [[JOIN]]
152 ; CHECK:       join:
153 ; CHECK-NEXT:    br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]]
154 ; CHECK:       if2:
155 ; CHECK-NEXT:    call void @foo()
156 ; CHECK-NEXT:    br label [[JOIN2:%.*]]
157 ; CHECK:       else2:
158 ; CHECK-NEXT:    call void @bar()
159 ; CHECK-NEXT:    br label [[JOIN2]]
160 ; CHECK:       join2:
161 ; CHECK-NEXT:    ret void
163   br i1 %c, label %if, label %else
166   call void @foo()
167   br label %join
169 else:
170   call void @bar()
171   br label %join
173 join:
174   br i1 %c, label %if2, label %else2
176 if2:
177   call void @foo()
178   br label %join2
180 else2:
181   call void @bar()
182   br label %join2
184 join2:
185   ret void
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:%.*]]
191 ; CHECK:       if:
192 ; CHECK-NEXT:    call void @foo()
193 ; CHECK-NEXT:    br label [[JOIN:%.*]]
194 ; CHECK:       else:
195 ; CHECK-NEXT:    call void @bar()
196 ; CHECK-NEXT:    br label [[JOIN]]
197 ; CHECK:       join:
198 ; CHECK-NEXT:    call void @use.i1(i1 [[C]])
199 ; CHECK-NEXT:    br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]]
200 ; CHECK:       if2:
201 ; CHECK-NEXT:    call void @foo()
202 ; CHECK-NEXT:    br label [[JOIN2:%.*]]
203 ; CHECK:       else2:
204 ; CHECK-NEXT:    call void @bar()
205 ; CHECK-NEXT:    br label [[JOIN2]]
206 ; CHECK:       join2:
207 ; CHECK-NEXT:    ret void
209   br i1 %c, label %if, label %else
212   call void @foo()
213   br label %join
215 else:
216   call void @bar()
217   br label %join
219 join:
220   call void @use.i1(i1 %c)
221   br i1 %c, label %if2, label %else2
223 if2:
224   call void @foo()
225   br label %join2
227 else2:
228   call void @bar()
229   br label %join2
231 join2:
232   ret void
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:%.*]]
238 ; CHECK:       if:
239 ; CHECK-NEXT:    call void @foo()
240 ; CHECK-NEXT:    br label [[JOIN:%.*]]
241 ; CHECK:       else:
242 ; CHECK-NEXT:    call void @bar()
243 ; CHECK-NEXT:    br label [[JOIN]]
244 ; CHECK:       join:
245 ; CHECK-NEXT:    br i1 [[C]], label [[IF2:%.*]], label [[ELSE2:%.*]]
246 ; CHECK:       if2:
247 ; CHECK-NEXT:    call void @use.i1(i1 [[C]])
248 ; CHECK-NEXT:    call void @foo()
249 ; CHECK-NEXT:    br label [[JOIN2:%.*]]
250 ; CHECK:       else2:
251 ; CHECK-NEXT:    call void @use.i1(i1 [[C]])
252 ; CHECK-NEXT:    call void @bar()
253 ; CHECK-NEXT:    br label [[JOIN2]]
254 ; CHECK:       join2:
255 ; CHECK-NEXT:    ret void
257   br i1 %c, label %if, label %else
260   call void @foo()
261   br label %join
263 else:
264   call void @bar()
265   br label %join
267 join:
268   br i1 %c, label %if2, label %else2
270 if2:
271   call void @use.i1(i1 %c)
272   call void @foo()
273   br label %join2
275 else2:
276   call void @use.i1(i1 %c)
277   call void @bar()
278   br label %join2
280 join2:
281   ret void
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:%.*]]
287 ; CHECK:       if1:
288 ; CHECK-NEXT:    call void @foo()
289 ; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[IF3_CRITEDGE:%.*]], label [[EXIT:%.*]]
290 ; CHECK:       if2:
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]]
298 ; CHECK:       exit:
299 ; CHECK-NEXT:    ret void
301   br i1 %cond1, label %if1, label %if2
303 if1:
304   call void @foo()
305   br i1 %cond2, label %join, label %exit
307 if2:
308   call void @bar()
309   br i1 %cond2, label %join, label %exit
311 join:
312   %phi = phi i32 [ 1, %if1 ], [ 2, %if2 ]
313   call void @use.i32(i32 %phi)
314   br i1 %cond2, label %if3, label %exit
316 if3:
317   call void @foo()
318   br label %exit
320 exit:
321   ret void
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(
328 ; CHECK-NEXT:  entry:
329 ; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
330 ; CHECK:       while.cond:
331 ; CHECK-NEXT:    br i1 [[CMP_A:%.*]], label [[FOR:%.*]], label [[WHILE_BODY_THREAD:%.*]]
332 ; CHECK:       for.body:
333 ; CHECK-NEXT:    br i1 [[CMP_B:%.*]], label [[WHILE_BODY:%.*]], label [[FOR_BODY:%.*]]
334 ; CHECK:       for:
335 ; CHECK-NEXT:    tail call void @foo()
336 ; CHECK-NEXT:    br label [[FOR_BODY]]
337 ; CHECK:       while.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]]
341 ; CHECK:       land:
342 ; CHECK-NEXT:    tail call void @bar()
343 ; CHECK-NEXT:    br label [[WHILE_COND]]
344 ; CHECK:       c.exit:
345 ; CHECK-NEXT:    br i1 [[CMP_A]], label [[FOR_D:%.*]], label [[WHILE_BODY_THREAD]]
346 ; CHECK:       for.d:
347 ; CHECK-NEXT:    ret void
349 entry:
350   br label %while.cond
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()
360   br label %for.body
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()
370   br label %while.cond
372 c.exit:                                           ; preds = %while.body
373   br i1 %cmp.a, label %for.d, label %while.cond
375 for.d:                                            ; preds = %c.exit
376   ret void
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(
384 ; CHECK-NEXT:  entry:
385 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[EXIT:%.*]], label [[IF:%.*]]
386 ; CHECK:       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:%.*]]
391 ; CHECK:       loop:
392 ; CHECK-NEXT:    [[C3_OLD:%.*]] = icmp eq i64 0, 0
393 ; CHECK-NEXT:    br i1 [[C3_OLD]], label [[EXIT]], label [[LOOP_SPLIT]]
394 ; CHECK:       loop.split:
395 ; CHECK-NEXT:    br i1 [[C1]], label [[LOOP_LATCH:%.*]], label [[LOOP:%.*]]
396 ; CHECK:       loop.latch:
397 ; CHECK-NEXT:    call void @foo()
398 ; CHECK-NEXT:    br label [[LOOP]]
399 ; CHECK:       exit:
400 ; CHECK-NEXT:    ret void
402 entry:
403   br i1 %c1, label %exit, label %if
406   call void @foo()
407   br i1 %c2, label %exit, label %loop
409 loop:
410   %c3 = icmp eq i64 0, 0
411   br i1 %c3, label %exit, label %loop.split
413 loop.split:
414   br i1 %c1, label %loop.latch, label %loop
416 loop.latch:
417   call void @foo()
418   br label %loop
420 exit:
421   ret void
424 define void @callbr() {
425 ; CHECK-LABEL: @callbr(
426 ; CHECK-NEXT:  entry:
427 ; CHECK-NEXT:    callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
428 ; CHECK-NEXT:            to label [[IF_END:%.*]] [label %if.end]
429 ; CHECK:       if.end:
430 ; CHECK-NEXT:    ret void
432 entry:
433   callbr void asm sideeffect "", "!i,~{dirflag},~{fpsr},~{flags}"()
434   to label %join [label %target]
436 target:
437   br label %join
439 join:
440   %phi = phi i1 [ false, %target ], [ false, %entry ]
441   br i1 %phi, label %if.then, label %if.end
443 if.then:
444   call void @foo()
445   br label %if.end
447 if.end:
448   ret void