[llvm] r368195 - [ValueTracking] When calculating known bits for integer abs, make sure we're looking at a negate and not just any instruction with the nsw flag set.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 7 11:28:16 PDT 2019


Author: ctopper
Date: Wed Aug  7 11:28:16 2019
New Revision: 368195

URL: http://llvm.org/viewvc/llvm-project?rev=368195&view=rev
Log:
[ValueTracking] When calculating known bits for integer abs, make sure we're looking at a negate and not just any instruction with the nsw flag set.

The matchSelectPattern code can match patterns like (x >= 0) ? x : -x
for absolute value. But it can also match ((x-y) >= 0) ? (x-y) : (y-x).
If the latter form was matched we can only use the nsw flag if its
set on both subtracts.

This match makes sure we're looking at the former case only.

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

Modified:
    llvm/trunk/lib/Analysis/ValueTracking.cpp
    llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=368195&r1=368194&r2=368195&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Wed Aug  7 11:28:16 2019
@@ -1095,7 +1095,8 @@ static void computeKnownBitsFromOperator
       // RHS from matchSelectPattern returns the negation part of abs pattern.
       // If the negate has an NSW flag we can assume the sign bit of the result
       // will be 0 because that makes abs(INT_MIN) undefined.
-      if (Q.IIQ.hasNoSignedWrap(cast<Instruction>(RHS)))
+      if (match(RHS, m_Neg(m_Specific(LHS))) &&
+          Q.IIQ.hasNoSignedWrap(cast<Instruction>(RHS)))
         MaxHighZeros = 1;
     }
 
@@ -5611,7 +5612,7 @@ static void setLimitsForIntrinsic(const
 }
 
 static void setLimitsForSelectPattern(const SelectInst &SI, APInt &Lower,
-                                      APInt &Upper) {
+                                      APInt &Upper, const InstrInfoQuery &IIQ) {
   const Value *LHS, *RHS;
   SelectPatternResult R = matchSelectPattern(&SI, LHS, RHS);
   if (R.Flavor == SPF_UNKNOWN)
@@ -5624,7 +5625,8 @@ static void setLimitsForSelectPattern(co
     // then the result of abs(X) is [0..SIGNED_MAX],
     // otherwise it is [0..SIGNED_MIN], as -SIGNED_MIN == SIGNED_MIN.
     Lower = APInt::getNullValue(BitWidth);
-    if (cast<Instruction>(RHS)->hasNoSignedWrap())
+    if (match(RHS, m_Neg(m_Specific(LHS))) &&
+        IIQ.hasNoSignedWrap(cast<Instruction>(RHS)))
       Upper = APInt::getSignedMaxValue(BitWidth) + 1;
     else
       Upper = APInt::getSignedMinValue(BitWidth) + 1;
@@ -5678,7 +5680,7 @@ ConstantRange llvm::computeConstantRange
   else if (auto *II = dyn_cast<IntrinsicInst>(V))
     setLimitsForIntrinsic(*II, Lower, Upper);
   else if (auto *SI = dyn_cast<SelectInst>(V))
-    setLimitsForSelectPattern(*SI, Lower, Upper);
+    setLimitsForSelectPattern(*SI, Lower, Upper, IIQ);
 
   ConstantRange CR = ConstantRange::getNonEmpty(Lower, Upper);
 

Modified: llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll?rev=368195&r1=368194&r2=368195&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll Wed Aug  7 11:28:16 2019
@@ -404,7 +404,12 @@ define i1 @nabs_no_intersection(i32 %a)
 ; We can't fold this to false unless both subs have nsw.
 define i1 @abs_sub_sub_missing_nsw(i32 %x, i32 %y) {
 ; CHECK-LABEL: @abs_sub_sub_missing_nsw(
-; CHECK-NEXT:    ret i1 false
+; CHECK-NEXT:    [[A:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[B:%.*]] = sub nsw i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 [[A]], -1
+; CHECK-NEXT:    [[D:%.*]] = select i1 [[C]], i32 [[A]], i32 [[B]]
+; CHECK-NEXT:    [[E:%.*]] = icmp slt i32 [[D]], 0
+; CHECK-NEXT:    ret i1 [[E]]
 ;
   %a = sub i32 %x, %y
   %b = sub nsw i32 %y, %x




More information about the llvm-commits mailing list