309 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S < %s | FileCheck %s3 4declare void @use(i32 %x)5declare i1 @cond()6 7define 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: [[COMPARATOR:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])14; CHECK-NEXT: call void @use(i32 [[COMPARATOR]])15; CHECK-NEXT: unreachable16; CHECK: exit:17; CHECK-NEXT: ret void18;19entry:20 %c1 = icmp eq i32 %x, %y21 %c2 = icmp slt i32 %x, %y22 %signed = select i1 %c2, i32 -1, i32 123 %comparator = select i1 %c1, i32 0, i32 %signed24 br i1 %c2, label %exit, label %unreached25 26unreached:27 call void @use(i32 %comparator)28 unreachable29 30exit:31 ret void32}33 34 35define void @test_02(i32 %x, i32 %y) {36; CHECK-LABEL: @test_02(37; CHECK-NEXT: entry:38; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]39; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]40; CHECK: medium:41; CHECK-NEXT: [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]42; CHECK-NEXT: br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]]43; CHECK: 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: unreachable47; CHECK: exit:48; CHECK-NEXT: ret void49;50entry:51 %c1 = icmp eq i32 %x, %y52 %c2 = icmp slt i32 %x, %y53 %signed = select i1 %c2, i32 -1, i32 154 %comparator = select i1 %c1, i32 0, i32 %signed55 br i1 %c2, label %exit, label %medium56 57medium:58 %c3 = icmp sgt i32 %x, %y59 br i1 %c3, label %exit, label %unreached60 61unreached:62 call void @use(i32 %comparator)63 unreachable64 65exit:66 ret void67}68 69define i32 @test_03(i32 %x, i32 %y) {70; CHECK-LABEL: @test_03(71; CHECK-NEXT: entry:72; CHECK-NEXT: [[C2:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]73; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[MEDIUM:%.*]]74; CHECK: medium:75; CHECK-NEXT: [[C3:%.*]] = icmp sgt i32 [[X]], [[Y]]76; CHECK-NEXT: br i1 [[C3]], label [[EXIT]], label [[UNREACHED:%.*]]77; CHECK: unreached:78; CHECK-NEXT: [[COMPARATOR:%.*]] = call i32 @llvm.scmp.i32.i32(i32 [[X]], i32 [[Y]])79; CHECK-NEXT: ret i32 [[COMPARATOR]]80; CHECK: exit:81; CHECK-NEXT: ret i32 082;83entry:84 %c1 = icmp eq i32 %x, %y85 %c2 = icmp slt i32 %x, %y86 %signed = select i1 %c2, i32 -1, i32 187 %comparator = select i1 %c1, i32 0, i32 %signed88 br i1 %c2, label %exit, label %medium89 90medium:91 %c3 = icmp sgt i32 %x, %y92 br i1 %c3, label %exit, label %unreached93 94unreached:95 ret i32 %comparator96 97exit:98 ret i32 099}100 101define i32 @test_04(i32 %x, i1 %c) {102; CHECK-LABEL: @test_04(103; CHECK-NEXT: bb0:104; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]105; CHECK: bb1:106; CHECK-NEXT: br label [[BB3:%.*]]107; CHECK: bb2:108; CHECK-NEXT: br label [[BB3]]109; CHECK: bb3:110; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[BB1]] ], [ 1, [[BB2]] ]111; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], 1112; CHECK-NEXT: [[R:%.*]] = add i32 [[P]], [[A]]113; CHECK-NEXT: ret i32 [[R]]114;115bb0:116 %a = add i32 %x, 1117 br i1 %c, label %bb1, label %bb2118bb1:119 br label %bb3120bb2:121 br label %bb3122bb3:123 %p = phi i32 [0, %bb1], [1, %bb2]124 %r = add i32 %p, %a125 ret i32 %r126}127 128; Do not sink into a potentially hotter block.129define i32 @test_05_neg(i32 %x, i1 %cond) {130; CHECK-LABEL: @test_05_neg(131; CHECK-NEXT: bb0:132; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], 1133; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]134; CHECK: bb1:135; CHECK-NEXT: br label [[BB3:%.*]]136; CHECK: bb2:137; CHECK-NEXT: [[CALL:%.*]] = call i1 @cond()138; CHECK-NEXT: br i1 [[CALL]], label [[BB2]], label [[BB3]]139; CHECK: bb3:140; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[BB1]] ], [ [[A]], [[BB2]] ]141; CHECK-NEXT: ret i32 [[P]]142;143bb0:144 %a = add i32 %x, 1145 br i1 %cond, label %bb1, label %bb2146bb1:147 br label %bb3148bb2:149 %call = call i1 @cond()150 br i1 %call, label %bb2, label %bb3151bb3:152 %p = phi i32 [0, %bb1], [%a, %bb2]153 ret i32 %p154}155 156define i1 @sink_to_unreachable_ret(i16 %X) {157; CHECK-LABEL: @sink_to_unreachable_ret(158; CHECK-NEXT: entry:159; CHECK-NEXT: br label [[LOOP:%.*]]160; CHECK: loop:161; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]162; CHECK: unreach:163; CHECK-NEXT: ret i1 poison164;165entry:166 br label %loop167 168loop:169 %p = icmp sgt i16 %X, 16170 br i1 true, label %loop, label %unreach171 172unreach:173 ret i1 %p174}175 176define void @sink_to_unreachable_condbr(i16 %X) {177; CHECK-LABEL: @sink_to_unreachable_condbr(178; CHECK-NEXT: entry:179; CHECK-NEXT: br label [[LOOP:%.*]]180; CHECK: loop:181; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]182; CHECK: unreach:183; CHECK-NEXT: br i1 poison, label [[DUMMY:%.*]], label [[LOOP]]184; CHECK: dummy:185; CHECK-NEXT: unreachable186;187entry:188 br label %loop189 190loop:191 %p = icmp sgt i16 %X, 16192 br i1 true, label %loop, label %unreach193 194unreach:195 br i1 %p, label %dummy, label %loop196 197dummy:198 unreachable199}200 201define void @sink_to_unreachable_switch(i16 %X) {202; CHECK-LABEL: @sink_to_unreachable_switch(203; CHECK-NEXT: entry:204; CHECK-NEXT: br label [[LOOP:%.*]]205; CHECK: loop:206; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]207; CHECK: unreach:208; CHECK-NEXT: switch i16 poison, label [[UNREACH_RET:%.*]] [209; CHECK-NEXT: ]210; CHECK: unreach.ret:211; CHECK-NEXT: unreachable212;213entry:214 br label %loop215 216loop:217 %quantum = srem i16 %X, 32218 br i1 true, label %loop, label %unreach219 220unreach:221 switch i16 %quantum, label %unreach.ret []222 223unreach.ret:224 unreachable225}226 227define void @sink_to_unreachable_indirectbr(ptr %Ptr) {228; CHECK-LABEL: @sink_to_unreachable_indirectbr(229; CHECK-NEXT: entry:230; CHECK-NEXT: br label [[LOOP:%.*]]231; CHECK: loop:232; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]233; CHECK: unreach:234; CHECK-NEXT: indirectbr ptr poison, [label %loop]235;236entry:237 br label %loop238 239loop:240 %gep = getelementptr inbounds ptr, ptr %Ptr, i16 1241 br i1 true, label %loop, label %unreach242 243unreach:244 indirectbr ptr %gep, [label %loop]245}246 247define void @sink_to_unreachable_invoke(ptr %Ptr) personality ptr @__CxxFrameHandler3 {248; CHECK-LABEL: @sink_to_unreachable_invoke(249; CHECK-NEXT: entry:250; CHECK-NEXT: br label [[LOOP:%.*]]251; CHECK: loop:252; CHECK-NEXT: br i1 true, label [[LOOP]], label [[UNREACH:%.*]]253; CHECK: unreach:254; CHECK-NEXT: invoke void poison(i1 false)255; CHECK-NEXT: to label [[DUMMY:%.*]] unwind label [[ICATCH_DISPATCH:%.*]]256; CHECK: unreach2:257; CHECK-NEXT: invoke void @__CxxFrameHandler3(ptr poison)258; CHECK-NEXT: to label [[DUMMY]] unwind label [[ICATCH_DISPATCH]]259; CHECK: unreach3: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 caller265; CHECK: icatch:266; CHECK-NEXT: [[TMP2:%.*]] = catchpad within [[TMP1]] [ptr null, i32 64, ptr null]267; CHECK-NEXT: catchret from [[TMP2]] to label [[DUMMY2:%.*]]268; CHECK: dummy:269; CHECK-NEXT: ret void270; CHECK: dummy2:271; CHECK-NEXT: ret void272;273entry:274 br label %loop275 276loop:277 %gep = getelementptr inbounds ptr, ptr %Ptr, i16 1278 br i1 true, label %loop, label %unreach279 280unreach:281 invoke void %gep(i1 false)282 to label %dummy unwind label %icatch.dispatch283 284unreach2:285 invoke void @__CxxFrameHandler3(ptr %gep)286 to label %dummy unwind label %icatch.dispatch287 288unreach3:289 %clean = cleanuppad within none []290 invoke void @__CxxFrameHandler3(ptr %gep) [ "funclet"(token %clean) ]291 to label %dummy unwind label %icatch.dispatch292 293icatch.dispatch:294 %tmp1 = catchswitch within none [label %icatch] unwind to caller295 296icatch:297 %tmp2 = catchpad within %tmp1 [ptr null, i32 64, ptr null]298 catchret from %tmp2 to label %dummy2299 300dummy:301 ret void302 303dummy2:304 ret void305}306 307declare void @may_throw()308declare i32 @__CxxFrameHandler3(...)309