Commit fbc7fcf5 authored by Noah Goldstein's avatar Noah Goldstein
Browse files

[ValueTracking] Use knownbits interface for determining if `div`/`rem` are safe to speculate

This just replaces the exact constant requirements with known-bits
which can prove better results.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D149423
parent 824e9bb2
Loading
Loading
Loading
Loading
+13 −14
Original line number Diff line number Diff line
@@ -6035,29 +6035,28 @@ bool llvm::isSafeToSpeculativelyExecuteWithOpcode(
  case Instruction::UDiv:
  case Instruction::URem: {
    // x / y is undefined if y == 0.
    const APInt *V;
    if (match(Inst->getOperand(1), m_APInt(V)))
      return *V != 0;
    return false;
    const DataLayout &DL = Inst->getModule()->getDataLayout();
    return isKnownNonZero(Inst->getOperand(1), DL, /*Depth*/ 0, AC, CtxI, DT);
  }
  case Instruction::SDiv:
  case Instruction::SRem: {
    // x / y is undefined if y == 0 or x == INT_MIN and y == -1
    const APInt *Numerator, *Denominator;
    if (!match(Inst->getOperand(1), m_APInt(Denominator)))
      return false;
    const DataLayout &DL = Inst->getModule()->getDataLayout();
    KnownBits KnownDenominator =
        computeKnownBits(Inst->getOperand(1), DL, /*Depth*/ 0, AC, CtxI, DT);
    // We cannot hoist this division if the denominator is 0.
    if (*Denominator == 0)
    if (!KnownDenominator.isNonZero())
      return false;

    // It's safe to hoist if the denominator is not 0 or -1.
    if (!Denominator->isAllOnes())
    if (!KnownDenominator.Zero.isZero())
      return true;
    // At this point we know that the denominator is -1.  It is safe to hoist as

    // At this point denominator may be -1.  It is safe to hoist as
    // long we know that the numerator is not INT_MIN.
    if (match(Inst->getOperand(0), m_APInt(Numerator)))
      return !Numerator->isMinSignedValue();
    // The numerator *might* be MinSignedValue.
    return false;
    KnownBits KnownNumerator =
        computeKnownBits(Inst->getOperand(0), DL, /*Depth*/ 0, AC, CtxI, DT);
    return !KnownNumerator.getSignedMinValue().isMinSignedValue();
  }
  case Instruction::Load: {
    const LoadInst *LI = dyn_cast<LoadInst>(Inst);
+3 −3
Original line number Diff line number Diff line
@@ -51,10 +51,10 @@ define void @sdiv_ok(i16 %n, i16 %xx) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XO:%.*]] = or i16 [[XX:%.*]], 1
; CHECK-NEXT:    [[X:%.*]] = and i16 [[XO]], 123
; CHECK-NEXT:    [[DIV:%.*]] = sdiv i16 [[N:%.*]], [[X]]
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    call void @maythrow()
; CHECK-NEXT:    [[DIV:%.*]] = sdiv i16 [[N:%.*]], [[X]]
; CHECK-NEXT:    call void @use(i16 [[DIV]])
; CHECK-NEXT:    br label [[LOOP]]
;
@@ -74,10 +74,10 @@ define void @srem_ok2(i16 %nn, i16 %xx) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[N:%.*]] = and i16 [[NN:%.*]], 123
; CHECK-NEXT:    [[X:%.*]] = or i16 [[XX:%.*]], 1
; CHECK-NEXT:    [[DIV:%.*]] = srem i16 [[N]], [[X]]
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    call void @maythrow()
; CHECK-NEXT:    [[DIV:%.*]] = srem i16 [[N]], [[X]]
; CHECK-NEXT:    call void @use(i16 [[DIV]])
; CHECK-NEXT:    br label [[LOOP]]
;
@@ -117,10 +117,10 @@ define void @udiv_ok(i16 %n, i16 %xx) {
; CHECK-LABEL: @udiv_ok(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[X:%.*]] = or i16 [[XX:%.*]], 1
; CHECK-NEXT:    [[DIV:%.*]] = udiv i16 [[N:%.*]], [[X]]
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    call void @maythrow()
; CHECK-NEXT:    [[DIV:%.*]] = udiv i16 [[N:%.*]], [[X]]
; CHECK-NEXT:    call void @use(i16 [[DIV]])
; CHECK-NEXT:    br label [[LOOP]]
;