diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-09-04 23:22:13 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-09-04 23:22:13 +0000 |
commit | 63cf26cf019ccffe107b78e57f2b1417ac7a8123 (patch) | |
tree | b10fa0cd716a6e96af908a98baf5c2884e3fa247 /llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | |
parent | 412f24dd2d987973b0b3be40957574e682bf1530 (diff) | |
download | bcm5719-llvm-63cf26cf019ccffe107b78e57f2b1417ac7a8123.tar.gz bcm5719-llvm-63cf26cf019ccffe107b78e57f2b1417ac7a8123.zip |
[InstCombine] fix xor-or-xor fold to check uses and handle commutes
I'm probably missing some way to use m_Deferred to remove the code
duplication, but that can be a follow-up.
The improvement in demand_shrink_nsw.ll is an example of missing
the fold because the pattern matching was deficient. I didn't try
to follow the bits in that test, but Alive says it's correct:
https://rise4fun.com/Alive/ugc
llvm-svn: 341426
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 53 |
1 files changed, 21 insertions, 32 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 202ec074e58..9e6f09dab3c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2791,41 +2791,30 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { match(Op0, m_OneUse(m_c_And(m_Value(X), m_Specific(Op1))))) return BinaryOperator::CreateAnd(Op1, Builder.CreateNot(X)); - { - Value *A, *B, *C, *D; - // (A ^ C)^(A | B) -> ((~A) & B) ^ C - if (match(Op0, m_Xor(m_Value(D), m_Value(C))) && - match(Op1, m_Or(m_Value(A), m_Value(B)))) { - if (D == A) - return BinaryOperator::CreateXor( - Builder.CreateAnd(Builder.CreateNot(A), B), C); - if (D == B) - return BinaryOperator::CreateXor( - Builder.CreateAnd(Builder.CreateNot(B), A), C); - } - // (A | B)^(A ^ C) -> ((~A) & B) ^ C - if (match(Op0, m_Or(m_Value(A), m_Value(B))) && - match(Op1, m_Xor(m_Value(D), m_Value(C)))) { - if (D == A) - return BinaryOperator::CreateXor( - Builder.CreateAnd(Builder.CreateNot(A), B), C); - if (D == B) - return BinaryOperator::CreateXor( - Builder.CreateAnd(Builder.CreateNot(B), A), C); - } - // (A & B) ^ (A ^ B) -> (A | B) - if (match(Op0, m_And(m_Value(A), m_Value(B))) && - match(Op1, m_c_Xor(m_Specific(A), m_Specific(B)))) - return BinaryOperator::CreateOr(A, B); - // (A ^ B) ^ (A & B) -> (A | B) - if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && - match(Op1, m_c_And(m_Specific(A), m_Specific(B)))) - return BinaryOperator::CreateOr(A, B); - } + Value *A, *B, *C; + // (A ^ B) ^ (A | C) --> (~A & C) ^ B -- There are 4 commuted variants. + if (match(&I, m_c_Xor(m_OneUse(m_Xor(m_Value(A), m_Value(B))), + m_OneUse(m_c_Or(m_Deferred(A), m_Value(C)))))) + return BinaryOperator::CreateXor( + Builder.CreateAnd(Builder.CreateNot(A), C), B); + + // (A ^ B) ^ (B | C) --> (~B & C) ^ A -- There are 4 commuted variants. + if (match(&I, m_c_Xor(m_OneUse(m_Xor(m_Value(A), m_Value(B))), + m_OneUse(m_c_Or(m_Deferred(B), m_Value(C)))))) + return BinaryOperator::CreateXor( + Builder.CreateAnd(Builder.CreateNot(B), C), A); + + // (A & B) ^ (A ^ B) -> (A | B) + if (match(Op0, m_And(m_Value(A), m_Value(B))) && + match(Op1, m_c_Xor(m_Specific(A), m_Specific(B)))) + return BinaryOperator::CreateOr(A, B); + // (A ^ B) ^ (A & B) -> (A | B) + if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && + match(Op1, m_c_And(m_Specific(A), m_Specific(B)))) + return BinaryOperator::CreateOr(A, B); // (A & ~B) ^ ~A -> ~(A & B) // (~B & A) ^ ~A -> ~(A & B) - Value *A, *B; if (match(Op0, m_c_And(m_Value(A), m_Not(m_Value(B)))) && match(Op1, m_Not(m_Specific(A)))) return BinaryOperator::CreateNot(Builder.CreateAnd(A, B)); |