Skip to content

Commit f1ee458

Browse files
committed
[ValueTracking] improve isKnownNonZero precision for smax
Instead of relying on known-bits for strictly positive, use the `isKnownPositive` API. This will use `isKnownNonZero` which is more accurate. Closes llvm#88170
1 parent 2ff82c2 commit f1ee458

File tree

2 files changed

+32
-15
lines changed

2 files changed

+32
-15
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,23 +2870,44 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
28702870
case Intrinsic::uadd_sat:
28712871
return isKnownNonZero(II->getArgOperand(1), DemandedElts, Depth, Q) ||
28722872
isKnownNonZero(II->getArgOperand(0), DemandedElts, Depth, Q);
2873-
case Intrinsic::smin:
28742873
case Intrinsic::smax: {
2875-
auto KnownOpImpliesNonZero = [&](const KnownBits &K) {
2876-
return II->getIntrinsicID() == Intrinsic::smin
2877-
? K.isNegative()
2878-
: K.isStrictlyPositive();
2874+
// If either arg is strictly positive the result is non-zero. Otherwise
2875+
// the result is non-zero if both ops are non-zero.
2876+
auto IsNonZero = [&](Value *Op, std::optional<bool> &OpNonZero,
2877+
const KnownBits &OpKnown) {
2878+
if (!OpNonZero.has_value())
2879+
OpNonZero = OpKnown.isNonZero() ||
2880+
isKnownNonZero(Op, DemandedElts, Depth, Q);
2881+
return *OpNonZero;
28792882
};
2880-
KnownBits XKnown =
2883+
// Avoid re-computing isKnownNonZero.
2884+
std::optional<bool> Op0NonZero, Op1NonZero;
2885+
KnownBits Op1Known =
2886+
computeKnownBits(II->getArgOperand(1), DemandedElts, Depth, Q);
2887+
if (Op1Known.isNonNegative() &&
2888+
IsNonZero(II->getArgOperand(1), Op1NonZero, Op1Known))
2889+
return true;
2890+
KnownBits Op0Known =
28812891
computeKnownBits(II->getArgOperand(0), DemandedElts, Depth, Q);
2882-
if (KnownOpImpliesNonZero(XKnown))
2892+
if (Op0Known.isNonNegative() &&
2893+
IsNonZero(II->getArgOperand(0), Op0NonZero, Op0Known))
28832894
return true;
2884-
KnownBits YKnown =
2895+
return IsNonZero(II->getArgOperand(1), Op1NonZero, Op1Known) &&
2896+
IsNonZero(II->getArgOperand(0), Op0NonZero, Op0Known);
2897+
}
2898+
case Intrinsic::smin: {
2899+
// If either arg is negative the result is non-zero. Otherwise
2900+
// the result is non-zero if both ops are non-zero.
2901+
KnownBits Op1Known =
28852902
computeKnownBits(II->getArgOperand(1), DemandedElts, Depth, Q);
2886-
if (KnownOpImpliesNonZero(YKnown))
2903+
if (Op1Known.isNegative())
2904+
return true;
2905+
KnownBits Op0Known =
2906+
computeKnownBits(II->getArgOperand(0), DemandedElts, Depth, Q);
2907+
if (Op0Known.isNegative())
28872908
return true;
28882909

2889-
if (XKnown.isNonZero() && YKnown.isNonZero())
2910+
if (Op1Known.isNonZero() && Op0Known.isNonZero())
28902911
return true;
28912912
}
28922913
[[fallthrough]];

llvm/test/Transforms/InstSimplify/known-non-zero.ll

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,7 @@ B:
169169

170170
define i1 @smax_non_zero(i8 %xx, i8 %y) {
171171
; CHECK-LABEL: @smax_non_zero(
172-
; CHECK-NEXT: [[X0:%.*]] = and i8 [[XX:%.*]], 63
173-
; CHECK-NEXT: [[X:%.*]] = add i8 [[X0]], 1
174-
; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y:%.*]])
175-
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[V]], 0
176-
; CHECK-NEXT: ret i1 [[R]]
172+
; CHECK-NEXT: ret i1 false
177173
;
178174
%x0 = and i8 %xx, 63
179175
%x = add i8 %x0, 1

0 commit comments

Comments
 (0)