Skip to content

Commit 0454763

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.
1 parent d5966f8 commit 0454763

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
@@ -2828,23 +2828,44 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
28282828
case Intrinsic::uadd_sat:
28292829
return isKnownNonZero(II->getArgOperand(1), DemandedElts, Depth, Q) ||
28302830
isKnownNonZero(II->getArgOperand(0), DemandedElts, Depth, Q);
2831-
case Intrinsic::smin:
28322831
case Intrinsic::smax: {
2833-
auto KnownOpImpliesNonZero = [&](const KnownBits &K) {
2834-
return II->getIntrinsicID() == Intrinsic::smin
2835-
? K.isNegative()
2836-
: K.isStrictlyPositive();
2832+
// If either arg is strictly positive the result is non-zero. Otherwise
2833+
// the result is non-zero if both ops are non-zero.
2834+
auto IsNonZero = [&](Value *Op, std::optional<bool> &OpNonZero,
2835+
KnownBits OpKnown) {
2836+
if (!OpNonZero.has_value())
2837+
OpNonZero = OpKnown.isNonZero() ||
2838+
isKnownNonZero(Op, DemandedElts, Depth, Q);
2839+
return *OpNonZero;
28372840
};
2838-
KnownBits XKnown =
2841+
// Avoid re-computing isKnownNonZero.
2842+
std::optional<bool> Op0NonZero, Op1NonZero;
2843+
KnownBits Op1Known =
2844+
computeKnownBits(II->getArgOperand(1), DemandedElts, Depth, Q);
2845+
if (Op1Known.isNonNegative() &&
2846+
IsNonZero(II->getArgOperand(1), Op1NonZero, Op1Known))
2847+
return true;
2848+
KnownBits Op0Known =
28392849
computeKnownBits(II->getArgOperand(0), DemandedElts, Depth, Q);
2840-
if (KnownOpImpliesNonZero(XKnown))
2850+
if (Op0Known.isNonNegative() &&
2851+
IsNonZero(II->getArgOperand(0), Op0NonZero, Op0Known))
28412852
return true;
2842-
KnownBits YKnown =
2853+
return IsNonZero(II->getArgOperand(1), Op1NonZero, Op1Known) &&
2854+
IsNonZero(II->getArgOperand(0), Op0NonZero, Op0Known);
2855+
}
2856+
case Intrinsic::smin: {
2857+
// If either arg is negative the result is non-zero. Otherwise
2858+
// the result is non-zero if both ops are non-zero.
2859+
KnownBits Op1Known =
28432860
computeKnownBits(II->getArgOperand(1), DemandedElts, Depth, Q);
2844-
if (KnownOpImpliesNonZero(YKnown))
2861+
if (Op1Known.isNegative())
2862+
return true;
2863+
KnownBits Op0Known =
2864+
computeKnownBits(II->getArgOperand(0), DemandedElts, Depth, Q);
2865+
if (Op0Known.isNegative())
28452866
return true;
28462867

2847-
if (XKnown.isNonZero() && YKnown.isNonZero())
2868+
if (Op1Known.isNonZero() && Op0Known.isNonZero())
28482869
return true;
28492870
}
28502871
[[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)