Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2124,6 +2124,11 @@ if (Op0->hasOneUse() || cast(Op0)->hasOneUse()) return BinaryOperator::CreateOr(Op1, C); + // ((B | C) & A) | B -> B | (A & C) + if (match(Op0, m_And(m_Or(m_Value(B), m_Value(C)), m_Value(A)))) + if (Op1 == B) + return BinaryOperator::CreateOr(B, Builder->CreateAnd(A, C)); + // (X >> Z) | (Y >> Z) -> (X|Y) >> Z for all shifts. if (BinaryOperator *SI1 = dyn_cast(Op1)) { if (BinaryOperator *SI0 = dyn_cast(Op0)) Index: test/Transforms/InstCombine/or.ll =================================================================== --- test/Transforms/InstCombine/or.ll +++ test/Transforms/InstCombine/or.ll @@ -469,3 +469,14 @@ %or = or i32 %xor, %and ret i32 %or } + +define i32 @test45(i32 %x, i32 %y, i32 %z) { +; CHECK-LABEL: test45( +; CHECK-NEXT: %1 = and i32 %x, %z +; CHECK-NEXT: %or1 = or i32 %1, %y +; CHECK-NEXT: ret i32 %or1 + %or = or i32 %y, %z + %and = and i32 %x, %or + %or1 = or i32 %and, %y + ret i32 %or1 +}