Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstCombine / sink_to_unreachable.ll
blob02ed22217854ea4cdff5c4e212d91eaa8f39b023
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=instcombine -S < %s | FileCheck %s
4 declare void @use(i32 %x)
5 declare i1 @cond()
7 define void @test_01(i32 %x, i32 %y) {
8 ; CHECK-LABEL: @test_01(
9 ; CHECK-NEXT:  entry:
10 ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
11 ; CHECK-NEXT:    br i1 [[C2]], label [[EXIT:%.*]], label [[UNREACHED:%.*]]
12 ; CHECK:       unreached:
13 ; CHECK-NEXT:    [[C1:%.*]] = icmp ne i32 [[X]], [[Y]]
14 ; CHECK-NEXT:    [[COMPARATOR:%.*]] = zext i1 [[C1]] to i32
15 ; CHECK-NEXT:    call void @use(i32 [[COMPARATOR]])
16 ; CHECK-NEXT:    unreachable
17 ; CHECK:       exit:
18 ; CHECK-NEXT:    ret void
20 entry:
21   %c1 = icmp eq i32 %x, %y
22   %c2 = icmp slt i32 %x, %y
23   %signed = select i1 %c2, i32 -1, i32 1
24   %comparator = select i1 %c1, i32 0, i32 %signed
25   br i1 %c2, label %exit, label %unreached
27 unreached:
28   call void @use(i32 %comparator)
29   unreachable
31 exit:
32   ret void
36 define void @test_02(i32 %x, i32 %y) {
37 ; CHECK-LABEL: @test_02(
38 ; CHECK-NEXT:  entry:
39 ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
40 ; CHECK-NEXT:    br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]
41 ; CHECK:       medium:
42 ; CHECK-NEXT:    [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]
43 ; CHECK-NEXT:    br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]]
44 ; CHECK:       unreached:
45 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i32 [[X]], [[Y]]
46 ; CHECK-NEXT:    [[SIGNED:%.*]] = select i1 [[C2]], i32 -1, i32 1
47 ; CHECK-NEXT:    [[COMPARATOR:%.*]] = select i1 [[C1]], i32 0, i32 [[SIGNED]]
48 ; CHECK-NEXT:    call void @use(i32 [[COMPARATOR]])
49 ; CHECK-NEXT:    unreachable
50 ; CHECK:       exit:
51 ; CHECK-NEXT:    ret void
53 entry:
54   %c1 = icmp eq i32 %x, %y
55   %c2 = icmp slt i32 %x, %y
56   %signed = select i1 %c2, i32 -1, i32 1
57   %comparator = select i1 %c1, i32 0, i32 %signed
58   br i1 %c2, label %exit, label %medium
60 medium:
61   %c3 = icmp sgt i32 %x, %y
62   br i1 %c3, label %exit, label %unreached
64 unreached:
65   call void @use(i32 %comparator)
66   unreachable
68 exit:
69   ret void
72 define i32 @test_03(i32 %x, i32 %y) {
73 ; CHECK-LABEL: @test_03(
74 ; CHECK-NEXT:  entry:
75 ; CHECK-NEXT:    [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
76 ; CHECK-NEXT:    br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]
77 ; CHECK:       medium:
78 ; CHECK-NEXT:    [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]
79 ; CHECK-NEXT:    br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]]
80 ; CHECK:       unreached:
81 ; CHECK-NEXT:    [[C1:%.*]] = icmp eq i32 [[X]], [[Y]]
82 ; CHECK-NEXT:    [[SIGNED:%.*]] = select i1 [[C2]], i32 -1, i32 1
83 ; CHECK-NEXT:    [[COMPARATOR:%.*]] = select i1 [[C1]], i32 0, i32 [[SIGNED]]
84 ; CHECK-NEXT:    ret i32 [[COMPARATOR]]
85 ; CHECK:       exit:
86 ; CHECK-NEXT:    ret i32 0
88 entry:
89   %c1 = icmp eq i32 %x, %y
90   %c2 = icmp slt i32 %x, %y
91   %signed = select i1 %c2, i32 -1, i32 1
92   %comparator = select i1 %c1, i32 0, i32 %signed
93   br i1 %c2, label %exit, label %medium
95 medium:
96   %c3 = icmp sgt i32 %x, %y
97   br i1 %c3, label %exit, label %unreached
99 unreached:
100   ret i32 %comparator
102 exit:
103   ret i32 0
106 define i32 @test_04(i32 %x, i1 %c) {
107 ; CHECK-LABEL: @test_04(
108 ; CHECK-NEXT:  bb0:
109 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
110 ; CHECK:       bb1:
111 ; CHECK-NEXT:    br label [[BB3:%.*]]
112 ; CHECK:       bb2:
113 ; CHECK-NEXT:    br label [[BB3]]
114 ; CHECK:       bb3:
115 ; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[BB1]] ], [ 1, [[BB2]] ]
116 ; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], 1
117 ; CHECK-NEXT:    [[R:%.*]] = add i32 [[P]], [[A]]
118 ; CHECK-NEXT:    ret i32 [[R]]
120 bb0:
121   %a = add i32 %x, 1
122   br i1 %c, label %bb1, label %bb2
123 bb1:
124   br label %bb3
125 bb2:
126   br label %bb3
127 bb3:
128   %p = phi i32 [0, %bb1], [1, %bb2]
129   %r = add i32 %p, %a
130   ret i32 %r
133 ; Do not sink into a potentially hotter block.
134 define i32 @test_05_neg(i32 %x, i1 %cond) {
135 ; CHECK-LABEL: @test_05_neg(
136 ; CHECK-NEXT:  bb0:
137 ; CHECK-NEXT:    [[A:%.*]] = add i32 [[X:%.*]], 1
138 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
139 ; CHECK:       bb1:
140 ; CHECK-NEXT:    br label [[BB3:%.*]]
141 ; CHECK:       bb2:
142 ; CHECK-NEXT:    [[CALL:%.*]] = call i1 @cond()
143 ; CHECK-NEXT:    br i1 [[CALL]], label [[BB2]], label [[BB3]]
144 ; CHECK:       bb3:
145 ; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[BB1]] ], [ [[A]], [[BB2]] ]
146 ; CHECK-NEXT:    ret i32 [[P]]
148 bb0:
149   %a = add i32 %x, 1
150   br i1 %cond, label %bb1, label %bb2
151 bb1:
152   br label %bb3
153 bb2:
154   %call = call i1 @cond()
155   br i1 %call, label %bb2, label %bb3
156 bb3:
157   %p = phi i32 [0, %bb1], [%a, %bb2]
158   ret i32 %p
161 define i1 @sink_to_unreachable_ret(i16 %X)  {
162 ; CHECK-LABEL: @sink_to_unreachable_ret(
163 ; CHECK-NEXT:  entry:
164 ; CHECK-NEXT:    br label [[LOOP:%.*]]
165 ; CHECK:       loop:
166 ; CHECK-NEXT:    br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
167 ; CHECK:       unreach:
168 ; CHECK-NEXT:    ret i1 poison
170 entry:
171   br label %loop
173 loop:
174   %p = icmp sgt i16 %X, 16
175   br i1 true, label %loop, label %unreach
177 unreach:
178   ret i1 %p
181 define void @sink_to_unreachable_condbr(i16 %X)  {
182 ; CHECK-LABEL: @sink_to_unreachable_condbr(
183 ; CHECK-NEXT:  entry:
184 ; CHECK-NEXT:    br label [[LOOP:%.*]]
185 ; CHECK:       loop:
186 ; CHECK-NEXT:    br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
187 ; CHECK:       unreach:
188 ; CHECK-NEXT:    br i1 poison, label [[DUMMY:%.*]], label [[LOOP]]
189 ; CHECK:       dummy:
190 ; CHECK-NEXT:    unreachable
192 entry:
193   br label %loop
195 loop:
196   %p = icmp sgt i16 %X, 16
197   br i1 true, label %loop, label %unreach
199 unreach:
200   br i1 %p, label %dummy, label %loop
202 dummy:
203   unreachable
206 define void @sink_to_unreachable_switch(i16 %X)  {
207 ; CHECK-LABEL: @sink_to_unreachable_switch(
208 ; CHECK-NEXT:  entry:
209 ; CHECK-NEXT:    br label [[LOOP:%.*]]
210 ; CHECK:       loop:
211 ; CHECK-NEXT:    br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
212 ; CHECK:       unreach:
213 ; CHECK-NEXT:    switch i16 poison, label [[UNREACH_RET:%.*]] [
214 ; CHECK-NEXT:    ]
215 ; CHECK:       unreach.ret:
216 ; CHECK-NEXT:    unreachable
218 entry:
219   br label %loop
221 loop:
222   %quantum = srem i16 %X, 32
223   br i1 true, label %loop, label %unreach
225 unreach:
226   switch i16 %quantum, label %unreach.ret []
228 unreach.ret:
229   unreachable
232 define void @sink_to_unreachable_indirectbr(ptr %Ptr)  {
233 ; CHECK-LABEL: @sink_to_unreachable_indirectbr(
234 ; CHECK-NEXT:  entry:
235 ; CHECK-NEXT:    br label [[LOOP:%.*]]
236 ; CHECK:       loop:
237 ; CHECK-NEXT:    br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
238 ; CHECK:       unreach:
239 ; CHECK-NEXT:    indirectbr ptr poison, [label %loop]
241 entry:
242   br label %loop
244 loop:
245   %gep = getelementptr inbounds ptr, ptr %Ptr, i16 1
246   br i1 true, label %loop, label %unreach
248 unreach:
249   indirectbr ptr %gep, [label %loop]
252 define void @sink_to_unreachable_invoke(ptr %Ptr) personality ptr @__CxxFrameHandler3 {
253 ; CHECK-LABEL: @sink_to_unreachable_invoke(
254 ; CHECK-NEXT:  entry:
255 ; CHECK-NEXT:    br label [[LOOP:%.*]]
256 ; CHECK:       loop:
257 ; CHECK-NEXT:    br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
258 ; CHECK:       unreach:
259 ; CHECK-NEXT:    invoke void poison(i1 false)
260 ; CHECK-NEXT:            to label [[DUMMY:%.*]] unwind label [[ICATCH_DISPATCH:%.*]]
261 ; CHECK:       unreach2:
262 ; CHECK-NEXT:    invoke void @__CxxFrameHandler3(ptr poison)
263 ; CHECK-NEXT:            to label [[DUMMY]] unwind label [[ICATCH_DISPATCH]]
264 ; CHECK:       unreach3:
265 ; CHECK-NEXT:    [[CLEAN:%.*]] = cleanuppad within none []
266 ; CHECK-NEXT:    invoke void @__CxxFrameHandler3(ptr poison) [ "funclet"(token [[CLEAN]]) ]
267 ; CHECK-NEXT:            to label [[DUMMY]] unwind label [[ICATCH_DISPATCH]]
268 ; CHECK:       icatch.dispatch:
269 ; CHECK-NEXT:    [[TMP1:%.*]] = catchswitch within none [label %icatch] unwind to caller
270 ; CHECK:       icatch:
271 ; CHECK-NEXT:    [[TMP2:%.*]] = catchpad within [[TMP1]] [ptr null, i32 64, ptr null]
272 ; CHECK-NEXT:    catchret from [[TMP2]] to label [[DUMMY2:%.*]]
273 ; CHECK:       dummy:
274 ; CHECK-NEXT:    ret void
275 ; CHECK:       dummy2:
276 ; CHECK-NEXT:    ret void
278 entry:
279   br label %loop
281 loop:
282   %gep = getelementptr inbounds ptr, ptr %Ptr, i16 1
283   br i1 true, label %loop, label %unreach
285 unreach:
286   invoke void %gep(i1 false)
287   to label %dummy unwind label %icatch.dispatch
289 unreach2:
290   invoke void @__CxxFrameHandler3(ptr %gep)
291   to label %dummy unwind label %icatch.dispatch
293 unreach3:
294   %clean = cleanuppad within none []
295   invoke void @__CxxFrameHandler3(ptr %gep) [ "funclet"(token %clean) ]
296   to label %dummy unwind label %icatch.dispatch
298 icatch.dispatch:
299   %tmp1 = catchswitch within none [label %icatch] unwind to caller
301 icatch:
302   %tmp2 = catchpad within %tmp1 [ptr null, i32 64, ptr null]
303   catchret from %tmp2 to label %dummy2
305 dummy:
306   ret void
308 dummy2:
309   ret void
312 declare void @may_throw()
313 declare i32 @__CxxFrameHandler3(...)