Skip to content

Commit

Permalink
[ValueTracking] Compute sdiv as non-zero if abs(num) u>= abs(denum)
Browse files Browse the repository at this point in the history
Just covering an additional case.

Proof: https://alive2.llvm.org/ce/z/MJz9fT

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D157302
  • Loading branch information
goldsteinn committed Aug 25, 2023
1 parent d0b4ed9 commit 846ff92
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 26 deletions.
37 changes: 22 additions & 15 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2570,26 +2570,33 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
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<PossiblyExactOperator>(I)->isExact())
return isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q);
if (I->getOpcode() == Instruction::UDiv) {
std::optional<bool> 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<bool> 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.

Expand Down
13 changes: 2 additions & 11 deletions llvm/test/Analysis/ValueTracking/known-non-zero.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1125,11 +1125,7 @@ define i1 @src_mul_maybe_zero_no_nonzero_mul(i8 %x, i8 %y) {

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
Expand All @@ -1140,12 +1136,7 @@ define i1 @sdiv_known_non_zero(i8 %x, i8 %y) {

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
Expand Down

0 comments on commit 846ff92

Please sign in to comment.