Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1802,8 +1802,8 @@ } } - // (~A & B & C) | ~(A | B | C) -> ~(A | (B ^ C)) - // (~A | B | C) & ~(A & B & C) -> (~A | (B ^ C)) + // (~A & B & C) | ... --> ... + // (~A | B | C) | ... --> ... // TODO: One use checks are conservative. We just need to check that a total // number of multiple used values. if (match(Op0, @@ -1816,6 +1816,8 @@ m_CombineAnd(m_Value(X), m_Not(m_Value(A)))), m_Value(B))))) { // X = ~A + // (~A & B & C) | ~(A | B | C) --> ~(A | (B ^ C)) + // (~A | B | C) & ~(A & B & C) --> (~A | (B ^ C)) if (match(Op1, m_OneUse(m_Not(m_c_BinOp( Opcode, m_c_BinOp(Opcode, m_Specific(A), m_Specific(B)), m_Specific(C))))) || @@ -1830,6 +1832,22 @@ ? BinaryOperator::CreateNot(Builder.CreateOr(Xor, A)) : BinaryOperator::CreateOr(Xor, X); } + + // (~A & B & C) | ~(A | B) --> (C | ~B) & ~A + // (~A | B | C) & ~(A & B) --> (C & ~B) | ~A + if (match(Op1, m_OneUse(m_Not(m_OneUse( + m_c_BinOp(Opcode, m_Specific(A), m_Specific(B))))))) + return BinaryOperator::Create( + FlippedOpcode, Builder.CreateBinOp(Opcode, C, Builder.CreateNot(B)), + X); + + // (~A & B & C) | ~(A | C) --> (B | ~C) & ~A + // (~A | B | C) & ~(A & C) --> (B & ~C) | ~A + if (match(Op1, m_OneUse(m_Not(m_OneUse( + m_c_BinOp(Opcode, m_Specific(A), m_Specific(C))))))) + return BinaryOperator::Create( + FlippedOpcode, Builder.CreateBinOp(Opcode, B, Builder.CreateNot(C)), + X); } return nullptr; Index: llvm/test/Transforms/InstCombine/and-xor-or.ll =================================================================== --- llvm/test/Transforms/InstCombine/and-xor-or.ll +++ llvm/test/Transforms/InstCombine/and-xor-or.ll @@ -3100,12 +3100,10 @@ define i32 @not_and_and_or_no_or(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[OR2]] ; %or1 = or i32 %b, %a @@ -3119,12 +3117,10 @@ define i32 @not_and_and_or_no_or_commute1_and(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or_commute1_and( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[C:%.*]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[NOT2]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[OR2]] ; %or1 = or i32 %b, %a @@ -3138,12 +3134,10 @@ define i32 @not_and_and_or_no_or_commute2_and(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or_commute2_and( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[OR2]] ; %or1 = or i32 %b, %a @@ -3157,12 +3151,10 @@ define i32 @not_and_and_or_no_or_commute1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or_commute1( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[OR2]] ; %or1 = or i32 %a, %b @@ -3177,12 +3169,10 @@ define i32 @not_and_and_or_no_or_commute2(i32 %a, i32 %b0, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or_commute2( ; CHECK-NEXT: [[B:%.*]] = sdiv i32 42, [[B0:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B]], [[NOT2]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[OR2]] ; %b = sdiv i32 42, %b0 ; thwart complexity-based canonicalization @@ -3198,12 +3188,10 @@ define i32 @not_and_and_or_no_or_commute3(i32 %a, i32 %b, i32 %c0) { ; CHECK-LABEL: @not_and_and_or_no_or_commute3( ; CHECK-NEXT: [[C:%.*]] = sdiv i32 42, [[C0:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[C]], [[AND1]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[C]], [[TMP1]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[OR2]] ; %c = sdiv i32 42, %c0 ; thwart complexity-based canonicalization @@ -3218,12 +3206,10 @@ define i32 @not_and_and_or_no_or_use1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or_use1( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[OR2]] ; @@ -3239,12 +3225,10 @@ define i32 @not_and_and_or_no_or_use2(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or_use2( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[NOT2]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[OR2]] ; @@ -3260,12 +3244,10 @@ define i32 @not_and_and_or_no_or_use3(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or_use3( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[OR2]] ; @@ -3281,12 +3263,10 @@ define i32 @not_and_and_or_no_or_use4(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or_use4( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[OR2]] ; @@ -3344,12 +3324,11 @@ define i32 @not_and_and_or_no_or_use7(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_no_or_use7( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[OR2:%.*]] = and i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[AND1]]) ; CHECK-NEXT: ret i32 [[OR2]] ; @@ -3388,12 +3367,10 @@ define i32 @not_or_or_and_no_and(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[OR2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND2]] ; %and1 = and i32 %b, %a @@ -3407,11 +3384,10 @@ define i32 @not_or_or_and_no_and_commute1_or(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and_commute1_or( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[C:%.*]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[NOT2]] -; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[AND1]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND2]] ; %and1 = and i32 %b, %a @@ -3425,11 +3401,10 @@ define i32 @not_or_or_and_no_and_commute2_or(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and_commute2_or( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[AND1]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND2]] ; %and1 = and i32 %b, %a @@ -3443,12 +3418,10 @@ define i32 @not_or_or_and_no_and_commute1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and_commute1( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[OR2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND2]] ; %and1 = and i32 %a, %b @@ -3463,12 +3436,10 @@ define i32 @not_or_or_and_no_and_commute2(i32 %a, i32 %b0, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and_commute2( ; CHECK-NEXT: [[B:%.*]] = sdiv i32 42, [[B0:%.*]] -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B]], [[NOT2]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[OR2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND2]] ; %b = sdiv i32 42, %b0 ; thwart complexity-based canonicalization @@ -3484,12 +3455,10 @@ define i32 @not_or_or_and_no_and_commute3(i32 %a, i32 %b, i32 %c0) { ; CHECK-LABEL: @not_or_or_and_no_and_commute3( ; CHECK-NEXT: [[C:%.*]] = sdiv i32 42, [[C0:%.*]] -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[C]], [[OR1]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[OR2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[C]], [[TMP1]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND2]] ; %c = sdiv i32 42, %c0 ; thwart complexity-based canonicalization @@ -3504,12 +3473,10 @@ define i32 @not_or_or_and_no_and_use1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and_use1( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[OR2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[AND2]] ; @@ -3525,11 +3492,10 @@ define i32 @not_or_or_and_no_and_use2(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and_use2( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[NOT2]] -; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[AND1]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[AND2]] ; @@ -3545,11 +3511,10 @@ define i32 @not_or_or_and_no_and_use3(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and_use3( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[AND1]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[AND2]] ; @@ -3565,11 +3530,10 @@ define i32 @not_or_or_and_no_and_use4(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and_use4( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[AND1]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[AND2]] ; @@ -3627,12 +3591,11 @@ define i32 @not_or_or_and_no_and_use7(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_no_and_use7( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[OR2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], -1 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[C:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = or i32 [[TMP2]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[OR1]]) ; CHECK-NEXT: ret i32 [[AND2]] ;