[PATCH] D150100: [KnownBits] Improve implementation of `KnownBits::abs`
Noah Goldstein via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun May 7 23:58:51 PDT 2023
goldstein.w.n created this revision.
goldstein.w.n added reviewers: foad, nikic, RKSimon.
Herald added subscribers: StephenFan, hiraditya.
Herald added a project: All.
goldstein.w.n requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
`abs` preserves the lowest set bit, so if we know the lowest set bit,
set it in the output.
As well, implement the case where the operand is known negative.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D150100
Files:
llvm/lib/Support/KnownBits.cpp
llvm/test/Analysis/ValueTracking/knownbits-abs.ll
Index: llvm/test/Analysis/ValueTracking/knownbits-abs.ll
===================================================================
--- llvm/test/Analysis/ValueTracking/knownbits-abs.ll
+++ llvm/test/Analysis/ValueTracking/knownbits-abs.ll
@@ -4,12 +4,7 @@
define i1 @abs_low_bit_set(i8 %x) {
; CHECK-LABEL: @abs_low_bit_set(
-; CHECK-NEXT: [[XX:%.*]] = and i8 [[X:%.*]], -16
-; CHECK-NEXT: [[V:%.*]] = or i8 [[XX]], 4
-; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[V]], i1 true)
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[ABS]], 4
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%xx = and i8 %x, 240
%v = or i8 %xx, 4
@@ -36,12 +31,7 @@
define i1 @abs_negative(i8 %x) {
; CHECK-LABEL: @abs_negative(
-; CHECK-NEXT: [[XX:%.*]] = and i8 [[X:%.*]], -16
-; CHECK-NEXT: [[V:%.*]] = or i8 [[XX]], -124
-; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[V]], i1 true)
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[ABS]], 8
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%xx = and i8 %x, 240
%v = or i8 %xx, 132
@@ -53,11 +43,7 @@
define i1 @abs_negative2(i8 %x) {
; CHECK-LABEL: @abs_negative2(
-; CHECK-NEXT: [[V:%.*]] = or i8 [[X:%.*]], -125
-; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[V]], i1 true)
-; CHECK-NEXT: [[AND:%.*]] = and i8 [[ABS]], 2
-; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 2
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 false
;
%v = or i8 %x, 131
%abs = call i8 @llvm.abs.i8(i8 %v, i1 true)
Index: llvm/lib/Support/KnownBits.cpp
===================================================================
--- llvm/lib/Support/KnownBits.cpp
+++ llvm/lib/Support/KnownBits.cpp
@@ -399,7 +399,14 @@
// Absolute value preserves trailing zero count.
KnownBits KnownAbs(getBitWidth());
- KnownAbs.Zero.setLowBits(countMinTrailingZeros());
+
+ unsigned Max = countMaxTrailingZeros();
+ unsigned Min = countMinTrailingZeros();
+
+ KnownAbs.Zero.setLowBits(Min);
+ // If we know the lowest set 1, then preserve it.
+ if (Max == Min && Max < getBitWidth())
+ KnownAbs.One.setBit(Max);
// We only know that the absolute values's MSB will be zero if INT_MIN is
// poison, or there is a set bit that isn't the sign bit (otherwise it could
@@ -407,8 +414,19 @@
if (IntMinIsPoison || (!One.isZero() && !One.isMinSignedValue()))
KnownAbs.Zero.setSignBit();
- // FIXME: Handle known negative input?
- // FIXME: Calculate the negated Known bits and combine them?
+ // If the input is negative, then abs(x) == -x.
+ if (isNegative()) {
+ KnownBits Zero(getBitWidth());
+ Zero.setAllZero();
+
+ KnownBits KnownNeg = computeForAddSub(
+ /*Add*/ false, /*NSW*/ false, Zero, *this);
+
+ // NB: KnownAbs is not always a subset of KnownNeg so we want to get input
+ // from both.
+ KnownAbs.One |= KnownNeg.One;
+ KnownAbs.Zero |= KnownNeg.Zero;
+ }
return KnownAbs;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D150100.520275.patch
Type: text/x-patch
Size: 3047 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230508/dbe39885/attachment.bin>
More information about the llvm-commits
mailing list