diff options
author | Noah Goldstein <goldstein.w.n@gmail.com> | 2023-08-24 14:22:05 -0500 |
---|---|---|
committer | Noah Goldstein <goldstein.w.n@gmail.com> | 2023-08-24 19:43:10 -0500 |
commit | 846ff921ffe8bf43eb2f66869475ad9a5ef0a02a (patch) | |
tree | 69c14e29735360890541553fd39265c136635893 /llvm | |
parent | d0b4ed9a2cf353eb9f59be344862595af2bd205d (diff) | |
download | llvm-846ff921ffe8bf43eb2f66869475ad9a5ef0a02a.zip llvm-846ff921ffe8bf43eb2f66869475ad9a5ef0a02a.tar.gz llvm-846ff921ffe8bf43eb2f66869475ad9a5ef0a02a.tar.bz2 |
[ValueTracking] Compute `sdiv` as non-zero if `abs(num) u>= abs(denum)`
Just covering an additional case.
Proof: https://alive2.llvm.org/ce/z/MJz9fT
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D157302
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 37 | ||||
-rw-r--r-- | llvm/test/Analysis/ValueTracking/known-non-zero.ll | 13 |
2 files changed, 24 insertions, 26 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 54539d2..06162c6 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -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. diff --git a/llvm/test/Analysis/ValueTracking/known-non-zero.ll b/llvm/test/Analysis/ValueTracking/known-non-zero.ll index 44b825f..6dce6e5 100644 --- a/llvm/test/Analysis/ValueTracking/known-non-zero.ll +++ b/llvm/test/Analysis/ValueTracking/known-non-zero.ll @@ -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 @@ -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 |