diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 1457422b255..6a1ec0f84e5 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -1870,6 +1870,24 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q, match(Op1, m_c_And(m_Not(m_Specific(A)), m_Specific(B))))) return Op0; + // (A & B) | (~A ^ B) -> (~A ^ B) + // (B & A) | (~A ^ B) -> (~A ^ B) + // (A & B) | (B ^ ~A) -> (B ^ ~A) + // (B & A) | (B ^ ~A) -> (B ^ ~A) + if (match(Op0, m_And(m_Value(A), m_Value(B))) && + (match(Op1, m_c_Xor(m_Specific(A), m_Not(m_Specific(B)))) || + match(Op1, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B))))) + return Op1; + + // (~A ^ B) | (A & B) -> (~A ^ B) + // (~A ^ B) | (B & A) -> (~A ^ B) + // (B ^ ~A) | (A & B) -> (B ^ ~A) + // (B ^ ~A) | (B & A) -> (B ^ ~A) + if (match(Op1, m_And(m_Value(A), m_Value(B))) && + (match(Op0, m_c_Xor(m_Specific(A), m_Not(m_Specific(B)))) || + match(Op0, m_c_Xor(m_Not(m_Specific(A)), m_Specific(B))))) + return Op0; + if (Value *V = simplifyAndOrOfICmps(Op0, Op1, false)) return V; diff --git a/test/Transforms/InstSimplify/AndOrXor.ll b/test/Transforms/InstSimplify/AndOrXor.ll index abca8222f31..9aa96eb2bdb 100644 --- a/test/Transforms/InstSimplify/AndOrXor.ll +++ b/test/Transforms/InstSimplify/AndOrXor.ll @@ -634,10 +634,8 @@ define i32 @test46_commuted_and(i32 %a, i32 %b) { define i32 @test47(i32 %a, i32 %b) { ; CHECK-LABEL: @test47( ; CHECK-NEXT: [[NEGA:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[A]], [[B:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NEGA]], [[B]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR]], [[AND]] -; CHECK-NEXT: ret i32 [[OR]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NEGA]], [[B:%.*]] +; CHECK-NEXT: ret i32 [[XOR]] ; %nega = xor i32 %a, -1 %and = and i32 %a, %b @@ -649,10 +647,8 @@ define i32 @test47(i32 %a, i32 %b) { define i32 @test48(i32 %a, i32 %b) { ; CHECK-LABEL: @test48( ; CHECK-NEXT: [[NEGA:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[A]], [[B:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[NEGA]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR]], [[AND]] -; CHECK-NEXT: ret i32 [[OR]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B:%.*]], [[NEGA]] +; CHECK-NEXT: ret i32 [[XOR]] ; %nega = xor i32 %a, -1 %and = and i32 %a, %b @@ -664,10 +660,8 @@ define i32 @test48(i32 %a, i32 %b) { define i32 @test49(i32 %a, i32 %b) { ; CHECK-LABEL: @test49( ; CHECK-NEXT: [[NEGA:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[NEGA]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR]], [[AND]] -; CHECK-NEXT: ret i32 [[OR]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B:%.*]], [[NEGA]] +; CHECK-NEXT: ret i32 [[XOR]] ; %nega = xor i32 %a, -1 %and = and i32 %b, %a @@ -679,10 +673,8 @@ define i32 @test49(i32 %a, i32 %b) { define i32 @test50(i32 %a, i32 %b) { ; CHECK-LABEL: @test50( ; CHECK-NEXT: [[NEGA:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NEGA]], [[B]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR]], [[AND]] -; CHECK-NEXT: ret i32 [[OR]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NEGA]], [[B:%.*]] +; CHECK-NEXT: ret i32 [[XOR]] ; %nega = xor i32 %a, -1 %and = and i32 %b, %a @@ -694,10 +686,8 @@ define i32 @test50(i32 %a, i32 %b) { define i32 @test51(i32 %a, i32 %b) { ; CHECK-LABEL: @test51( ; CHECK-NEXT: [[NEGA:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[A]], [[B:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NEGA]], [[B]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XOR]] -; CHECK-NEXT: ret i32 [[OR]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NEGA]], [[B:%.*]] +; CHECK-NEXT: ret i32 [[XOR]] ; %nega = xor i32 %a, -1 %and = and i32 %a, %b @@ -709,10 +699,8 @@ define i32 @test51(i32 %a, i32 %b) { define i32 @test52(i32 %a, i32 %b) { ; CHECK-LABEL: @test52( ; CHECK-NEXT: [[NEGA:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[A]], [[B:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[NEGA]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XOR]] -; CHECK-NEXT: ret i32 [[OR]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B:%.*]], [[NEGA]] +; CHECK-NEXT: ret i32 [[XOR]] ; %nega = xor i32 %a, -1 %and = and i32 %a, %b @@ -724,10 +712,8 @@ define i32 @test52(i32 %a, i32 %b) { define i32 @test53(i32 %a, i32 %b) { ; CHECK-LABEL: @test53( ; CHECK-NEXT: [[NEGA:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[NEGA]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XOR]] -; CHECK-NEXT: ret i32 [[OR]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B:%.*]], [[NEGA]] +; CHECK-NEXT: ret i32 [[XOR]] ; %nega = xor i32 %a, -1 %and = and i32 %b, %a @@ -739,10 +725,8 @@ define i32 @test53(i32 %a, i32 %b) { define i32 @test54(i32 %a, i32 %b) { ; CHECK-LABEL: @test54( ; CHECK-NEXT: [[NEGA:%.*]] = xor i32 [[A:%.*]], -1 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NEGA]], [[B]] -; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XOR]] -; CHECK-NEXT: ret i32 [[OR]] +; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NEGA]], [[B:%.*]] +; CHECK-NEXT: ret i32 [[XOR]] ; %nega = xor i32 %a, -1 %and = and i32 %b, %a