diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index b83d3c64150..64708c4d4f7 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2124,6 +2124,10 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { 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_Specific(Op1), m_Value(C)), m_Value(A)))) + return BinaryOperator::CreateOr(Op1, 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)) diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll index 2fcdfa5f8ce..5d6ca9603f7 100644 --- a/test/Transforms/InstCombine/or.ll +++ b/test/Transforms/InstCombine/or.ll @@ -469,3 +469,14 @@ define i32 @test44(i32 %a, i32 %b) { %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 +}