diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -6021,29 +6021,28 @@ 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 // 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(Inst); diff --git a/llvm/test/Analysis/ValueTracking/speculate-div.ll b/llvm/test/Analysis/ValueTracking/speculate-div.ll --- a/llvm/test/Analysis/ValueTracking/speculate-div.ll +++ b/llvm/test/Analysis/ValueTracking/speculate-div.ll @@ -52,20 +52,17 @@ ; CHECK-NEXT: [[X:%.*]] = or i16 [[XX:%.*]], 1 ; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 ; CHECK-NEXT: [[N0:%.*]] = or i16 [[TMP0]], 1 +; CHECK-NEXT: [[DIV_0:%.*]] = srem i16 [[N0]], [[X]] +; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: call void @side_effects0() -; CHECK-NEXT: [[DIV_0:%.*]] = srem i16 [[N0]], [[X]] -; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] ; CHECK-NEXT: br label [[IF_END:%.*]] ; CHECK: if.else: ; CHECK-NEXT: call void @side_effects1() -; CHECK-NEXT: [[DIV_1:%.*]] = srem i16 [[N0]], [[X]] -; CHECK-NEXT: [[V:%.*]] = add i16 [[DIV_1]], [[TMP0]] ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] -; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 +; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2 ; CHECK-NEXT: ret void ; entry: @@ -142,20 +139,17 @@ ; CHECK-NEXT: [[XO:%.*]] = or i16 [[XX:%.*]], 1 ; CHECK-NEXT: [[X:%.*]] = and i16 [[XO]], 123 ; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 [[TMP0]], [[X]] +; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: call void @side_effects0() -; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 [[TMP0]], [[X]] -; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] ; CHECK-NEXT: br label [[IF_END:%.*]] ; CHECK: if.else: ; CHECK-NEXT: call void @side_effects1() -; CHECK-NEXT: [[DIV_1:%.*]] = sdiv i16 [[TMP0]], [[X]] -; CHECK-NEXT: [[V:%.*]] = add i16 [[DIV_1]], [[TMP0]] ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] -; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 +; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2 ; CHECK-NEXT: ret void ; entry: @@ -185,20 +179,17 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: [[X:%.*]] = add nuw i16 [[XX:%.*]], 1 ; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 +; CHECK-NEXT: [[DIV_0:%.*]] = udiv i16 [[TMP0]], [[X]] +; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] ; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: ; CHECK-NEXT: call void @side_effects0() -; CHECK-NEXT: [[DIV_0:%.*]] = udiv i16 [[TMP0]], [[X]] -; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] ; CHECK-NEXT: br label [[IF_END:%.*]] ; CHECK: if.else: ; CHECK-NEXT: call void @side_effects1() -; CHECK-NEXT: [[DIV_1:%.*]] = udiv i16 [[TMP0]], [[X]] -; CHECK-NEXT: [[V:%.*]] = add i16 [[DIV_1]], [[TMP0]] ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: -; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] -; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 +; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2 ; CHECK-NEXT: ret void ; entry: