Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Show First 20 Lines • Show All 974 Lines • ▼ Show 20 Lines | |||||
m_OneUse(m_c_Or(m_Deferred(A), m_Value(C)))))) | m_OneUse(m_c_Or(m_Deferred(A), m_Value(C)))))) | ||||
return BinaryOperator::CreateXor( | return BinaryOperator::CreateXor( | ||||
Builder.CreateAnd(Builder.CreateNot(A), C), B); | Builder.CreateAnd(Builder.CreateNot(A), C), B); | ||||
// (A ^ B) ^ (B | C) --> (~B & C) ^ A -- There are 4 commuted variants. | // (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))), | 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)))))) | m_OneUse(m_c_Or(m_Deferred(B), m_Value(C)))))) | ||||
return BinaryOperator::CreateXor( | return BinaryOperator::CreateXor( | ||||
Builder.CreateAnd(Builder.CreateNot(B), C), A); | Builder.CreateAnd(Builder.CreateNot(B), C), A); | ||||
spatel: What about the case where the `and` is Op1? | |||||
// (A & B) ^ (A ^ B) -> (A | B) | // (A & B) ^ (A ^ B) -> (A | B) | ||||
if (match(Op0, m_And(m_Value(A), m_Value(B))) && | if (match(Op0, m_And(m_Value(A), m_Value(B))) && | ||||
match(Op1, m_c_Xor(m_Specific(A), m_Specific(B)))) | match(Op1, m_c_Xor(m_Specific(A), m_Specific(B)))) | ||||
Not Done ReplyInline ActionsAvoid this. Use if (match(&I, m_c_Xor(......) above. xbolva00: Avoid this.
Use
if (match(&I, m_c_Xor(......)
above. | |||||
Not Done ReplyInline ActionsNow you can remove this fold, since previous check ^ handles commutation. xbolva00: Now you can remove this fold, since previous check ^ handles commutation. | |||||
return BinaryOperator::CreateOr(A, B); | return BinaryOperator::CreateOr(A, B); | ||||
// (A ^ B) ^ (A & B) -> (A | B) | // (A ^ B) ^ (A & B) -> (A | B) | ||||
if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && | if (match(Op0, m_Xor(m_Value(A), m_Value(B))) && | ||||
match(Op1, m_c_And(m_Specific(A), m_Specific(B)))) | match(Op1, m_c_And(m_Specific(A), m_Specific(B)))) | ||||
return BinaryOperator::CreateOr(A, B); | return BinaryOperator::CreateOr(A, B); | ||||
// (A & ~B) ^ ~A -> ~(A & B) | // (A & ~B) ^ ~A -> ~(A & B) | ||||
// (~B & A) ^ ~A -> ~(A & B) | // (~B & A) ^ ~A -> ~(A & B) | ||||
if (match(Op0, m_c_And(m_Value(A), m_Not(m_Value(B)))) && | if (match(Op0, m_c_And(m_Value(A), m_Not(m_Value(B)))) && | ||||
match(Op1, m_Not(m_Specific(A)))) | match(Op1, m_Not(m_Specific(A)))) | ||||
return BinaryOperator::CreateNot(Builder.CreateAnd(A, B)); | return BinaryOperator::CreateNot(Builder.CreateAnd(A, B)); | ||||
// (~A & B) ^ A --> (A | B) -- There are 4 commuted variants. | |||||
if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(A)), m_Value(B)), m_Deferred(A)))) | |||||
return BinaryOperator::CreateOr(A, B); | |||||
// (A | B) ^ (A | C) --> (B ^ C) & ~A -- There are 4 commuted variants. | // (A | B) ^ (A | C) --> (B ^ C) & ~A -- There are 4 commuted variants. | ||||
// TODO: Loosen one-use restriction if common operand is a constant. | // TODO: Loosen one-use restriction if common operand is a constant. | ||||
Value *D; | Value *D; | ||||
if (match(Op0, m_OneUse(m_Or(m_Value(A), m_Value(B)))) && | if (match(Op0, m_OneUse(m_Or(m_Value(A), m_Value(B)))) && | ||||
match(Op1, m_OneUse(m_Or(m_Value(C), m_Value(D))))) { | match(Op1, m_OneUse(m_Or(m_Value(C), m_Value(D))))) { | ||||
if (B == C || B == D) | if (B == C || B == D) | ||||
std::swap(A, B); | std::swap(A, B); | ||||
if (A == C) | if (A == C) | ||||
▲ Show 20 Lines • Show All 105 Lines • Show Last 20 Lines |
What about the case where the and is Op1?