Index: llvm/include/llvm/CodeGen/SwitchLoweringUtils.h =================================================================== --- llvm/include/llvm/CodeGen/SwitchLoweringUtils.h +++ llvm/include/llvm/CodeGen/SwitchLoweringUtils.h @@ -212,13 +212,14 @@ BitTestInfo Cases; BranchProbability Prob; BranchProbability DefaultProb; + bool OmitRangeCheck; BitTestBlock(APInt F, APInt R, const Value *SV, unsigned Rg, MVT RgVT, bool E, bool CR, MachineBasicBlock *P, MachineBasicBlock *D, BitTestInfo C, BranchProbability Pr) : 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) {} + Cases(std::move(C)), Prob(Pr), OmitRangeCheck(false) {} }; /// Return the range of values within a range. Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2619,13 +2619,13 @@ MachineBasicBlock *SwitchBB) { SDLoc dl = getCurSDLoc(); - // Subtract the minimum value + // Subtract the minimum value. SDValue SwitchOp = getValue(B.SValue); EVT VT = SwitchOp.getValueType(); SDValue Sub = DAG.getNode(ISD::SUB, dl, VT, SwitchOp, DAG.getConstant(B.First, dl, VT)); - // Check range + // Check range. const TargetLowering &TLI = DAG.getTargetLoweringInfo(); SDValue RangeCmp = DAG.getSetCC( dl, TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), @@ -2634,9 +2634,9 @@ // Determine the type of the test operands. bool UsePtrType = false; - if (!TLI.isTypeLegal(VT)) + if (!TLI.isTypeLegal(VT)) { UsePtrType = true; - else { + } else { for (unsigned i = 0, e = B.Cases.size(); i != e; ++i) if (!isUIntN(VT.getSizeInBits(), B.Cases[i].Mask)) { // Switch table case range are encoded into series of masks. @@ -2660,16 +2660,24 @@ addSuccessorWithProb(SwitchBB, MBB, B.Prob); SwitchBB->normalizeSuccProbs(); - SDValue BrRange = DAG.getNode(ISD::BRCOND, dl, - MVT::Other, CopyTo, RangeCmp, - DAG.getBasicBlock(B.Default)); - - // Avoid emitting unnecessary branches to the next block. - if (MBB != NextBlock(SwitchBB)) - BrRange = DAG.getNode(ISD::BR, dl, MVT::Other, BrRange, - DAG.getBasicBlock(MBB)); + if (!B.OmitRangeCheck) { + SDValue BrRange = DAG.getNode(ISD::BRCOND, dl, + MVT::Other, CopyTo, RangeCmp, + DAG.getBasicBlock(B.Default)); - DAG.setRoot(BrRange); + // Avoid emitting unnecessary branches to the next block. + if (MBB != NextBlock(SwitchBB)) + BrRange = DAG.getNode(ISD::BR, dl, MVT::Other, BrRange, + DAG.getBasicBlock(MBB)); + DAG.setRoot(BrRange); + } else { + // Branch or fall through to MBB without a range check. + if (MBB != NextBlock(SwitchBB)) + DAG.setRoot( + DAG.getNode(ISD::BR, dl, MVT::Other, CopyTo, DAG.getBasicBlock(MBB))); + else + DAG.setRoot(CopyTo); + } } /// visitBitTestCase - this function produces one "bit test" @@ -10164,8 +10172,6 @@ break; } case CC_BitTests: { - // FIXME: If Fallthrough is unreachable, skip the range check. - // FIXME: Optimize away range check based on pivot comparisons. BitTestBlock *BTB = &SL->BitTestCases[I->BTCasesIndex]; @@ -10186,6 +10192,11 @@ BTB->DefaultProb -= DefaultProb / 2; } + if (FallthroughUnreachable) { + // Skip the range check if the fallthrough block is unreachable. + BTB->OmitRangeCheck = true; + } + // If we're in the right place, emit the bit test header right now. if (CurMBB == SwitchMBB) { visitBitTestHeader(*BTB, SwitchMBB); Index: llvm/test/CodeGen/X86/switch-bt.ll =================================================================== --- llvm/test/CodeGen/X86/switch-bt.ll +++ llvm/test/CodeGen/X86/switch-bt.ll @@ -155,3 +155,45 @@ ; CHECK: cmpl $60 ; CHECK: jne } + + +; Omit the range check when the default case is unreachable, see PR43129. +declare void @g(i32) +define void @test5(i32 %x) { + +; CHECK-LABEL: test5 +; CHECK-NOT: cmp + +; 73 = 2^0 + 2^3 + 2^6 +; CHECK: movl $73 +; CHECK-NEXT: btl +; CHECK-NEXT: jb + +; 146 = 2^1 + 2^4 + 2^7 +; CHECK-NEXT: movl $146 +; CHECK-NEXT: btl +; CHECK-NEXT: jae + +; CHECK-NEXT: movl $1, %edi +; CHECK-NEXT: callq g + + +entry: + switch i32 %x, label %return [ + i32 0, label %bb0 + i32 3, label %bb0 + i32 6, label %bb0 + + i32 1, label %bb1 + i32 4, label %bb1 + i32 7, label %bb1 + + i32 2, label %bb2 + i32 5, label %bb2 + i32 8, label %bb2 + ] +bb0: tail call void @g(i32 0) br label %return +bb1: tail call void @g(i32 1) br label %return +bb2: tail call void @g(i32 2) br label %return +return: unreachable +}