Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1795,6 +1795,37 @@ } } + // (~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 does not exceed reduction + // in operations. + if (match(Op0, + m_OneUse(m_c_BinOp(FlippedOpcode, + m_BinOp(FlippedOpcode, m_Value(B), m_Value(C)), + m_CombineAnd(m_Value(X), m_Not(m_Value(A)))))) || + match(Op0, m_OneUse(m_c_BinOp( + FlippedOpcode, + m_c_BinOp(FlippedOpcode, m_Value(C), + m_CombineAnd(m_Value(X), m_Not(m_Value(A)))), + m_Value(B))))) { + // X = ~A + if (match(Op1, m_OneUse(m_Not(m_c_BinOp( + Opcode, m_c_BinOp(Opcode, m_Specific(A), m_Specific(B)), + m_Specific(C))))) || + match(Op1, m_OneUse(m_Not(m_c_BinOp( + Opcode, m_c_BinOp(Opcode, m_Specific(B), m_Specific(C)), + m_Specific(A))))) || + match(Op1, m_OneUse(m_Not(m_c_BinOp( + Opcode, m_c_BinOp(Opcode, m_Specific(A), m_Specific(C)), + m_Specific(B)))))) { + Value *Xor = Builder.CreateXor(B, C); + return (Opcode == Instruction::Or) + ? BinaryOperator::CreateNot(Builder.CreateOr(Xor, A)) + : BinaryOperator::CreateOr(Xor, 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 @@ -2534,13 +2534,9 @@ define i32 @not_and_and_or_not_or_or(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %b, %a @@ -2555,13 +2551,9 @@ define i32 @not_and_and_or_not_or_or_commute1_or(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or_commute1_or( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[B:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %c, %a @@ -2576,13 +2568,9 @@ define i32 @not_and_and_or_not_or_or_commute2_or(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or_commute2_or( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[A:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %b, %c @@ -2597,13 +2585,9 @@ define i32 @not_and_and_or_not_or_or_commute1_and(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or_commute1_and( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[B]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %b, %a @@ -2618,13 +2602,9 @@ define i32 @not_and_and_or_not_or_or_commute2_and(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or_commute2_and( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[NOT2]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %b, %a @@ -2639,13 +2619,9 @@ define i32 @not_and_and_or_not_or_or_commute1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or_commute1( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %a, %b @@ -2661,13 +2637,9 @@ define i32 @not_and_and_or_not_or_or_commute2(i32 %a, i32 %b, i32 %c0) { ; CHECK-LABEL: @not_and_and_or_not_or_or_commute2( ; CHECK-NEXT: [[C:%.*]] = sdiv i32 42, [[C0:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[C]], [[OR1]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %c = sdiv i32 42, %c0 ; thwart complexity-based canonicalization @@ -2684,13 +2656,9 @@ define i32 @not_and_and_or_not_or_or_commute3(i32 %a, i32 %b0, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or_commute3( ; CHECK-NEXT: [[B:%.*]] = sdiv i32 42, [[B0:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B]], [[NOT2]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[C:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %b = sdiv i32 42, %b0 ; thwart complexity-based canonicalization @@ -2707,13 +2675,9 @@ define i32 @not_and_and_or_not_or_or_commute4(i32 %a, i32 %b, i32 %c0) { ; CHECK-LABEL: @not_and_and_or_not_or_or_commute4( ; CHECK-NEXT: [[C:%.*]] = sdiv i32 42, [[C0:%.*]] -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[C]], [[AND1]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A:%.*]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %c = sdiv i32 42, %c0 ; thwart complexity-based canonicalization @@ -2730,12 +2694,9 @@ define i32 @not_and_and_or_not_or_or_use1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or_use1( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: call void @use(i32 [[OR1]]) ; CHECK-NEXT: ret i32 [[OR3]] ; @@ -2754,11 +2715,9 @@ ; CHECK-LABEL: @not_and_and_or_not_or_or_use2( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C]], [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: call void @use(i32 [[OR2]]) ; CHECK-NEXT: ret i32 [[OR3]] ; @@ -2798,13 +2757,10 @@ define i32 @not_and_and_or_not_or_or_use4(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or_use4( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[OR3]] ; @@ -2821,13 +2777,11 @@ define i32 @not_and_and_or_not_or_or_use5(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_and_and_or_not_or_or_use5( -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND2]], [[NOT1]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT2]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[A]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP2]], -1 ; CHECK-NEXT: call void @use(i32 [[AND1]]) ; CHECK-NEXT: ret i32 [[OR3]] ; @@ -2869,12 +2823,9 @@ define i32 @not_or_or_and_not_and_and(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND3]] ; %and1 = and i32 %b, %a @@ -2889,12 +2840,9 @@ define i32 @not_or_or_and_not_and_and_commute1_and(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and_commute1_and( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[C:%.*]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[B:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND3]] ; %and1 = and i32 %c, %a @@ -2909,12 +2857,9 @@ define i32 @not_or_or_and_not_and_and_commute2_and(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and_commute2_and( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[A:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND3]] ; %and1 = and i32 %b, %c @@ -2929,12 +2874,9 @@ define i32 @not_or_or_and_not_and_and_commute1_or(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and_commute1_or( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[C]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[B]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND3]] ; %and1 = and i32 %b, %a @@ -2949,12 +2891,9 @@ define i32 @not_or_or_and_not_and_and_commute2_or(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and_commute2_or( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B]], [[C]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[NOT2]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], [[C:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND3]] ; %and1 = and i32 %b, %a @@ -2969,12 +2908,9 @@ define i32 @not_or_or_and_not_and_and_commute1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and_commute1( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND3]] ; %and1 = and i32 %a, %b @@ -2990,12 +2926,9 @@ define i32 @not_or_or_and_not_and_and_commute2(i32 %a, i32 %b, i32 %c0) { ; CHECK-LABEL: @not_or_or_and_not_and_and_commute2( ; CHECK-NEXT: [[C:%.*]] = sdiv i32 42, [[C0:%.*]] -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[C]], [[AND1]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C]], [[B:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND3]] ; %c = sdiv i32 42, %c0 ; thwart complexity-based canonicalization @@ -3012,12 +2945,9 @@ define i32 @not_or_or_and_not_and_and_commute3(i32 %a, i32 %b0, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and_commute3( ; CHECK-NEXT: [[B:%.*]] = sdiv i32 42, [[B0:%.*]] -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B]], [[NOT2]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[C:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND3]] ; %b = sdiv i32 42, %b0 ; thwart complexity-based canonicalization @@ -3034,12 +2964,9 @@ define i32 @not_or_or_and_not_and_and_commute4(i32 %a, i32 %b, i32 %c0) { ; CHECK-LABEL: @not_or_or_and_not_and_and_commute4( ; CHECK-NEXT: [[C:%.*]] = sdiv i32 42, [[C0:%.*]] -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[C]], [[OR1]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C]], [[B:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: ret i32 [[AND3]] ; %c = sdiv i32 42, %c0 ; thwart complexity-based canonicalization @@ -3056,11 +2983,9 @@ define i32 @not_or_or_and_not_and_and_use1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and_use1( ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[AND1]]) ; CHECK-NEXT: ret i32 [[AND3]] ; @@ -3080,9 +3005,8 @@ ; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] ; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C]], [[B]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[AND2]]) ; CHECK-NEXT: ret i32 [[AND3]] ; @@ -3122,12 +3046,9 @@ define i32 @not_or_or_and_not_and_and_use4(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and_use4( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[NOT2]]) ; CHECK-NEXT: ret i32 [[AND3]] ; @@ -3144,12 +3065,10 @@ define i32 @not_or_or_and_not_and_and_use5(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @not_or_or_and_not_and_and_use5( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[AND1]], [[C:%.*]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[OR1]], [[C]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR2]] +; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[A:%.*]], -1 +; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT2]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[AND3:%.*]] = or i32 [[TMP1]], [[NOT2]] ; CHECK-NEXT: call void @use(i32 [[OR1]]) ; CHECK-NEXT: ret i32 [[AND3]] ;