[llvm] r284649 - [InstSimplify] fold negation of sign-bit

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 19 14:23:46 PDT 2016


Author: spatel
Date: Wed Oct 19 16:23:45 2016
New Revision: 284649

URL: http://llvm.org/viewvc/llvm-project?rev=284649&view=rev
Log:
[InstSimplify] fold negation of sign-bit

0 - X --> X, if X is 0 or the minimum signed value
0 - X --> 0, if X is 0 or the minimum signed value and the sub is NSW

I noticed this pattern might be created in the backend after the change from D25485, 
so we'll want to add a similar fold for the DAG.

The use of computeKnownBits in InstSimplify may be something to investigate if the
compile time of InstSimplify is noticeable. We could replace computeKnownBits with 
specific pattern matchers or limit the recursion.

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

Modified:
    llvm/trunk/lib/Analysis/InstructionSimplify.cpp
    llvm/trunk/test/Transforms/InstSimplify/negate.ll

Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=284649&r1=284648&r2=284649&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Wed Oct 19 16:23:45 2016
@@ -680,9 +680,26 @@ static Value *SimplifySubInst(Value *Op0
   if (Op0 == Op1)
     return Constant::getNullValue(Op0->getType());
 
-  // 0 - X -> 0 if the sub is NUW.
-  if (isNUW && match(Op0, m_Zero()))
-    return Op0;
+  // Is this a negation?
+  if (match(Op0, m_Zero())) {
+    // 0 - X -> 0 if the sub is NUW.
+    if (isNUW)
+      return Op0;
+
+    unsigned BitWidth = Op1->getType()->getScalarSizeInBits();
+    APInt KnownZero(BitWidth, 0);
+    APInt KnownOne(BitWidth, 0);
+    computeKnownBits(Op1, KnownZero, KnownOne, Q.DL, 0, Q.AC, Q.CxtI, Q.DT);
+    if (KnownZero == ~APInt::getSignBit(BitWidth)) {
+      // Op1 is either 0 or the minimum signed value. If the sub is NSW, then
+      // Op1 must be 0 because negating the minimum signed value is undefined.
+      if (isNSW)
+        return Op0;
+
+      // 0 - X -> X if X is 0 or the minimum signed value.
+      return Op1;
+    }
+  }
 
   // (X + Y) - Z -> X + (Y - Z) or Y + (X - Z) if everything simplifies.
   // For example, (X + Y) - Y -> X; (Y + X) - Y -> X

Modified: llvm/trunk/test/Transforms/InstSimplify/negate.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/negate.ll?rev=284649&r1=284648&r2=284649&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/negate.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/negate.ll Wed Oct 19 16:23:45 2016
@@ -19,9 +19,7 @@ define <2 x i32> @negate_nuw_vec(<2 x i3
 
 define i8 @negate_zero_or_minsigned_nsw(i8 %x) {
 ; CHECK-LABEL: @negate_zero_or_minsigned_nsw(
-; CHECK-NEXT:    [[SIGNBIT:%.*]] = and i8 %x, -128
-; CHECK-NEXT:    [[NEG:%.*]] = sub nsw i8 0, [[SIGNBIT]]
-; CHECK-NEXT:    ret i8 [[NEG]]
+; CHECK-NEXT:    ret i8 0
 ;
   %signbit = and i8 %x, 128
   %neg = sub nsw i8 0, %signbit
@@ -30,9 +28,7 @@ define i8 @negate_zero_or_minsigned_nsw(
 
 define <2 x i8> @negate_zero_or_minsigned_nsw_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @negate_zero_or_minsigned_nsw_vec(
-; CHECK-NEXT:    [[SIGNBIT:%.*]] = shl <2 x i8> %x, <i8 7, i8 7>
-; CHECK-NEXT:    [[NEG:%.*]] = sub nsw <2 x i8> zeroinitializer, [[SIGNBIT]]
-; CHECK-NEXT:    ret <2 x i8> [[NEG]]
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
 ;
   %signbit = shl <2 x i8> %x, <i8 7, i8 7>
   %neg = sub nsw <2 x i8> zeroinitializer, %signbit
@@ -42,8 +38,7 @@ define <2 x i8> @negate_zero_or_minsigne
 define i8 @negate_zero_or_minsigned(i8 %x) {
 ; CHECK-LABEL: @negate_zero_or_minsigned(
 ; CHECK-NEXT:    [[SIGNBIT:%.*]] = shl i8 %x, 7
-; CHECK-NEXT:    [[NEG:%.*]] = sub i8 0, [[SIGNBIT]]
-; CHECK-NEXT:    ret i8 [[NEG]]
+; CHECK-NEXT:    ret i8 [[SIGNBIT]]
 ;
   %signbit = shl i8 %x, 7
   %neg = sub i8 0, %signbit
@@ -53,8 +48,7 @@ define i8 @negate_zero_or_minsigned(i8 %
 define <2 x i8> @negate_zero_or_minsigned_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @negate_zero_or_minsigned_vec(
 ; CHECK-NEXT:    [[SIGNBIT:%.*]] = and <2 x i8> %x, <i8 -128, i8 -128>
-; CHECK-NEXT:    [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[SIGNBIT]]
-; CHECK-NEXT:    ret <2 x i8> [[NEG]]
+; CHECK-NEXT:    ret <2 x i8> [[SIGNBIT]]
 ;
   %signbit = and <2 x i8> %x, <i8 128, i8 128>
   %neg = sub <2 x i8> zeroinitializer, %signbit




More information about the llvm-commits mailing list