summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2017-05-01 22:25:42 +0000
committerSanjay Patel <spatel@rotateright.com>2017-05-01 22:25:42 +0000
commit59d0aeaafe275cc20fafca52b21c4610c681a156 (patch)
treefbad8569e2ea7b01c47f2b3ff8e70a52368d0c61 /llvm/lib/Transforms
parent941a20511968ddd8ace9b4ad1296aa7e2c11c206 (diff)
downloadbcm5719-llvm-59d0aeaafe275cc20fafca52b21c4610c681a156.tar.gz
bcm5719-llvm-59d0aeaafe275cc20fafca52b21c4610c681a156.zip
[InstCombine] check one-use before applying DeMorgan nor/nand folds
If we have ~(~X & Y), it only makes sense to transform it to (X | ~Y) when we do not need the intermediate (~X & Y) value. In that case, we would need an extra instruction to generate ~Y + 'or' (as shown in the test changes). It's ok if we have multiple uses of ~X or Y, however. In those cases, we may not reduce the instruction count or critical path, but we might improve throughput because we can generate ~X and ~Y in parallel. Whether that actually makes perf sense or not for a target is something we can't answer in IR. Differential Revision: https://reviews.llvm.org/D32703 llvm-svn: 301848
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp24
1 files changed, 14 insertions, 10 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index e37ceb58f15..41ae37ee127 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2438,16 +2438,20 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
if (match(&I, m_Not(m_BinOp(NotOp)))) {
if (NotOp->getOpcode() == Instruction::And ||
NotOp->getOpcode() == Instruction::Or) {
- // ~(~X & Y) --> (X | ~Y) - De Morgan's Law
- // ~(~X | Y) === (X & ~Y) - De Morgan's Law
- if (dyn_castNotVal(NotOp->getOperand(1)))
- NotOp->swapOperands();
- if (Value *Op0NotVal = dyn_castNotVal(NotOp->getOperand(0))) {
- Value *NotY = Builder->CreateNot(
- NotOp->getOperand(1), NotOp->getOperand(1)->getName() + ".not");
- if (NotOp->getOpcode() == Instruction::And)
- return BinaryOperator::CreateOr(Op0NotVal, NotY);
- return BinaryOperator::CreateAnd(Op0NotVal, NotY);
+ // We must eliminate the and/or for this transform to not increase the
+ // instruction count.
+ if (NotOp->hasOneUse()) {
+ // ~(~X & Y) --> (X | ~Y) - De Morgan's Law
+ // ~(~X | Y) === (X & ~Y) - De Morgan's Law
+ if (dyn_castNotVal(NotOp->getOperand(1)))
+ NotOp->swapOperands();
+ if (Value *Op0NotVal = dyn_castNotVal(NotOp->getOperand(0))) {
+ Value *NotY = Builder->CreateNot(
+ NotOp->getOperand(1), NotOp->getOperand(1)->getName() + ".not");
+ if (NotOp->getOpcode() == Instruction::And)
+ return BinaryOperator::CreateOr(Op0NotVal, NotY);
+ return BinaryOperator::CreateAnd(Op0NotVal, NotY);
+ }
}
// ~(X & Y) --> (~X | ~Y) - De Morgan's Law
OpenPOWER on IntegriCloud