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 @@ -2570,26 +2570,33 @@ return isNonZeroShift(I, DemandedElts, Depth, Q, Known); } case Instruction::UDiv: - case Instruction::SDiv: + case Instruction::SDiv: { // X / Y // div exact can only produce a zero if the dividend is zero. if (cast(I)->isExact()) return isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q); - if (I->getOpcode() == Instruction::UDiv) { - std::optional XUgeY; - KnownBits XKnown = - computeKnownBits(I->getOperand(0), DemandedElts, Depth, Q); - if (!XKnown.isUnknown()) { - KnownBits YKnown = - computeKnownBits(I->getOperand(1), DemandedElts, Depth, Q); - // If X u>= Y then div is non zero (0/0 is UB). - XUgeY = KnownBits::uge(XKnown, YKnown); - } - // If X is total unknown or X u< Y we won't be able to prove non-zero - // with compute known bits so just return early. - return XUgeY && *XUgeY; + + std::optional XUgeY; + KnownBits XKnown = + computeKnownBits(I->getOperand(0), DemandedElts, Depth, Q); + // If X is fully unknown we won't be able to figure anything out so don't + // both computing knownbits for Y. + if (XKnown.isUnknown()) + return false; + + KnownBits YKnown = + computeKnownBits(I->getOperand(1), DemandedElts, Depth, Q); + if (I->getOpcode() == Instruction::SDiv) { + // For signed division need to compare abs value of the operands. + XKnown = XKnown.abs(/*IntMinIsPoison*/ false); + YKnown = YKnown.abs(/*IntMinIsPoison*/ false); } - break; + // If X u>= Y then div is non zero (0/0 is UB). + XUgeY = KnownBits::uge(XKnown, YKnown); + // If X is total unknown or X u< Y we won't be able to prove non-zero + // with compute known bits so just return early. + return XUgeY && *XUgeY; + } case Instruction::Add: { // X + Y. diff --git a/llvm/test/Analysis/ValueTracking/known-non-zero.ll b/llvm/test/Analysis/ValueTracking/known-non-zero.ll --- a/llvm/test/Analysis/ValueTracking/known-non-zero.ll +++ b/llvm/test/Analysis/ValueTracking/known-non-zero.ll @@ -1125,11 +1125,7 @@ define i1 @sdiv_known_non_zero(i8 %x, i8 %y) { ; CHECK-LABEL: @sdiv_known_non_zero( -; CHECK-NEXT: [[XX0:%.*]] = or i8 [[X:%.*]], -121 -; CHECK-NEXT: [[XX:%.*]] = and i8 [[XX0]], -2 -; CHECK-NEXT: [[XY:%.*]] = sdiv i8 [[XX]], -2 -; CHECK-NEXT: [[NZ:%.*]] = icmp ne i8 [[XY]], 0 -; CHECK-NEXT: ret i1 [[NZ]] +; CHECK-NEXT: ret i1 true ; %xx0 = or i8 %x, 135 %xx = and i8 %xx0, -2 @@ -1140,12 +1136,7 @@ define i1 @sdiv_known_non_zero2(i8 %x, i8 %y) { ; CHECK-LABEL: @sdiv_known_non_zero2( -; CHECK-NEXT: [[XX0:%.*]] = or i8 [[X:%.*]], 15 -; CHECK-NEXT: [[XX:%.*]] = and i8 [[XX0]], -4 -; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 3 -; CHECK-NEXT: [[XY:%.*]] = sdiv i8 [[XX]], [[YY]] -; CHECK-NEXT: [[NZ:%.*]] = icmp ne i8 [[XY]], 0 -; CHECK-NEXT: ret i1 [[NZ]] +; CHECK-NEXT: ret i1 true ; %xx0 = or i8 %x, 15 %xx = and i8 %xx0, -4