summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
diff options
context:
space:
mode:
authorCraig Topper <craig.topper@intel.com>2017-07-02 01:15:51 +0000
committerCraig Topper <craig.topper@intel.com>2017-07-02 01:15:51 +0000
commitf60ab47098c4768014ac4b761a6df41cb0cc0d5e (patch)
treedc46dfe4f3fb5897153abf2e13f5b738797d2ce9 /llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
parente3f7dda1fb57e8810e4757dea0fed3917666ef24 (diff)
downloadbcm5719-llvm-f60ab47098c4768014ac4b761a6df41cb0cc0d5e.tar.gz
bcm5719-llvm-f60ab47098c4768014ac4b761a6df41cb0cc0d5e.zip
[InstCombine] Fold (a | b) ^ (~a | ~b) --> ~(a ^ b) and (a & b) ^ (~a & ~b) --> ~(a ^ b)
Summary: I came across this while thinking about what would happen if one of the operands in this xor pattern was itself a inverted (A & ~B) ^ (~A & B)-> (A^B). The patterns here assume that the (~a | ~b) will be demorganed to ~(a & b) first. Though I wonder if there's a multiple use case that would prevent the demorgan. Reviewers: spatel Reviewed By: spatel Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D34870 llvm-svn: 306967
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp20
1 files changed, 18 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index db98be2c98f..53f61d6a9c7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2276,7 +2276,8 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
/// A ^ B can be specified using other logic ops in a variety of patterns. We
/// can fold these early and efficiently by morphing an existing instruction.
-static Instruction *foldXorToXor(BinaryOperator &I) {
+static Instruction *foldXorToXor(BinaryOperator &I,
+ InstCombiner::BuilderTy &Builder) {
assert(I.getOpcode() == Instruction::Xor);
Value *Op0 = I.getOperand(0);
Value *Op1 = I.getOperand(1);
@@ -2323,6 +2324,21 @@ static Instruction *foldXorToXor(BinaryOperator &I) {
return &I;
}
+ // For the remaining cases we need to get rid of one of the operands.
+ if (!Op0->hasOneUse() && !Op1->hasOneUse())
+ return nullptr;
+
+ // (A | B) ^ ~(A & B) -> ~(A ^ B)
+ // (A | B) ^ ~(B & A) -> ~(A ^ B)
+ // (A & B) ^ ~(A | B) -> ~(A ^ B)
+ // (A & B) ^ ~(B | A) -> ~(A ^ B)
+ // Complexity sorting ensures the not will be on the right side.
+ if ((match(Op0, m_Or(m_Value(A), m_Value(B))) &&
+ match(Op1, m_Not(m_c_And(m_Specific(A), m_Specific(B))))) ||
+ (match(Op0, m_And(m_Value(A), m_Value(B))) &&
+ match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B))))))
+ return BinaryOperator::CreateNot(Builder.CreateXor(A, B));
+
return nullptr;
}
@@ -2381,7 +2397,7 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) {
if (Value *V = SimplifyXorInst(Op0, Op1, SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V);
- if (Instruction *NewXor = foldXorToXor(I))
+ if (Instruction *NewXor = foldXorToXor(I, *Builder))
return NewXor;
// (A&B)^(A&C) -> A&(B^C) etc
OpenPOWER on IntegriCloud