Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2959,6 +2959,45 @@ if (matchSimpleRecurrence(&I, PN, Start, Step) && DT.dominates(Step, PN)) return replaceInstUsesWith(I, Builder.CreateOr(Start, Step)); + // (A | B) | (C & D) + if (match(Op0, m_Or(m_Value(A), m_Value(B))) && + match(Op1, m_And(m_Value(C), m_Value(D)))) { + Value *X; + // (C | (A & D)) | (A & B) -> C | ((A & D) | (A & B)) + // (C | (D & A)) | (A & B) -> C | ((D & A) | (A & B)) + // (C | (B & D)) | (A & B) -> C | ((B & D) | (A & B)) + // (C | (D & B)) | (A & B) -> C | ((D & B) | (A & B)) + if (match(B, m_c_BinOp(Instruction::And, m_Specific(C), m_Value(X))) || + match(B, m_c_BinOp(Instruction::And, m_Specific(D), m_Value(X)))) + return BinaryOperator::CreateOr(A, Builder.CreateOr(B, Op1)); + // ((A & D) | C) | (A & B) -> ((A & D) | (A & B)) | C + // ((D & A) | C) | (A & B) -> ((D & A) | (A & B)) | C + // ((B & D) | C) | (A & B) -> ((B & D) | (A & B)) | C + // ((D & B) | C) | (A & B) -> ((D & B) | (A & B)) | C + if (match(A, m_c_BinOp(Instruction::And, m_Specific(C), m_Value(X))) || + match(A, m_c_BinOp(Instruction::And, m_Specific(D), m_Value(X)))) + return BinaryOperator::CreateOr(Builder.CreateOr(A, Op1), B); + } + + // (A & B) | (C | D) + if (match(Op0, m_And(m_Value(A), m_Value(B))) && + match(Op1, m_Or(m_Value(C), m_Value(D)))) { + // (A & B) | (C | (A & D)) -> C | ((A & D) | (A & B)) + // (A & B) | (C | (D & A)) -> C | ((D & A) | (A & B)) + // (A & B) | (C | (B & D)) -> C | ((B & D) | (A & B)) + // (A & B) | (C | (D & B)) -> C | ((D & B) | (A & B)) + if (match(D, m_c_BinOp(Instruction::And, m_Specific(A), m_Value(X))) || + match(D, m_c_BinOp(Instruction::And, m_Specific(B), m_Value(X)))) + return BinaryOperator::CreateOr(C, Builder.CreateOr(Op0, D)); + // (A & B) | ((A & D) | C) -> ((A & D) | (A & B)) | C + // (A & B) | ((D & A) | C) -> ((D & A) | (A & B)) | C + // (A & B) | ((B & D) | C) -> ((B & D) | (A & B)) | C + // (A & B) | ((D & B) | C) -> ((D & B) | (A & B)) | C + if (match(C, m_c_BinOp(Instruction::And, m_Specific(A), m_Value(X))) || + match(C, m_c_BinOp(Instruction::And, m_Specific(B), m_Value(X)))) + return BinaryOperator::CreateOr(Builder.CreateOr(Op0, C), D); + } + return nullptr; } Index: llvm/test/Transforms/InstCombine/and-or.ll =================================================================== --- llvm/test/Transforms/InstCombine/and-or.ll +++ llvm/test/Transforms/InstCombine/and-or.ll @@ -338,22 +338,10 @@ define i64 @or_or_and_complex(i64 %i) { ; CHECK-LABEL: @or_or_and_complex( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[I:%.*]], 8 -; CHECK-NEXT: [[SHL:%.*]] = and i64 [[TMP1]], 71776119061217280 ; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[I]], 8 -; CHECK-NEXT: [[SHL3:%.*]] = and i64 [[TMP2]], -72057594037927936 -; CHECK-NEXT: [[OR:%.*]] = or i64 [[SHL]], [[SHL3]] -; CHECK-NEXT: [[SHL6:%.*]] = and i64 [[TMP1]], 1095216660480 -; CHECK-NEXT: [[OR7:%.*]] = or i64 [[OR]], [[SHL6]] -; CHECK-NEXT: [[SHL10:%.*]] = and i64 [[TMP2]], 280375465082880 -; CHECK-NEXT: [[OR11:%.*]] = or i64 [[OR7]], [[SHL10]] -; CHECK-NEXT: [[SHL14:%.*]] = and i64 [[TMP1]], 16711680 -; CHECK-NEXT: [[OR15:%.*]] = or i64 [[OR11]], [[SHL14]] -; CHECK-NEXT: [[SHL18:%.*]] = and i64 [[TMP2]], 4278190080 -; CHECK-NEXT: [[OR19:%.*]] = or i64 [[OR15]], [[SHL18]] -; CHECK-NEXT: [[AND21:%.*]] = and i64 [[TMP1]], 255 -; CHECK-NEXT: [[OR23:%.*]] = or i64 [[OR19]], [[AND21]] -; CHECK-NEXT: [[SHL26:%.*]] = and i64 [[TMP2]], 65280 -; CHECK-NEXT: [[OR27:%.*]] = or i64 [[OR23]], [[SHL26]] +; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP1]], 71777214294589695 +; CHECK-NEXT: [[TMP4:%.*]] = and i64 [[TMP2]], -71777214294589696 +; CHECK-NEXT: [[OR27:%.*]] = or i64 [[TMP3]], [[TMP4]] ; CHECK-NEXT: ret i64 [[OR27]] ; %1 = lshr i64 %i, 8 @@ -379,10 +367,9 @@ ; (C | (A & D)) | (A & B) define i8 @or_or_and_pat1(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_or_and_pat1( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[A]], [[D:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[OR1]], [[AND1]] +; CHECK-NEXT: [[AND11:%.*]] = or i8 [[D:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND11]], [[A:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -395,10 +382,9 @@ ; (C | (D & A)) | (A & B) define i8 @or_or_and_pat2(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_or_and_pat2( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[D:%.*]], [[A]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[OR1]], [[AND1]] +; CHECK-NEXT: [[AND21:%.*]] = or i8 [[D:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND21]], [[A:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -411,10 +397,9 @@ ; (C | (B & D)) | (A & B) define i8 @or_or_and_pat3(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_or_and_pat3( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[B]], [[D:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[OR1]], [[AND1]] +; CHECK-NEXT: [[AND11:%.*]] = or i8 [[D:%.*]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND11]], [[B:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -427,10 +412,9 @@ ; (C | (D & B)) | (A & B) define i8 @or_or_and_pat4(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_or_and_pat4( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[D:%.*]], [[B]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[OR1]], [[AND1]] +; CHECK-NEXT: [[AND21:%.*]] = or i8 [[D:%.*]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND21]], [[B:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -443,10 +427,9 @@ ; ((A & D) | C) | (A & B) define i8 @or_or_and_pat5(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_or_and_pat5( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[A]], [[D:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[OR1]], [[AND1]] +; CHECK-NEXT: [[AND11:%.*]] = or i8 [[D:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND11]], [[A:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -459,10 +442,9 @@ ; ((D & A) | C) | (A & B) define i8 @or_or_and_pat6(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_or_and_pat6( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[D:%.*]], [[A]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[OR1]], [[AND1]] +; CHECK-NEXT: [[AND21:%.*]] = or i8 [[D:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND21]], [[A:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -475,10 +457,9 @@ ; ((B & D) | C) | (A & B) define i8 @or_or_and_pat7(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_or_and_pat7( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[B]], [[D:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[OR1]], [[AND1]] +; CHECK-NEXT: [[AND11:%.*]] = or i8 [[D:%.*]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND11]], [[B:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -491,10 +472,9 @@ ; ((D & B) | C) | (A & B) define i8 @or_or_and_pat8(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_or_and_pat8( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[D:%.*]], [[B]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[OR1]], [[AND1]] +; CHECK-NEXT: [[AND21:%.*]] = or i8 [[D:%.*]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND21]], [[B:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -507,10 +487,9 @@ ; (A & B) | (C | (A & D)) define i8 @or_and_or_pat1(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_and_or_pat1( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[A]], [[D:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND1]], [[OR1]] +; CHECK-NEXT: [[AND21:%.*]] = or i8 [[B:%.*]], [[D:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND21]], [[A:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -523,10 +502,9 @@ ; (A & B) | (C | (D & A)) define i8 @or_and_or_pat2(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_and_or_pat2( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[D:%.*]], [[A]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND1]], [[OR1]] +; CHECK-NEXT: [[AND21:%.*]] = or i8 [[B:%.*]], [[D:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND21]], [[A:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -539,10 +517,9 @@ ; (A & B) | (C | (B & D)) define i8 @or_and_or_pat3(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_and_or_pat3( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[B]], [[D:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND1]], [[OR1]] +; CHECK-NEXT: [[AND11:%.*]] = or i8 [[A:%.*]], [[D:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND11]], [[B:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -555,10 +532,9 @@ ; (A & B) | (C | (D & B)) define i8 @or_and_or_pat4(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_and_or_pat4( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[D:%.*]], [[B]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND1]], [[OR1]] +; CHECK-NEXT: [[AND11:%.*]] = or i8 [[A:%.*]], [[D:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND11]], [[B:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -571,10 +547,9 @@ ; (A & B) | ((A & D) | C) define i8 @or_and_or_pat5(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_and_or_pat5( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[A]], [[D:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND1]], [[OR1]] +; CHECK-NEXT: [[AND21:%.*]] = or i8 [[B:%.*]], [[D:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND21]], [[A:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -587,10 +562,9 @@ ; (A & B) | ((D & A) | C) define i8 @or_and_or_pat6(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_and_or_pat6( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[D:%.*]], [[A]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND1]], [[OR1]] +; CHECK-NEXT: [[AND21:%.*]] = or i8 [[B:%.*]], [[D:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND21]], [[A:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -603,10 +577,9 @@ ; (A & B) | ((B & D) | C) define i8 @or_and_or_pat7(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_and_or_pat7( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[B]], [[D:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND1]], [[OR1]] +; CHECK-NEXT: [[AND11:%.*]] = or i8 [[A:%.*]], [[D:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND11]], [[B:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b @@ -619,10 +592,9 @@ ; (A & B) | ((D & B) | C) define i8 @or_and_or_pat8(i8 %a, i8 %b, i8 %c, i8 %d) { ; CHECK-LABEL: @or_and_or_pat8( -; CHECK-NEXT: [[AND1:%.*]] = and i8 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i8 [[D:%.*]], [[B]] -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AND2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i8 [[AND1]], [[OR1]] +; CHECK-NEXT: [[AND11:%.*]] = or i8 [[A:%.*]], [[D:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[AND11]], [[B:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = or i8 [[TMP1]], [[C:%.*]] ; CHECK-NEXT: ret i8 [[OR2]] ; %and1 = and i8 %a, %b Index: llvm/test/Transforms/InstCombine/or.ll =================================================================== --- llvm/test/Transforms/InstCombine/or.ll +++ llvm/test/Transforms/InstCombine/or.ll @@ -396,10 +396,8 @@ define <2 x i32> @test30vec(<2 x i32> %A) { ; CHECK-LABEL: @test30vec( -; CHECK-NEXT: [[C:%.*]] = and <2 x i32> [[A:%.*]], -; CHECK-NEXT: [[B:%.*]] = and <2 x i32> [[A]], -; CHECK-NEXT: [[D:%.*]] = or <2 x i32> [[B]], -; CHECK-NEXT: [[E:%.*]] = or <2 x i32> [[D]], [[C]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], +; CHECK-NEXT: [[E:%.*]] = or <2 x i32> [[TMP1]], ; CHECK-NEXT: ret <2 x i32> [[E]] ; %B = or <2 x i32> %A,