diff --git a/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h b/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h --- a/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h +++ b/llvm/include/llvm/CodeGen/SwitchLoweringUtils.h @@ -219,13 +219,15 @@ BranchProbability Prob; BranchProbability DefaultProb; bool OmitRangeCheck; + bool UnreachableDefault; BitTestBlock(APInt F, APInt R, const Value *SV, unsigned Rg, MVT RgVT, bool E, bool CR, MachineBasicBlock *P, MachineBasicBlock *D, - BitTestInfo C, BranchProbability Pr) + BitTestInfo C, BranchProbability Pr, bool Ud) : First(std::move(F)), Range(std::move(R)), SValue(SV), Reg(Rg), RegVT(RgVT), Emitted(E), ContiguousRange(CR), Parent(P), Default(D), - Cases(std::move(C)), Prob(Pr), OmitRangeCheck(false) {} + Cases(std::move(C)), Prob(Pr), OmitRangeCheck(false), + UnreachableDefault(Ud) {} }; /// Return the range of values within a range. diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1861,9 +1861,11 @@ // test, and delete the last bit test. MachineBasicBlock *NextMBB; - if (BTB.ContiguousRange && j + 2 == ej) { + if ((BTB.ContiguousRange || BTB.UnreachableDefault) && j + 2 == ej) { // Second-to-last bit-test with contiguous range: fall through to the // target of the final bit test. + // Second-to-last bit-test with unreachable default: jump to the target + // of the next bit test. NextMBB = BTB.Cases[j + 1].TargetBB; } else if (j + 1 == ej) { // For the last bit test, fall through to Default. @@ -1880,7 +1882,7 @@ SDB->clear(); CodeGenAndEmitDAG(); - if (BTB.ContiguousRange && j + 2 == ej) { + if ((BTB.ContiguousRange || BTB.UnreachableDefault) && j + 2 == ej) { // Since we're not going to use the final bit test, remove it. BTB.Cases.pop_back(); break; diff --git a/llvm/lib/CodeGen/SwitchLoweringUtils.cpp b/llvm/lib/CodeGen/SwitchLoweringUtils.cpp --- a/llvm/lib/CodeGen/SwitchLoweringUtils.cpp +++ b/llvm/lib/CodeGen/SwitchLoweringUtils.cpp @@ -451,10 +451,12 @@ FuncInfo.MF->CreateMachineBasicBlock(SI->getParent()); BTI.push_back(BitTestCase(CB.Mask, BitTestBB, CB.BB, CB.ExtraProb)); } + bool DefaultUnreachable = + isa(SI->getDefaultDest()->getFirstNonPHIOrDbg()); BitTestCases.emplace_back(std::move(LowBound), std::move(CmpRange), SI->getCondition(), -1U, MVT::Other, false, ContiguousRange, nullptr, nullptr, std::move(BTI), - TotalProb); + TotalProb, DefaultUnreachable); BTCluster = CaseCluster::bitTests(Clusters[First].Low, Clusters[Last].High, BitTestCases.size() - 1, TotalProb); diff --git a/llvm/test/CodeGen/X86/SwitchLowering.ll b/llvm/test/CodeGen/X86/SwitchLowering.ll --- a/llvm/test/CodeGen/X86/SwitchLowering.ll +++ b/llvm/test/CodeGen/X86/SwitchLowering.ll @@ -62,6 +62,9 @@ declare void @foo(i8) +; PR50080 +; The important part of this test is that we emit only 1 bit test rather than +; 2 since the default BB of the switch is unreachable. define i32 @baz(i32 %0) { ; CHECK-LABEL: baz: ; CHECK: # %bb.0: @@ -70,16 +73,11 @@ ; CHECK-NEXT: movl $13056, %edx # imm = 0x3300 ; CHECK-NEXT: btl %ecx, %edx ; CHECK-NEXT: jae .LBB1_1 -; CHECK-NEXT: # %bb.3: # %return +; CHECK-NEXT: # %bb.2: # %return ; CHECK-NEXT: retl -; CHECK-NEXT: .LBB1_1: -; CHECK-NEXT: movl $48, %eax -; CHECK-NEXT: btl %ecx, %eax -; CHECK-NEXT: jae .LBB1_4 -; CHECK-NEXT: # %bb.2: # %sw.epilog8 +; CHECK-NEXT: .LBB1_1: # %sw.epilog8 ; CHECK-NEXT: movl $1, %eax ; CHECK-NEXT: retl -; CHECK-NEXT: .LBB1_4: # %if.then.unreachabledefault switch i32 %0, label %if.then.unreachabledefault [ i32 4, label %sw.epilog8 i32 5, label %sw.epilog8 diff --git a/llvm/test/CodeGen/X86/switch-bit-test-unreachable-default.ll b/llvm/test/CodeGen/X86/switch-bit-test-unreachable-default.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/switch-bit-test-unreachable-default.ll @@ -0,0 +1,56 @@ +; RUN: llc -mtriple=x86_64-- -print-after=finalize-isel -stop-after=finalize-isel %s -o /dev/null 2>&1 | FileCheck %s + +; PR50080 +; The important part of this test is that we emit only 1 bit test (BT32rr) +; rather than 2 since the default BB of the switch is unreachable. +define i32 @baz(i32 %0) { +; CHECK: bb.0 (%ir-block.1): +; CHECK: successors: %bb.4(0x80000000); %bb.4(100.00%) +; CHECK: liveins: $edi +; CHECK: %1:gr32 = COPY $edi +; CHECK: %2:gr32 = MOV32r0 implicit-def dead $eflags +; CHECK: %3:gr32 = COPY %1:gr32 +; CHECK: bb.4 (%ir-block.1): +; CHECK: ; predecessors: %bb.0 +; CHECK: successors: %bb.3(0x55555555), %bb.1(0x2aaaaaab); %bb.3(66.67%), %bb.1(33.33%) +; CHECK: %4:gr32 = MOV32ri 13056 +; CHECK: BT32rr killed %4:gr32, %3:gr32, implicit-def $eflags +; CHECK: JCC_1 %bb.3, 2, implicit $eflags +; CHECK: JMP_1 %bb.1 +; CHECK: bb.5 (%ir-block.1): +; CHECK: bb.1.sw.epilog8: +; CHECK: ; predecessors: %bb.4 +; CHECK: successors: %bb.3(0x80000000); %bb.3(100.00%) +; CHECK: %5:gr32 = MOV32ri 1 +; CHECK: JMP_1 %bb.3 +; CHECK: bb.2.if.then.unreachabledefault: +; CHECK: bb.3.return: +; CHECK: ; predecessors: %bb.4, %bb.1 +; CHECK: %0:gr32 = PHI %2:gr32, %bb.4, %5:gr32, %bb.1 +; CHECK: $eax = COPY %0:gr32 +; CHECK: RET 0, $eax + switch i32 %0, label %if.then.unreachabledefault [ + i32 4, label %sw.epilog8 + i32 5, label %sw.epilog8 + i32 8, label %sw.bb2 + i32 9, label %sw.bb2 + i32 12, label %sw.bb4 + i32 13, label %sw.bb4 + ] + +sw.bb2: + br label %return + +sw.bb4: + br label %return + +sw.epilog8: + br label %return + +if.then.unreachabledefault: + unreachable + +return: + %retval.0 = phi i32 [ 1, %sw.epilog8 ], [ 0, %sw.bb2 ], [ 0, %sw.bb4 ] + ret i32 %retval.0 +}