Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1621,6 +1621,15 @@ return BinaryOperator::CreateNeg(Y); } + // (sub (or A, B) (and A, B)) --> (xor A, B) + { + Value *A = nullptr, *B = nullptr; + if (match(Op1, m_And(m_Value(A), m_Value(B))) && + (match(Op0, m_Or(m_Specific(A), m_Specific(B))) || + match(Op0, m_Or(m_Specific(B), m_Specific(A))))) + return BinaryOperator::CreateXor(A, B); + } + if (Op1->hasOneUse()) { Value *X = nullptr, *Y = nullptr, *Z = nullptr; Constant *C = nullptr; Index: test/Transforms/InstCombine/sub.ll =================================================================== --- test/Transforms/InstCombine/sub.ll +++ test/Transforms/InstCombine/sub.ll @@ -529,3 +529,13 @@ ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 %x, -32768 ; CHECK: ret i32 [[ADD]] } + +define i32 @test45(i32 %x, i32 %y) { + %or = or i32 %x, %y + %and = and i32 %x, %y + %sub = sub i32 %or, %and + ret i32 %sub +; CHECK-LABEL: @test45( +; CHECK-NEXT: %sub = xor i32 %x, %y +; CHECK:ret i32 %sub +}