Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1727,16 +1727,18 @@ (Opcode == Instruction::And) ? Instruction::Or : Instruction::And; Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - Value *A, *B, *C; + Value *A, *B, *C, *X, *Y; // (~(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_c_BinOp(FlippedOpcode, - m_Not(m_BinOp(Opcode, m_Value(A), m_Value(B))), - m_Value(C)))) { + if (match(Op0, + m_c_BinOp(FlippedOpcode, + m_CombineAnd(m_Value(X), m_Not(m_BinOp(Opcode, m_Value(A), + m_Value(B)))), + m_Value(C)))) { // (~(A | B) & C) | (~(A | C) & B) --> (B ^ C) & ~A // (~(A & B) | C) & (~(A & C) | B) --> ~((B ^ C) & A) if (match(Op1, @@ -1776,6 +1778,18 @@ m_c_BinOp(Opcode, m_Specific(B), m_Specific(C))))))) return BinaryOperator::CreateNot(Builder.CreateBinOp( Opcode, Builder.CreateBinOp(FlippedOpcode, A, C), B)); + + // (~(A | B) & C) | ~(C | (A ^ B)) --> ~((A | B) & (C | (A ^ B))) + if (Opcode == Instruction::Or && Op0->hasOneUse() && + match(Op1, m_OneUse(m_Not(m_CombineAnd( + m_Value(Y), + m_c_BinOp(Opcode, m_Specific(C), + m_c_Xor(m_Specific(A), m_Specific(B)))))))) { + // X = ~(A | B) + // Y = (C | (A ^ B) + Value *Or = cast(X)->getOperand(0); + return BinaryOperator::CreateNot(Builder.CreateAnd(Or, Y)); + } } 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 @@ -2018,17 +2018,15 @@ ret i32 %and3 } -; (a & ~(b | c)) | ~(a | (b ^ c)) --> (~a & b & c) | ~(b | c) +; (a & ~(b | c)) | ~(a | (b ^ c)) --> ~((b | c) & (a | (b ^ c))) define i32 @and_not_or_or_not_or_xor(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @and_not_or_or_not_or_xor( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %b, %c @@ -2044,12 +2042,10 @@ define i32 @and_not_or_or_not_or_xor_commute1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @and_not_or_or_not_or_xor_commute1( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[C:%.*]], [[B:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %c, %b @@ -2066,12 +2062,10 @@ ; CHECK-LABEL: @and_not_or_or_not_or_xor_commute2( ; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A]], [[NOT1]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] ; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization @@ -2088,12 +2082,10 @@ define i32 @and_not_or_or_not_or_xor_commute3(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @and_not_or_or_not_or_xor_commute3( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[C]], [[B]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %b, %c @@ -2110,12 +2102,10 @@ ; CHECK-LABEL: @and_not_or_or_not_or_xor_commute4( ; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]] ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[A]], [[NOT1]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] ; CHECK-NEXT: [[OR2:%.*]] = or i32 [[A]], [[XOR1]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization @@ -2132,12 +2122,10 @@ define i32 @and_not_or_or_not_or_xor_commute5(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @and_not_or_or_not_or_xor_commute5( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: ret i32 [[OR3]] ; %or1 = or i32 %b, %c @@ -2153,12 +2141,10 @@ define i32 @and_not_or_or_not_or_xor_use1(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @and_not_or_or_not_or_xor_use1( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: call void @use(i32 [[OR1]]) ; CHECK-NEXT: ret i32 [[OR3]] ; @@ -2177,11 +2163,10 @@ ; CHECK-LABEL: @and_not_or_or_not_or_xor_use2( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] ; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: call void @use(i32 [[NOT1]]) ; CHECK-NEXT: ret i32 [[OR3]] ; @@ -2222,12 +2207,10 @@ define i32 @and_not_or_or_not_or_xor_use4(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @and_not_or_or_not_or_xor_use4( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: call void @use(i32 [[XOR1]]) ; CHECK-NEXT: ret i32 [[OR3]] ; @@ -2245,12 +2228,10 @@ define i32 @and_not_or_or_not_or_xor_use5(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @and_not_or_or_not_or_xor_use5( ; CHECK-NEXT: [[OR1:%.*]] = or i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[OR1]], -1 -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[NOT1]], [[A:%.*]] ; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[OR2]], -1 -; CHECK-NEXT: [[OR3:%.*]] = or i32 [[AND1]], [[NOT2]] +; CHECK-NEXT: [[OR2:%.*]] = or i32 [[XOR1]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[OR1]], [[OR2]] +; CHECK-NEXT: [[OR3:%.*]] = xor i32 [[TMP1]], -1 ; CHECK-NEXT: call void @use(i32 [[OR2]]) ; CHECK-NEXT: ret i32 [[OR3]] ; @@ -2288,265 +2269,6 @@ ret i32 %or3 } -; (a | ~(b & c)) & ~(a & (b ^ c)) --> ~(a | b) | (a ^ b ^ c) - -define i32 @or_not_and_and_not_and_xor(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_commute1(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_commute1( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[C:%.*]], [[B:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %c, %b - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_commute2(i32 %a0, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_commute2( -; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]] -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[A]], [[NOT1]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: ret i32 [[AND3]] -; - %a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %a, %not1 - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_commute3(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_commute3( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[C]], [[B]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %c, %b - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_commute4(i32 %a0, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_commute4( -; CHECK-NEXT: [[A:%.*]] = sdiv i32 42, [[A0:%.*]] -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[A]], [[NOT1]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[A]], [[XOR1]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: ret i32 [[AND3]] -; - %a = sdiv i32 42, %a0 ; thwart complexity-based canonicalization - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %a, %not1 - %xor1 = xor i32 %b, %c - %and2 = and i32 %a, %xor1 - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_commute5(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_commute5( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %not2, %or1 - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_use1(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_use1( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: call void @use(i32 [[AND1]]) -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - call void @use(i32 %and1) - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_use2(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_use2( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: call void @use(i32 [[NOT1]]) -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - call void @use(i32 %not1) - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_use3(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_use3( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: call void @use(i32 [[OR1]]) -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - call void @use(i32 %or1) - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_use4(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_use4( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: call void @use(i32 [[XOR1]]) -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - call void @use(i32 %xor1) - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_use5(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_use5( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: call void @use(i32 [[AND2]]) -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - call void @use(i32 %and2) - ret i32 %and3 -} - -define i32 @or_not_and_and_not_and_xor_use6(i32 %a, i32 %b, i32 %c) { -; CHECK-LABEL: @or_not_and_and_not_and_xor_use6( -; CHECK-NEXT: [[AND1:%.*]] = and i32 [[B:%.*]], [[C:%.*]] -; CHECK-NEXT: [[NOT1:%.*]] = xor i32 [[AND1]], -1 -; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOT1]], [[A:%.*]] -; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[C]] -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[XOR1]], [[A]] -; CHECK-NEXT: [[NOT2:%.*]] = xor i32 [[AND2]], -1 -; CHECK-NEXT: [[AND3:%.*]] = xor i32 [[AND2]], [[OR1]] -; CHECK-NEXT: call void @use(i32 [[NOT2]]) -; CHECK-NEXT: ret i32 [[AND3]] -; - %and1 = and i32 %b, %c - %not1 = xor i32 %and1, -1 - %or1 = or i32 %not1, %a - %xor1 = xor i32 %b, %c - %and2 = and i32 %xor1, %a - %not2 = xor i32 %and2, -1 - %and3 = and i32 %or1, %not2 - call void @use(i32 %not2) - ret i32 %and3 -} - ; (~a & b & c) | ~(a | b | c) -> ~(a | (b ^ c)) define i32 @not_and_and_or_not_or_or(i32 %a, i32 %b, i32 %c) {