Teach ComputeMaskedBits about sub nsw.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127548 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index 6c33d2d..c36f68c 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -431,16 +431,24 @@
     }
 
     // Are we still trying to solve for the sign bit?
-    if (I->getOpcode() == Instruction::Add &&
-        Mask.isNegative() && !KnownZero.isNegative() && !KnownOne.isNegative()){
+    if (Mask.isNegative() && !KnownZero.isNegative() && !KnownOne.isNegative()){
       OverflowingBinaryOperator *OBO = cast<OverflowingBinaryOperator>(I);
       if (OBO->hasNoSignedWrap()) {
-        // Adding two positive numbers can't wrap into negative ...
-        if (LHSKnownZero.isNegative() && KnownZero2.isNegative())
-          KnownZero |= APInt::getSignBit(BitWidth);
-        // and adding two negative numbers can't wrap into positive.
-        else if (LHSKnownOne.isNegative() && KnownOne2.isNegative())
-          KnownOne |= APInt::getSignBit(BitWidth);
+        if (I->getOpcode() == Instruction::Add) {
+          // Adding two positive numbers can't wrap into negative
+          if (LHSKnownZero.isNegative() && KnownZero2.isNegative())
+            KnownZero |= APInt::getSignBit(BitWidth);
+          // and adding two negative numbers can't wrap into positive.
+          else if (LHSKnownOne.isNegative() && KnownOne2.isNegative())
+            KnownOne |= APInt::getSignBit(BitWidth);
+        } else {
+          // Subtracting a negative number from a positive one can't wrap
+          if (LHSKnownZero.isNegative() && KnownOne2.isNegative())
+            KnownZero |= APInt::getSignBit(BitWidth);
+          // neither can subtracting a positive number from a negative one.
+          else if (LHSKnownOne.isNegative() && KnownZero2.isNegative())
+            KnownOne |= APInt::getSignBit(BitWidth);
+        }
       }
     }
 
diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll
index 75a36b4..d2c564f 100644
--- a/test/Transforms/InstSimplify/compare.ll
+++ b/test/Transforms/InstSimplify/compare.ll
@@ -271,6 +271,29 @@
   %D = icmp slt i32 %C, 0
   ret i1 %D
 }
+
+; CHECK: @srem3
+; CHECK-NEXT: ret i1 false
+define i1 @srem3(i16 %X, i32 %Y) {
+  %A = zext i16 %X to i32
+  %B = or i32 2147483648, %A
+  %C = sub nsw i32 1, %B
+  %D = srem i32 %C, %Y
+  %E = icmp slt i32 %D, 0
+  ret i1 %E
+}
+
+; CHECK: @srem4
+; CHECK-NEXT: ret i1 false
+define i1 @srem4(i16 %X, i32 %Y) {
+  %A = zext i16 %X to i32
+  %B = or i32 2147483648, %A
+  %C = sub nsw i32 %A, %B
+  %D = srem i32 %C, %Y
+  %E = icmp slt i32 %D, 0
+  ret i1 %E
+}
+
 define i1 @udiv1(i32 %X) {
 ; CHECK: @udiv1
   %A = udiv i32 %X, 1000000