summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp13
-rw-r--r--test/Transforms/InstCombine/2010-01-28-NegativeSRem.ll19
2 files changed, 30 insertions, 2 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 74a1b6803d..ec1ed66496 100644
--- a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -681,10 +681,19 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
LHSKnownZero, LHSKnownOne, Depth+1))
return I;
+ // The low bits of LHS are unchanged by the srem.
+ KnownZero |= LHSKnownZero & LowBits;
+ KnownOne |= LHSKnownOne & LowBits;
+
+ // If LHS is non-negative or has all low bits zero, then the upper bits
+ // are all zero.
if (LHSKnownZero[BitWidth-1] || ((LHSKnownZero & LowBits) == LowBits))
- LHSKnownZero |= ~LowBits;
+ KnownZero |= ~LowBits;
- KnownZero |= LHSKnownZero & DemandedMask;
+ // If LHS is negative and not all low bits are zero, then the upper bits
+ // are all one.
+ if (LHSKnownOne[BitWidth-1] && ((LHSKnownOne & LowBits) != 0))
+ KnownOne |= ~LowBits;
assert(!(KnownZero & KnownOne) && "Bits known to be one AND zero?");
}
diff --git a/test/Transforms/InstCombine/2010-01-28-NegativeSRem.ll b/test/Transforms/InstCombine/2010-01-28-NegativeSRem.ll
new file mode 100644
index 0000000000..4ab9bf0c3f
--- /dev/null
+++ b/test/Transforms/InstCombine/2010-01-28-NegativeSRem.ll
@@ -0,0 +1,19 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+; PR6165
+
+define i32 @f() {
+entry:
+ br label %BB1
+
+BB1: ; preds = %BB1, %entry
+; CHECK: BB1:
+ %x = phi i32 [ -29, %entry ], [ 0, %BB1 ] ; <i32> [#uses=2]
+ %rem = srem i32 %x, 2 ; <i32> [#uses=1]
+ %t = icmp eq i32 %rem, -1 ; <i1> [#uses=1]
+ br i1 %t, label %BB2, label %BB1
+; CHECK-NOT: br i1 false
+
+BB2: ; preds = %BB1
+; CHECK: BB2:
+ ret i32 %x
+}