summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2016-10-19 21:23:45 +0000
committerSanjay Patel <spatel@rotateright.com>2016-10-19 21:23:45 +0000
commitefd88857724df8e865fcf6a28103b230971db9de (patch)
tree6a4192d331293660e10e573c726dcdac27793949 /llvm
parent76a2e60e593784314cc87b408796c6b4cd50d810 (diff)
downloadbcm5719-llvm-efd88857724df8e865fcf6a28103b230971db9de.tar.gz
bcm5719-llvm-efd88857724df8e865fcf6a28103b230971db9de.zip
[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 llvm-svn: 284649
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp23
-rw-r--r--llvm/test/Transforms/InstSimplify/negate.ll14
2 files changed, 24 insertions, 13 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 8d6c83b1b8d..1679d3a4667 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -680,9 +680,26 @@ static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
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
diff --git a/llvm/test/Transforms/InstSimplify/negate.ll b/llvm/test/Transforms/InstSimplify/negate.ll
index 9eeb53e0c7d..17eb52d3527 100644
--- a/llvm/test/Transforms/InstSimplify/negate.ll
+++ b/llvm/test/Transforms/InstSimplify/negate.ll
@@ -19,9 +19,7 @@ define <2 x i32> @negate_nuw_vec(<2 x i32> %x) {
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(i8 %x) {
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_minsigned_nsw_vec(<2 x i8> %x) {
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 %x) {
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
OpenPOWER on IntegriCloud