Commit cbefc36f authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Switch lowering: omit range check for bit tests when default is unreachable (PR43129)

This is modeled after the same functionality for jump tables, which was
added in r357067.

Differential revision: https://reviews.llvm.org/D68131

llvm-svn: 373431
parent 70f70035
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -212,13 +212,14 @@ struct BitTestBlock {
  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.
+23 −17
Original line number Diff line number Diff line
@@ -2622,17 +2622,11 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B,
  // 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.
  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
  SDValue RangeCmp = DAG.getSetCC(
      dl, TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
                                 Sub.getValueType()),
      Sub, DAG.getConstant(B.Range, dl, VT), ISD::SETUGT);
  SDValue RangeSub =
      DAG.getNode(ISD::SUB, dl, VT, SwitchOp, DAG.getConstant(B.First, dl, VT));

  // Determine the type of the test operands.
  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
  bool UsePtrType = false;
  if (!TLI.isTypeLegal(VT)) {
    UsePtrType = true;
@@ -2645,6 +2639,7 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B,
        break;
      }
  }
  SDValue Sub = RangeSub;
  if (UsePtrType) {
    VT = TLI.getPointerTy(DAG.getDataLayout());
    Sub = DAG.getZExtOrTrunc(Sub, dl, VT);
@@ -2660,16 +2655,24 @@ void SelectionDAGBuilder::visitBitTestHeader(BitTestBlock &B,
  addSuccessorWithProb(SwitchBB, MBB, B.Prob);
  SwitchBB->normalizeSuccProbs();

  SDValue BrRange = DAG.getNode(ISD::BRCOND, dl,
                                MVT::Other, CopyTo, RangeCmp,
  SDValue Root = CopyTo;
  if (!B.OmitRangeCheck) {
    // Conditional branch to the default block.
    SDValue RangeCmp = DAG.getSetCC(dl,
        TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(),
                               RangeSub.getValueType()),
        RangeSub, DAG.getConstant(B.Range, dl, RangeSub.getValueType()),
        ISD::SETUGT);

    Root = DAG.getNode(ISD::BRCOND, dl, MVT::Other, Root, 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));
    Root = DAG.getNode(ISD::BR, dl, MVT::Other, Root, DAG.getBasicBlock(MBB));

  DAG.setRoot(BrRange);
  DAG.setRoot(Root);
}

/// visitBitTestCase - this function produces one "bit test"
@@ -10164,8 +10167,6 @@ void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
        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 +10187,11 @@ void SelectionDAGBuilder::lowerWorkItem(SwitchWorkListItem W, Value *Cond,
          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);
+2 −3
Original line number Diff line number Diff line
@@ -157,13 +157,12 @@ sw.epilog:
}


; TODO: Omit the range check when the default case is unreachable, see PR43129.
; 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: cmpl $8, %edi
; CHECK: ja
; CHECK-NOT: cmp

; 73 = 2^0 + 2^3 + 2^6
; CHECK:      movl $73