Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1230,9 +1230,10 @@ // (A | ~B) & (B | ~A) --> ~(A ^ B) // (~B | A) & (~A | B) --> ~(A ^ B) // (~B | A) & (B | ~A) --> ~(A ^ B) - if (match(Op0, m_c_Or(m_Value(A), m_Not(m_Value(B)))) && - match(Op1, m_c_Or(m_Not(m_Specific(A)), m_Specific(B)))) - return BinaryOperator::CreateNot(Builder.CreateXor(A, B)); + if (Op0->hasOneUse() || Op1->hasOneUse()) + if (match(Op0, m_c_Or(m_Value(A), m_Not(m_Value(B)))) && + match(Op1, m_c_Or(m_Not(m_Specific(A)), m_Specific(B)))) + return BinaryOperator::CreateNot(Builder.CreateXor(A, B)); return nullptr; } @@ -1247,9 +1248,10 @@ // Operand complexity canonicalization guarantees that the 'and' is Op0. // (A & B) | ~(A | B) --> ~(A ^ B) // (A & B) | ~(B | A) --> ~(A ^ B) - if (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)); + if (Op0->hasOneUse() || Op1->hasOneUse()) + if (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)); // (A & ~B) | (~A & B) --> A ^ B // (A & ~B) | (B & ~A) --> A ^ B Index: llvm/trunk/test/Transforms/InstCombine/and-or-not.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/and-or-not.ll +++ llvm/trunk/test/Transforms/InstCombine/and-or-not.ll @@ -527,8 +527,7 @@ ; CHECK-NEXT: [[NOTB:%.*]] = xor i32 [[B]], -1 ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOTA]], [[B]] ; CHECK-NEXT: [[OR2:%.*]] = or i32 [[NOTB]], [[A]] -; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[A]] -; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[OR1]], [[OR2]] ; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[OR1]], [[OR2]] ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], [[AND]] ; CHECK-NEXT: ret i32 [[MUL2]] @@ -552,8 +551,7 @@ ; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[OR:%.*]] = or i32 [[A]], [[B]] ; CHECK-NEXT: [[NOTOR:%.*]] = xor i32 [[OR]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND]], [[NOTOR]] ; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[AND]], [[NOTOR]] ; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], [[OR2]] ; CHECK-NEXT: ret i32 [[MUL2]]