Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2612,6 +2612,22 @@ if (match(Op0I, m_Xor(m_Value(A), m_Value(B))) && match(Op1I, m_And(m_Specific(A), m_Specific(B)))) return BinaryOperator::CreateOr(A, B); + // (A | (B ^ C)) ^ ((A ^ C) ^ B) -> A & (B ^ C) + if (match(Op0I, m_Or(m_Value(A), m_Xor(m_Value(B), m_Value(C)))) && + match(Op1I, m_Xor(m_Xor(m_Specific(A), m_Specific(C)), m_Specific(B)))) + return BinaryOperator::CreateAnd(A, Builder->CreateXor(B,C)); + // ( (B ^ C) | A ) ^ ((A ^ C) ^ B) -> A & (B ^ C) + if (match(Op0I, m_Or(m_Xor(m_Value(B), m_Value(C)), m_Value(A))) && + match(Op1I, m_Xor( m_Xor(m_Specific(A), m_Specific(C)), m_Specific(B)))) + return BinaryOperator::CreateAnd(A, Builder->CreateXor(B,C)); + // ((A ^ B) ^ C) ^ (A | (B ^ C)) -> A & (B ^ C) + if (match(Op0I, m_Xor(m_Xor(m_Value(A), m_Value(B)), m_Value(C))) && + match(Op1I, m_Or(m_Specific(A), m_Xor(m_Specific(B), m_Specific(C))))) + return BinaryOperator::CreateAnd(A, Builder->CreateXor(B,C)); + // ((A ^ B) ^ C) ^ (B ^ C) | A )) -> A & (B ^ C) + if (match(Op0I, m_Xor(m_Xor(m_Value(A), m_Value(B)), m_Value(C))) && + match(Op1I, m_Or(m_Xor(m_Specific(B), m_Specific(C)), m_Specific(A)))) + return BinaryOperator::CreateAnd(A, Builder->CreateXor(B,C)); } // (A | B)^(~A) -> (A | ~B) Index: test/Transforms/InstCombine/or-xor.ll =================================================================== --- test/Transforms/InstCombine/or-xor.ll +++ test/Transforms/InstCombine/or-xor.ll @@ -181,3 +181,31 @@ %xor = or i32 %and1, %and2 ret i32 %xor } + +; (x | (y ^ z)) ^ ((x ^ z) ^ y) -> x & (y ^ z) +define i32 @test19(i32 %x, i32 %y, i32 %z) { + %xor1 = xor i32 %y, %z + %or = or i32 %x, %xor1 + %xor2 = xor i32 %x, %z + %xor3 = xor i32 %xor2, %y + %res = xor i32 %or, %xor3 + ret i32 %res +; CHECK-LABEL: @test19( +; CHECK-NEXT: %1 = xor i32 %y, %z +; CHECK-NEXT: %res = and i32 %1, %x +; CHECK-NEXT: ret i32 %res +} + +; ((x | ~y) ^ (~x ^ y)) -> (x & ~y) +define i32 @test20(i32 %x, i32 %y) { + %noty = xor i32 %y, -1 + %or = or i32 %x, %noty + %notx = xor i32 %x, -1 + %xor = xor i32 %notx, %y + %res = xor i32 %or, %xor + ret i32 %res +; CHECK-LABEL: @test20( +; CHECK-NEXT: %1 = xor i32 %y, -1 +; CHECK-NEXT: %res = and i32 %x, %1 +; CHECK-NEXT: ret i32 %res +}