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: [[COMPARATOR:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
14 ; CHECK-NEXT: call void @use(i32 [[COMPARATOR]])
15 ; CHECK-NEXT: unreachable
17 ; CHECK-NEXT: ret void
20 %c1 = icmp eq i32 %x, %y
21 %c2 = icmp slt i32 %x, %y
22 %signed = select i1 %c2, i32 -1, i32 1
23 %comparator = select i1 %c1, i32 0, i32 %signed
24 br i1 %c2, label %exit, label %unreached
27 call void @use(i32 %comparator)
35 define void @test_02(i32 %x, i32 %y) {
36 ; CHECK-LABEL: @test_02(
38 ; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
39 ; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]
41 ; CHECK-NEXT: [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]
42 ; CHECK-NEXT: br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]]
44 ; CHECK-NEXT: [[COMPARATOR:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
45 ; CHECK-NEXT: call void @use(i32 [[COMPARATOR]])
46 ; CHECK-NEXT: unreachable
48 ; CHECK-NEXT: ret void
51 %c1 = icmp eq i32 %x, %y
52 %c2 = icmp slt i32 %x, %y
53 %signed = select i1 %c2, i32 -1, i32 1
54 %comparator = select i1 %c1, i32 0, i32 %signed
55 br i1 %c2, label %exit, label %medium
58 %c3 = icmp sgt i32 %x, %y
59 br i1 %c3, label %exit, label %unreached
62 call void @use(i32 %comparator)
69 define i32 @test_03(i32 %x, i32 %y) {
70 ; CHECK-LABEL: @test_03(
72 ; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
73 ; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]
75 ; CHECK-NEXT: [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]
76 ; CHECK-NEXT: br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]]
78 ; CHECK-NEXT: [[COMPARATOR:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])
79 ; CHECK-NEXT: ret i32 [[COMPARATOR]]
81 ; CHECK-NEXT: ret i32 0
84 %c1 = icmp eq i32 %x, %y
85 %c2 = icmp slt i32 %x, %y
86 %signed = select i1 %c2, i32 -1, i32 1
87 %comparator = select i1 %c1, i32 0, i32 %signed
88 br i1 %c2, label %exit, label %medium
91 %c3 = icmp sgt i32 %x, %y
92 br i1 %c3, label %exit, label %unreached
101 define i32 @test_04(i32 %x, i1 %c) {
102 ; CHECK-LABEL: @test_04(
104 ; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
106 ; CHECK-NEXT: br label [[BB3:%.*]]
108 ; CHECK-NEXT: br label [[BB3]]
110 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[BB1]] ], [ 1, [[BB2]] ]
111 ; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], 1
112 ; CHECK-NEXT: [[R:%.*]] = add i32 [[P]], [[A]]
113 ; CHECK-NEXT: ret i32 [[R]]
117 br i1 %c, label %bb1, label %bb2
123 %p = phi i32 [0, %bb1], [1, %bb2]
128 ; Do not sink into a potentially hotter block.
129 define i32 @test_05_neg(i32 %x, i1 %cond) {
130 ; CHECK-LABEL: @test_05_neg(
132 ; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], 1
133 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
135 ; CHECK-NEXT: br label [[BB3:%.*]]
137 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @cond()
138 ; CHECK-NEXT: br i1 [[CALL]], label [[BB2]], label [[BB3]]
140 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[BB1]] ], [ [[A]], [[BB2]] ]
141 ; CHECK-NEXT: ret i32 [[P]]
145 br i1 %cond, label %bb1, label %bb2
149 %call = call i1 @cond()
150 br i1 %call, label %bb2, label %bb3
152 %p = phi i32 [0, %bb1], [%a, %bb2]
156 define i1 @sink_to_unreachable_ret(i16 %X) {
157 ; CHECK-LABEL: @sink_to_unreachable_ret(
159 ; CHECK-NEXT: br label [[LOOP:%.*]]
161 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
163 ; CHECK-NEXT: ret i1 poison
169 %p = icmp sgt i16 %X, 16
170 br i1 true, label %loop, label %unreach
176 define void @sink_to_unreachable_condbr(i16 %X) {
177 ; CHECK-LABEL: @sink_to_unreachable_condbr(
179 ; CHECK-NEXT: br label [[LOOP:%.*]]
181 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
183 ; CHECK-NEXT: br i1 poison, label [[DUMMY:%.*]], label [[LOOP]]
185 ; CHECK-NEXT: unreachable
191 %p = icmp sgt i16 %X, 16
192 br i1 true, label %loop, label %unreach
195 br i1 %p, label %dummy, label %loop
201 define void @sink_to_unreachable_switch(i16 %X) {
202 ; CHECK-LABEL: @sink_to_unreachable_switch(
204 ; CHECK-NEXT: br label [[LOOP:%.*]]
206 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
208 ; CHECK-NEXT: switch i16 poison, label [[UNREACH_RET:%.*]] [
210 ; CHECK: unreach.ret:
211 ; CHECK-NEXT: unreachable
217 %quantum = srem i16 %X, 32
218 br i1 true, label %loop, label %unreach
221 switch i16 %quantum, label %unreach.ret []
227 define void @sink_to_unreachable_indirectbr(ptr %Ptr) {
228 ; CHECK-LABEL: @sink_to_unreachable_indirectbr(
230 ; CHECK-NEXT: br label [[LOOP:%.*]]
232 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
234 ; CHECK-NEXT: indirectbr ptr poison, [label %loop]
240 %gep = getelementptr inbounds ptr, ptr %Ptr, i16 1
241 br i1 true, label %loop, label %unreach
244 indirectbr ptr %gep, [label %loop]
247 define void @sink_to_unreachable_invoke(ptr %Ptr) personality ptr @__CxxFrameHandler3 {
248 ; CHECK-LABEL: @sink_to_unreachable_invoke(
250 ; CHECK-NEXT: br label [[LOOP:%.*]]
252 ; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]
254 ; CHECK-NEXT: invoke void poison(i1 false)
255 ; CHECK-NEXT: to label [[DUMMY:%.*]] unwind label [[ICATCH_DISPATCH:%.*]]
257 ; CHECK-NEXT: invoke void @__CxxFrameHandler3(ptr poison)
258 ; CHECK-NEXT: to label [[DUMMY]] unwind label [[ICATCH_DISPATCH]]
260 ; CHECK-NEXT: [[CLEAN:%.*]] = cleanuppad within none []
261 ; CHECK-NEXT: invoke void @__CxxFrameHandler3(ptr poison) [ "funclet"(token [[CLEAN]]) ]
262 ; CHECK-NEXT: to label [[DUMMY]] unwind label [[ICATCH_DISPATCH]]
263 ; CHECK: icatch.dispatch:
264 ; CHECK-NEXT: [[TMP1:%.*]] = catchswitch within none [label %icatch] unwind to caller
266 ; CHECK-NEXT: [[TMP2:%.*]] = catchpad within [[TMP1]] [ptr null, i32 64, ptr null]
267 ; CHECK-NEXT: catchret from [[TMP2]] to label [[DUMMY2:%.*]]
269 ; CHECK-NEXT: ret void
271 ; CHECK-NEXT: ret void
277 %gep = getelementptr inbounds ptr, ptr %Ptr, i16 1
278 br i1 true, label %loop, label %unreach
281 invoke void %gep(i1 false)
282 to label %dummy unwind label %icatch.dispatch
285 invoke void @__CxxFrameHandler3(ptr %gep)
286 to label %dummy unwind label %icatch.dispatch
289 %clean = cleanuppad within none []
290 invoke void @__CxxFrameHandler3(ptr %gep) [ "funclet"(token %clean) ]
291 to label %dummy unwind label %icatch.dispatch
294 %tmp1 = catchswitch within none [label %icatch] unwind to caller
297 %tmp2 = catchpad within %tmp1 [ptr null, i32 64, ptr null]
298 catchret from %tmp2 to label %dummy2
307 declare void @may_throw()
308 declare i32 @__CxxFrameHandler3(...)