summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2017-05-08 20:49:59 +0000
committerSanjay Patel <spatel@rotateright.com>2017-05-08 20:49:59 +0000
commita1c88148910f71841b3ab1deafb7d1b285a24a07 (patch)
treef044bb2ada370ef0bf52ee1876f8dc9151eab01e
parentaa42a100513a040a2e8276287011a36c7e042e7b (diff)
downloadbcm5719-llvm-a1c88148910f71841b3ab1deafb7d1b285a24a07.tar.gz
bcm5719-llvm-a1c88148910f71841b3ab1deafb7d1b285a24a07.zip
[InstCombine] add folds for not-of-shift-right
This is another step towards getting rid of dyn_castNotVal, so we can recommit: https://reviews.llvm.org/rL300977 As the tests show, we were missing the lshr case for constants and both ashr/lshr vector splat folds. The ashr case with constant was being performed inefficiently in 2 steps. It's also possible there was a latent bug in that case because we can't do that fold if the constant is positive: http://rise4fun.com/Alive/Bge llvm-svn: 302465
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp47
-rw-r--r--llvm/test/Transforms/InstCombine/not.ll22
2 files changed, 48 insertions, 21 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b114801cc1c..417e9136a56 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2399,27 +2399,44 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
}
// Is this a 'not' (~) fed by a binary operator?
- BinaryOperator *NotOp;
- if (match(&I, m_Not(m_BinOp(NotOp)))) {
- if (NotOp->getOpcode() == Instruction::And ||
- NotOp->getOpcode() == Instruction::Or) {
+ BinaryOperator *NotVal;
+ if (match(&I, m_Not(m_BinOp(NotVal)))) {
+ if (NotVal->getOpcode() == Instruction::And ||
+ NotVal->getOpcode() == Instruction::Or) {
// Apply DeMorgan's Law when inverts are free:
// ~(X & Y) --> (~X | ~Y)
// ~(X | Y) --> (~X & ~Y)
- if (IsFreeToInvert(NotOp->getOperand(0),
- NotOp->getOperand(0)->hasOneUse()) &&
- IsFreeToInvert(NotOp->getOperand(1),
- NotOp->getOperand(1)->hasOneUse())) {
- Value *NotX = Builder->CreateNot(NotOp->getOperand(0), "notlhs");
- Value *NotY = Builder->CreateNot(NotOp->getOperand(1), "notrhs");
- if (NotOp->getOpcode() == Instruction::And)
+ if (IsFreeToInvert(NotVal->getOperand(0),
+ NotVal->getOperand(0)->hasOneUse()) &&
+ IsFreeToInvert(NotVal->getOperand(1),
+ NotVal->getOperand(1)->hasOneUse())) {
+ Value *NotX = Builder->CreateNot(NotVal->getOperand(0), "notlhs");
+ Value *NotY = Builder->CreateNot(NotVal->getOperand(1), "notrhs");
+ if (NotVal->getOpcode() == Instruction::And)
return BinaryOperator::CreateOr(NotX, NotY);
return BinaryOperator::CreateAnd(NotX, NotY);
}
- } else if (NotOp->getOpcode() == Instruction::AShr) {
- // ~(~X >>s Y) --> (X >>s Y)
- if (Value *Op0NotVal = dyn_castNotVal(NotOp->getOperand(0)))
- return BinaryOperator::CreateAShr(Op0NotVal, NotOp->getOperand(1));
+ }
+
+ // ~(~X >>s Y) --> (X >>s Y)
+ if (match(NotVal, m_AShr(m_Not(m_Value(X)), m_Value(Y))))
+ return BinaryOperator::CreateAShr(X, Y);
+
+ // If we are inverting a right-shifted constant, we may be able to eliminate
+ // the 'not' by inverting the constant and using the opposite shift type.
+ // Canonicalization rules ensure that only a negative constant uses 'ashr',
+ // but we must check that in case that transform has not fired yet.
+ const APInt *C;
+ if (match(NotVal, m_AShr(m_APInt(C), m_Value(Y))) && C->isNegative()) {
+ // ~(C >>s Y) --> ~C >>u Y (when inverting the replicated sign bits)
+ Constant *NotC = ConstantInt::get(I.getType(), ~(*C));
+ return BinaryOperator::CreateLShr(NotC, Y);
+ }
+
+ if (match(NotVal, m_LShr(m_APInt(C), m_Value(Y))) && C->isNonNegative()) {
+ // ~(C >>u Y) --> ~C >>s Y (when inverting the replicated sign bits)
+ Constant *NotC = ConstantInt::get(I.getType(), ~(*C));
+ return BinaryOperator::CreateAShr(NotC, Y);
}
}
diff --git a/llvm/test/Transforms/InstCombine/not.ll b/llvm/test/Transforms/InstCombine/not.ll
index 9f57b6a2702..6ff0a50318d 100644
--- a/llvm/test/Transforms/InstCombine/not.ll
+++ b/llvm/test/Transforms/InstCombine/not.ll
@@ -79,8 +79,7 @@ define i8 @not_ashr_const(i8 %x) {
define <2 x i8> @not_ashr_const_splat(<2 x i8> %x) {
; CHECK-LABEL: @not_ashr_const_splat(
-; CHECK-NEXT: [[SHR:%.*]] = ashr <2 x i8> <i8 -42, i8 -42>, %x
-; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i8> [[SHR]], <i8 -1, i8 -1>
+; CHECK-NEXT: [[NOT:%.*]] = lshr <2 x i8> <i8 41, i8 41>, %x
; CHECK-NEXT: ret <2 x i8> [[NOT]]
;
%shr = ashr <2 x i8> <i8 -42, i8 -42>, %x
@@ -88,10 +87,22 @@ define <2 x i8> @not_ashr_const_splat(<2 x i8> %x) {
ret <2 x i8> %not
}
+; We can't get rid of the 'not' on a logical shift of a negative constant.
+
+define i8 @not_lshr_const_negative(i8 %x) {
+; CHECK-LABEL: @not_lshr_const_negative(
+; CHECK-NEXT: [[SHR:%.*]] = lshr i8 -42, %x
+; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[SHR]], -1
+; CHECK-NEXT: ret i8 [[NOT]]
+;
+ %shr = lshr i8 -42, %x
+ %not = xor i8 %shr, -1
+ ret i8 %not
+}
+
define i8 @not_lshr_const(i8 %x) {
; CHECK-LABEL: @not_lshr_const(
-; CHECK-NEXT: [[SHR:%.*]] = lshr i8 42, %x
-; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[SHR]], -1
+; CHECK-NEXT: [[NOT:%.*]] = ashr i8 -43, %x
; CHECK-NEXT: ret i8 [[NOT]]
;
%shr = lshr i8 42, %x
@@ -101,8 +112,7 @@ define i8 @not_lshr_const(i8 %x) {
define <2 x i8> @not_lshr_const_splat(<2 x i8> %x) {
; CHECK-LABEL: @not_lshr_const_splat(
-; CHECK-NEXT: [[SHR:%.*]] = lshr <2 x i8> <i8 42, i8 42>, %x
-; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i8> [[SHR]], <i8 -1, i8 -1>
+; CHECK-NEXT: [[NOT:%.*]] = ashr <2 x i8> <i8 -43, i8 -43>, %x
; CHECK-NEXT: ret <2 x i8> [[NOT]]
;
%shr = lshr <2 x i8> <i8 42, i8 42>, %x
OpenPOWER on IntegriCloud