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)
7 define void @test_01(i32 %x, i32 %y) {
8 ; CHECK-LABEL: @test_01(
10 ; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
11 ; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[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
18 ; CHECK-NEXT: ret void
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
28 call void @use(i32 %comparator)
36 define void @test_02(i32 %x, i32 %y) {
37 ; CHECK-LABEL: @test_02(
39 ; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
40 ; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]
42 ; CHECK-NEXT: [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]
43 ; CHECK-NEXT: br i1 [[C3]], label [[EXIT]], label [[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
51 ; CHECK-NEXT: ret void
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
61 %c3 = icmp sgt i32 %x, %y
62 br i1 %c3, label %exit, label %unreached
65 call void @use(i32 %comparator)
72 define i32 @test_03(i32 %x, i32 %y) {
73 ; CHECK-LABEL: @test_03(
75 ; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
76 ; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]
78 ; CHECK-NEXT: [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]
79 ; CHECK-NEXT: br i1 [[C3]], label [[EXIT]], label [[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]]
86 ; CHECK-NEXT: ret i32 0
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
96 %c3 = icmp sgt i32 %x, %y
97 br i1 %c3, label %exit, label %unreached
106 define i32 @test_04(i32 %x, i1 %c) {
107 ; CHECK-LABEL: @test_04(
109 ; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
111 ; CHECK-NEXT: br label [[BB3:%.*]]
113 ; CHECK-NEXT: br label [[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]]
122 br i1 %c, label %bb1, label %bb2
128 %p = phi i32 [0, %bb1], [1, %bb2]
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(
137 ; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], 1
138 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
140 ; CHECK-NEXT: br label [[BB3:%.*]]
142 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @cond()
143 ; CHECK-NEXT: br i1 [[CALL]], label [[BB2]], label [[BB3]]
145 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[BB1]] ], [ [[A]], [[BB2]] ]
146 ; CHECK-NEXT: ret i32 [[P]]
150 br i1 %cond, label %bb1, label %bb2
154 %call = call i1 @cond()
155 br i1 %call, label %bb2, label %bb3
157 %p = phi i32 [0, %bb1], [%a, %bb2]
161 define i1 @sink_to_unreachable_ret(i16 %X) {
162 ; CHECK-LABEL: @sink_to_unreachable_ret(
164 ; CHECK-NEXT: br label [[LOOP:%.*]]
166 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
168 ; CHECK-NEXT: ret i1 poison
174 %p = icmp sgt i16 %X, 16
175 br i1 true, label %loop, label %unreach
181 define void @sink_to_unreachable_condbr(i16 %X) {
182 ; CHECK-LABEL: @sink_to_unreachable_condbr(
184 ; CHECK-NEXT: br label [[LOOP:%.*]]
186 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
188 ; CHECK-NEXT: br i1 poison, label [[DUMMY:%.*]], label [[LOOP]]
190 ; CHECK-NEXT: unreachable
196 %p = icmp sgt i16 %X, 16
197 br i1 true, label %loop, label %unreach
200 br i1 %p, label %dummy, label %loop
206 define void @sink_to_unreachable_switch(i16 %X) {
207 ; CHECK-LABEL: @sink_to_unreachable_switch(
209 ; CHECK-NEXT: br label [[LOOP:%.*]]
211 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
213 ; CHECK-NEXT: switch i16 poison, label [[UNREACH_RET:%.*]] [
215 ; CHECK: unreach.ret:
216 ; CHECK-NEXT: unreachable
222 %quantum = srem i16 %X, 32
223 br i1 true, label %loop, label %unreach
226 switch i16 %quantum, label %unreach.ret []
232 define void @sink_to_unreachable_indirectbr(ptr %Ptr) {
233 ; CHECK-LABEL: @sink_to_unreachable_indirectbr(
235 ; CHECK-NEXT: br label [[LOOP:%.*]]
237 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
239 ; CHECK-NEXT: indirectbr ptr poison, [label %loop]
245 %gep = getelementptr inbounds ptr, ptr %Ptr, i16 1
246 br i1 true, label %loop, label %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(
255 ; CHECK-NEXT: br label [[LOOP:%.*]]
257 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
259 ; CHECK-NEXT: invoke void poison(i1 false)
260 ; CHECK-NEXT: to label [[DUMMY:%.*]] unwind label [[ICATCH_DISPATCH:%.*]]
262 ; CHECK-NEXT: invoke void @__CxxFrameHandler3(ptr poison)
263 ; CHECK-NEXT: to label [[DUMMY]] unwind label [[ICATCH_DISPATCH]]
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
271 ; CHECK-NEXT: [[TMP2:%.*]] = catchpad within [[TMP1]] [ptr null, i32 64, ptr null]
272 ; CHECK-NEXT: catchret from [[TMP2]] to label [[DUMMY2:%.*]]
274 ; CHECK-NEXT: ret void
276 ; CHECK-NEXT: ret void
282 %gep = getelementptr inbounds ptr, ptr %Ptr, i16 1
283 br i1 true, label %loop, label %unreach
286 invoke void %gep(i1 false)
287 to label %dummy unwind label %icatch.dispatch
290 invoke void @__CxxFrameHandler3(ptr %gep)
291 to label %dummy unwind label %icatch.dispatch
294 %clean = cleanuppad within none []
295 invoke void @__CxxFrameHandler3(ptr %gep) [ "funclet"(token %clean) ]
296 to label %dummy unwind label %icatch.dispatch
299 %tmp1 = catchswitch within none [label %icatch] unwind to caller
302 %tmp2 = catchpad within %tmp1 [ptr null, i32 64, ptr null]
303 catchret from %tmp2 to label %dummy2
312 declare void @may_throw()
313 declare i32 @__CxxFrameHandler3(...)