Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2436,10 +2436,11 @@ if (Instruction *NV = FoldOpIntoPhi(I)) return NV; } - + BinaryOperator *Op0I = dyn_cast(Op0); BinaryOperator *Op1I = dyn_cast(Op1); if (Op1I) { Value *A, *B; + Value *A1, *B1; if (match(Op1I, m_Or(m_Value(A), m_Value(B)))) { if (A == Op0) { // B^(B|A) == (A|B)^B Op1I->swapOperands(); @@ -2448,6 +2449,15 @@ } else if (B == Op0) { // B^(A|B) == (A|B)^B I.swapOperands(); // Simplified below. std::swap(Op0, Op1); + } else if (Op0I && match(Op0I, m_Xor(m_Value(A1), m_Value(B1)))) { + if (A1 == A && B1 == B) { + I.swapOperands(); // (A^B)^(A|B) == (A|B)^(A^B) + std::swap(Op0, Op1); // Simplified below. + } else if (A1 == B && B1 == A) { + Op1I->swapOperands(); // (A^B)^(B|A) == (A|B)^(A^B) + I.swapOperands(); // Simplied below. + std::swap(Op0, Op1); + } } } else if (match(Op1I, m_And(m_Value(A), m_Value(B))) && Op1I->hasOneUse()){ @@ -2462,17 +2472,25 @@ } } - BinaryOperator *Op0I = dyn_cast(Op0); if (Op0I) { Value *A, *B; + Value *A1, *B1; if (match(Op0I, m_Or(m_Value(A), m_Value(B))) && Op0I->hasOneUse()) { if (A == Op1) // (B|A)^B == (A|B)^B std::swap(A, B); if (B == Op1) // (A|B)^B == A & ~B return BinaryOperator::CreateAnd(A, Builder->CreateNot(Op1)); - } else if (match(Op0I, m_And(m_Value(A), m_Value(B))) && - Op0I->hasOneUse()){ + if (Op1I && match(Op1I, m_Xor(m_Value(A1), m_Value(B1))) && + Op1I->hasOneUse()) { + if ((A == A1 && B == B1) || (A == B1 && B == A1)) { + // (A|B)^(A^B) == A & B + // (A|B)^(B^A) == A & B + return BinaryOperator::CreateAnd(A, B); + } + } + } else if (Op0I && match(Op0I, m_And(m_Value(A), m_Value(B))) && + Op0I->hasOneUse()) { if (A == Op1) // (A&B)^A -> (B&A)^A std::swap(A, B); if (B == Op1 && // (B&A)^A == ~B & A Index: test/Transforms/InstCombine/or-xor.ll =================================================================== --- test/Transforms/InstCombine/or-xor.ll +++ test/Transforms/InstCombine/or-xor.ll @@ -136,3 +136,13 @@ ; CHECK-NEXT: %and = and i32 %x, %y ; CHECK-NEXT: ret i32 %and } + +define i32 @test15(i32 %x, i32 %y) #0 { + %1 = xor i32 %y, %x + %2 = or i32 %y, %x + %3 = xor i32 %2, %1 + ret i32 %3 +; CHECK-LABEL: @test15( +; CHECK-NEXT: %1 = and i32 %y, %x +; CHECK-NEXT: ret i32 %1 +}