[llvm] 86dea1f - [ValueTracking] Improve llvm.abs handling in computeKnownBits.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 15:55:49 PDT 2020


Author: Craig Topper
Date: 2020-07-31T15:55:03-07:00
New Revision: 86dea1f39bd127776b999e10dff212003068d30a

URL: https://github.com/llvm/llvm-project/commit/86dea1f39bd127776b999e10dff212003068d30a
DIFF: https://github.com/llvm/llvm-project/commit/86dea1f39bd127776b999e10dff212003068d30a.diff

LOG: [ValueTracking] Improve llvm.abs handling in computeKnownBits.

Add the optimizations we have in the SelectionDAG version.
Known non-negative copies all known bits. Any known one other than
the sign bit makes result non-negative.

Differential Revision: https://reviews.llvm.org/D85000

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/InstCombine/abs-intrinsic.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 4cd2d07bf4b0..af55c96f3a53 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1644,13 +1644,24 @@ static void computeKnownBitsFromOperator(const Operator *I,
       default: break;
       case Intrinsic::abs:
         computeKnownBits(I->getOperand(0), Known2, Depth + 1, Q);
-        // Otherwise, if this call is undefined for INT_MIN, the result is
-        // positive.
-        if (match(II->getArgOperand(1), m_One()))
-          Known.Zero.setSignBit();
+
+        // If the source's MSB is zero then we know the rest of the bits.
+        if (Known2.isNonNegative()) {
+          Known.Zero |= Known2.Zero;
+          Known.One |= Known2.One;
+          break;
+        }
+
         // Absolute value preserves trailing zero count.
         Known.Zero.setLowBits(Known2.Zero.countTrailingOnes());
-        // FIXME: Handle known negative/non-negative input?
+
+        // If this call is undefined for INT_MIN, the result is positive. We
+        // also know it can't be INT_MIN if there is a set bit that isn't the
+        // sign bit.
+        Known2.One.clearSignBit();
+        if (match(II->getArgOperand(1), m_One()) || Known2.One.getBoolValue())
+          Known.Zero.setSignBit();
+        // FIXME: Handle known negative input?
         // FIXME: Calculate the negated Known bits and combine them?
         break;
       case Intrinsic::bitreverse:

diff  --git a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
index 8b965b3d1e44..ed845cc84267 100644
--- a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
+++ b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
@@ -2,6 +2,7 @@
 ; RUN: opt < %s -instcombine -S | FileCheck %s
 
 declare i32 @llvm.abs.i32(i32, i1)
+declare <4 x i32> @llvm.abs.v4i32(<4 x i32>, i1)
 
 define i1 @abs_nsw_must_be_positive(i32 %x) {
 ; CHECK-LABEL: @abs_nsw_must_be_positive(
@@ -12,6 +13,15 @@ define i1 @abs_nsw_must_be_positive(i32 %x) {
   ret i1 %c2
 }
 
+define <4 x i1> @abs_nsw_must_be_positive_vec(<4 x i32> %x) {
+; CHECK-LABEL: @abs_nsw_must_be_positive_vec(
+; CHECK-NEXT:    ret <4 x i1> <i1 true, i1 true, i1 true, i1 true>
+;
+  %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %x, i1 true)
+  %c2 = icmp sge <4 x i32> %abs, zeroinitializer
+  ret <4 x i1> %c2
+}
+
 ; Negative test, no nsw provides no information about the sign bit of the result.
 define i1 @abs_nonsw(i32 %x) {
 ; CHECK-LABEL: @abs_nonsw(
@@ -24,6 +34,17 @@ define i1 @abs_nonsw(i32 %x) {
   ret i1 %c2
 }
 
+define <4 x i1> @abs_nonsw_vec(<4 x i32> %x) {
+; CHECK-LABEL: @abs_nonsw_vec(
+; CHECK-NEXT:    [[ABS:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[X:%.*]], i1 false)
+; CHECK-NEXT:    [[C2:%.*]] = icmp sgt <4 x i32> [[ABS]], <i32 -1, i32 -1, i32 -1, i32 -1>
+; CHECK-NEXT:    ret <4 x i1> [[C2]]
+;
+  %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %x, i1 false)
+  %c2 = icmp sge <4 x i32> %abs, zeroinitializer
+  ret <4 x i1> %c2
+}
+
 ; abs preserves trailing zeros so the second and is unneeded
 define i32 @abs_trailing_zeros(i32 %x) {
 ; CHECK-LABEL: @abs_trailing_zeros(
@@ -37,6 +58,18 @@ define i32 @abs_trailing_zeros(i32 %x) {
   ret i32 %and2
 }
 
+define <4 x i32> @abs_trailing_zeros_vec(<4 x i32> %x) {
+; CHECK-LABEL: @abs_trailing_zeros_vec(
+; CHECK-NEXT:    [[AND:%.*]] = and <4 x i32> [[X:%.*]], <i32 -4, i32 -8, i32 -16, i32 -32>
+; CHECK-NEXT:    [[ABS:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[AND]], i1 false)
+; CHECK-NEXT:    ret <4 x i32> [[ABS]]
+;
+  %and = and <4 x i32> %x, <i32 -4, i32 -8, i32 -16, i32 -32>
+  %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %and, i1 false)
+  %and2 = and <4 x i32> %abs, <i32 -2, i32 -2, i32 -2, i32 -2>
+  ret <4 x i32> %and2
+}
+
 ; negative test, can't remove the second and based on trailing zeroes.
 ; FIXME: Could remove the first and using demanded bits.
 define i32 @abs_trailing_zeros_negative(i32 %x) {
@@ -52,12 +85,25 @@ define i32 @abs_trailing_zeros_negative(i32 %x) {
   ret i32 %and2
 }
 
+define <4 x i32> @abs_trailing_zeros_negative_vec(<4 x i32> %x) {
+; CHECK-LABEL: @abs_trailing_zeros_negative_vec(
+; CHECK-NEXT:    [[AND:%.*]] = and <4 x i32> [[X:%.*]], <i32 -2, i32 -2, i32 -2, i32 -2>
+; CHECK-NEXT:    [[ABS:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[AND]], i1 false)
+; CHECK-NEXT:    [[AND2:%.*]] = and <4 x i32> [[ABS]], <i32 -4, i32 -4, i32 -4, i32 -4>
+; CHECK-NEXT:    ret <4 x i32> [[AND2]]
+;
+  %and = and <4 x i32> %x, <i32 -2, i32 -2, i32 -2, i32 -2>
+  %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %and, i1 false)
+  %and2 = and <4 x i32> %abs, <i32 -4, i32 -4, i32 -4, i32 -4>
+  ret <4 x i32> %and2
+}
+
 ; Make sure we infer this add doesn't overflow. The input to the abs has 3
 ; sign bits, the abs reduces this to 2 sign bits.
 define i32 @abs_signbits(i30 %x) {
 ; CHECK-LABEL: @abs_signbits(
-; CHECK-NEXT:    [[AND:%.*]] = sext i30 [[X:%.*]] to i32
-; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[AND]], i1 false)
+; CHECK-NEXT:    [[EXT:%.*]] = sext i30 [[X:%.*]] to i32
+; CHECK-NEXT:    [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[EXT]], i1 false)
 ; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[ABS]], 1
 ; CHECK-NEXT:    ret i32 [[ADD]]
 ;
@@ -66,3 +112,56 @@ define i32 @abs_signbits(i30 %x) {
   %add = add i32 %abs, 1
   ret i32 %add
 }
+
+define <4 x i32> @abs_signbits_vec(<4 x i30> %x) {
+; CHECK-LABEL: @abs_signbits_vec(
+; CHECK-NEXT:    [[EXT:%.*]] = sext <4 x i30> [[X:%.*]] to <4 x i32>
+; CHECK-NEXT:    [[ABS:%.*]] = call <4 x i32> @llvm.abs.v4i32(<4 x i32> [[EXT]], i1 false)
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw <4 x i32> [[ABS]], <i32 1, i32 1, i32 1, i32 1>
+; CHECK-NEXT:    ret <4 x i32> [[ADD]]
+;
+  %ext = sext <4 x i30> %x to <4 x i32>
+  %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %ext, i1 false)
+  %add = add <4 x i32> %abs, <i32 1, i32 1, i32 1, i32 1>
+  ret <4 x i32> %add
+}
+
+define i1 @abs_known_positive_input_compare(i31 %x) {
+; CHECK-LABEL: @abs_known_positive_input_compare(
+; CHECK-NEXT:    ret i1 true
+;
+  %zext = zext i31 %x to i32
+  %abs = call i32 @llvm.abs.i32(i32 %zext, i1 false)
+  %c2 = icmp sge i32 %abs, 0
+  ret i1 %c2
+}
+
+define <4 x i1> @abs_known_positive_input_compare_vec(<4 x i31> %x) {
+; CHECK-LABEL: @abs_known_positive_input_compare_vec(
+; CHECK-NEXT:    ret <4 x i1> <i1 true, i1 true, i1 true, i1 true>
+;
+  %zext = zext <4 x i31> %x to <4 x i32>
+  %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %zext, i1 false)
+  %c2 = icmp sge <4 x i32> %abs, zeroinitializer
+  ret <4 x i1> %c2
+}
+
+define i1 @abs_known_not_int_min(i32 %x) {
+; CHECK-LABEL: @abs_known_not_int_min(
+; CHECK-NEXT:    ret i1 true
+;
+  %or = or i32 %x, 1
+  %abs = call i32 @llvm.abs.i32(i32 %or, i1 false)
+  %c2 = icmp sge i32 %abs, 0
+  ret i1 %c2
+}
+
+define <4 x i1> @abs_known_not_int_min_vec(<4 x i32> %x) {
+; CHECK-LABEL: @abs_known_not_int_min_vec(
+; CHECK-NEXT:    ret <4 x i1> <i1 true, i1 true, i1 true, i1 true>
+;
+  %or = or <4 x i32> %x, <i32 1, i32 1, i32 1, i32 1>
+  %abs = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %or, i1 false)
+  %c2 = icmp sge <4 x i32> %abs, zeroinitializer
+  ret <4 x i1> %c2
+}


        


More information about the llvm-commits mailing list