Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1988,6 +1988,16 @@ return BinaryOperator::CreateXor(NOr, C1); } + // ((~A & B) | A) -> (A | B) + if (match(Op0, m_And(m_Not(m_Value(A)), m_Value(B))) && + match(Op1, m_Specific(A))) + return BinaryOperator::CreateOr(A, B); + + // ((A & B) | ~A) -> (~A | B) + if (match(Op0, m_And(m_Value(A), m_Value(B))) && + match(Op1, m_Not(m_Specific(A)))) + return BinaryOperator::CreateOr(Builder->CreateNot(A), B); + // (A & C)|(B & D) Value *C = nullptr, *D = nullptr; if (match(Op0, m_And(m_Value(A), m_Value(C))) && Index: llvm/trunk/test/Transforms/InstCombine/or.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/or.ll +++ llvm/trunk/test/Transforms/InstCombine/or.ll @@ -408,3 +408,22 @@ %or = or i32 %x, %sext ret i32 %or } + +define i32 @test39(i32 %a, i32 %b) { +; CHECK-LABEL: test39( +; CHECK-NEXT: %or = or i32 %a, %b + %xor = xor i32 %a, -1 + %and = and i32 %xor, %b + %or = or i32 %and, %a + ret i32 %or +} + +define i32 @test40(i32 %a, i32 %b) { +; CHECK-LABEL: test40( +; CHECK-NEXT: %1 = xor i32 %a, -1 +; CHECK-NEXT: %or = or i32 %1, %b + %and = and i32 %a, %b + %xor = xor i32 %a, -1 + %or = or i32 %and, %xor + ret i32 %or +}