summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-06-15 05:58:24 +0000
committerChris Lattner <sabre@nondot.org>2007-06-15 05:58:24 +0000
commit481e28b1f54ff5ef3879e283092a0fce40b151fb (patch)
tree0d76c5b79ef21f99f1fc5f8ca1f6ee613a70988d /llvm/lib/Transforms
parenta8de4cccd9de837cbec9db406448d70a1353b2e1 (diff)
downloadbcm5719-llvm-481e28b1f54ff5ef3879e283092a0fce40b151fb.tar.gz
bcm5719-llvm-481e28b1f54ff5ef3879e283092a0fce40b151fb.zip
Implement two xforms:
1. ~(~X | Y) === (X & ~Y) 2. (A|B) & ~(A&B) -> A^B This allows us to transform ~(~(a|b) | (a&b)) -> a^b. This implements PR1510 for scalar values. llvm-svn: 37584
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/InstructionCombining.cpp32
1 files changed, 26 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
index bab6616deda..546f0f2709d 100644
--- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -3363,13 +3363,28 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
}
{
- Value *A = 0, *B = 0;
- if (match(Op0, m_Or(m_Value(A), m_Value(B))))
+ Value *A = 0, *B = 0, *C = 0, *D = 0;
+ if (match(Op0, m_Or(m_Value(A), m_Value(B)))) {
if (A == Op1 || B == Op1) // (A | ?) & A --> A
return ReplaceInstUsesWith(I, Op1);
- if (match(Op1, m_Or(m_Value(A), m_Value(B))))
+
+ // (A|B) & ~(A&B) -> A^B
+ if (match(Op1, m_Not(m_And(m_Value(C), m_Value(D))))) {
+ if ((A == C && B == D) || (A == D && B == C))
+ return BinaryOperator::createXor(A, B);
+ }
+ }
+
+ if (match(Op1, m_Or(m_Value(A), m_Value(B)))) {
if (A == Op0 || B == Op0) // A & (A | ?) --> A
return ReplaceInstUsesWith(I, Op0);
+
+ // ~(A&B) & (A|B) -> A^B
+ if (match(Op0, m_Not(m_And(m_Value(C), m_Value(D))))) {
+ if ((A == C && B == D) || (A == D && B == C))
+ return BinaryOperator::createXor(A, B);
+ }
+ }
if (Op0->hasOneUse() &&
match(Op0, m_Xor(m_Value(A), m_Value(B)))) {
@@ -4137,15 +4152,20 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
return BinaryOperator::createAdd(Op0I->getOperand(1), ConstantRHS);
}
- // ~(~X & Y) --> (X | ~Y)
- if (Op0I->getOpcode() == Instruction::And && RHS->isAllOnesValue()) {
+ // ~(~X & Y) --> (X | ~Y) - De Morgan's Law
+ // ~(~X | Y) === (X & ~Y) - De Morgan's Law
+ if ((Op0I->getOpcode() == Instruction::And ||
+ Op0I->getOpcode() == Instruction::Or) && RHS->isAllOnesValue()) {
if (dyn_castNotVal(Op0I->getOperand(1))) Op0I->swapOperands();
if (Value *Op0NotVal = dyn_castNotVal(Op0I->getOperand(0))) {
Instruction *NotY =
BinaryOperator::createNot(Op0I->getOperand(1),
Op0I->getOperand(1)->getName()+".not");
InsertNewInstBefore(NotY, I);
- return BinaryOperator::createOr(Op0NotVal, NotY);
+ if (Op0I->getOpcode() == Instruction::And)
+ return BinaryOperator::createOr(Op0NotVal, NotY);
+ else
+ return BinaryOperator::createAnd(Op0NotVal, NotY);
}
}
OpenPOWER on IntegriCloud