diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 2ee1e1e98f2eae..e571c6ba2ff4d5 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2245,6 +2245,14 @@ static Value *simplifyOrLogic(Value *X, Value *Y) { match(Y, m_Not(m_c_Or(m_Specific(A), m_Specific(B))))) return NotA; + // ~(A ^ B) | (A & B) --> ~(A & B) + // ~(A ^ B) | (B & A) --> ~(A & B) + Value *NotAB; + if (match(X, m_CombineAnd(m_NotForbidUndef(m_Xor(m_Value(A), m_Value(B))), + m_Value(NotAB))) && + match(Y, m_c_And(m_Specific(A), m_Specific(B)))) + return NotAB; + return nullptr; } diff --git a/llvm/test/Transforms/InstSimplify/AndOrXor.ll b/llvm/test/Transforms/InstSimplify/AndOrXor.ll index 3c3d908d5738bc..e0d9258e9a8ab8 100644 --- a/llvm/test/Transforms/InstSimplify/AndOrXor.ll +++ b/llvm/test/Transforms/InstSimplify/AndOrXor.ll @@ -756,74 +756,6 @@ define i32 @or_xorn_and_commute7(i32 %a, i32 %b) { ret i32 %or } -; (A & B) | ~(A ^ B) -> ~(A ^ B) - -define i32 @test55(i32 %a, i32 %b) { -; CHECK-LABEL: @test55( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] -; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XNOR]] -; CHECK-NEXT: ret i32 [[OR]] -; - %and = and i32 %a, %b - %xor = xor i32 %a, %b - %xnor = xor i32 %xor, -1 - %or = or i32 %and, %xnor - ret i32 %or -} - -; ~(A ^ B) | (A & B) -> ~(A ^ B) - -define i32 @test56(i32 %a, i32 %b) { -; CHECK-LABEL: @test56( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] -; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i32 [[XNOR]], [[AND]] -; CHECK-NEXT: ret i32 [[OR]] -; - %and = and i32 %a, %b - %xor = xor i32 %a, %b - %xnor = xor i32 %xor, -1 - %or = or i32 %xnor, %and - ret i32 %or -} - -; (B & A) | ~(A ^ B) -> ~(A ^ B) - -define i32 @test57(i32 %a, i32 %b) { -; CHECK-LABEL: @test57( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] -; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], [[XNOR]] -; CHECK-NEXT: ret i32 [[OR]] -; - %and = and i32 %b, %a - %xor = xor i32 %a, %b - %xnor = xor i32 %xor, -1 - %or = or i32 %and, %xnor - ret i32 %or -} - -; ~(A ^ B) | (A & B) -> ~(A ^ B) - -define i32 @test58(i32 %a, i32 %b) { -; CHECK-LABEL: @test58( -; CHECK-NEXT: [[AND:%.*]] = and i32 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] -; CHECK-NEXT: [[XNOR:%.*]] = xor i32 [[XOR]], -1 -; CHECK-NEXT: [[OR:%.*]] = or i32 [[XNOR]], [[AND]] -; CHECK-NEXT: ret i32 [[OR]] -; - %and = and i32 %b, %a - %xor = xor i32 %a, %b - %xnor = xor i32 %xor, -1 - %or = or i32 %xnor, %and - ret i32 %or -} - define i8 @lshr_perfect_mask(i8 %x) { ; CHECK-LABEL: @lshr_perfect_mask( ; CHECK-NEXT: [[SH:%.*]] = lshr i8 [[X:%.*]], 5 diff --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll index 1f56c15ee102b0..821715100c5e94 100644 --- a/llvm/test/Transforms/InstSimplify/or.ll +++ b/llvm/test/Transforms/InstSimplify/or.ll @@ -622,13 +622,13 @@ define i32 @shifted_all_ones_not_same_amt(i32 %shamt, i32 %other) { ret i32 %o } +; (A & B) | ~(A ^ B) --> ~(A ^ B) + define i4 @or_nxor_and_commute0(i4 %a, i4 %b) { ; CHECK-LABEL: @or_nxor_and_commute0( -; CHECK-NEXT: [[AND:%.*]] = and i4 [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i4 [[A]], [[B]] +; CHECK-NEXT: [[XOR:%.*]] = xor i4 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[NOT:%.*]] = xor i4 [[XOR]], -1 -; CHECK-NEXT: [[R:%.*]] = or i4 [[AND]], [[NOT]] -; CHECK-NEXT: ret i4 [[R]] +; CHECK-NEXT: ret i4 [[NOT]] ; %and = and i4 %a, %b %xor = xor i4 %a, %b @@ -639,11 +639,9 @@ define i4 @or_nxor_and_commute0(i4 %a, i4 %b) { define <2 x i4> @or_nxor_and_commute1(<2 x i4> %a, <2 x i4> %b) { ; CHECK-LABEL: @or_nxor_and_commute1( -; CHECK-NEXT: [[AND:%.*]] = and <2 x i4> [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i4> [[A]], [[B]] +; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i4> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i4> [[XOR]], -; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[NOT]], [[AND]] -; CHECK-NEXT: ret <2 x i4> [[R]] +; CHECK-NEXT: ret <2 x i4> [[NOT]] ; %and = and <2 x i4> %a, %b %xor = xor <2 x i4> %a, %b @@ -654,11 +652,9 @@ define <2 x i4> @or_nxor_and_commute1(<2 x i4> %a, <2 x i4> %b) { define i74 @or_nxor_and_commute2(i74 %a, i74 %b) { ; CHECK-LABEL: @or_nxor_and_commute2( -; CHECK-NEXT: [[AND:%.*]] = and i74 [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor i74 [[A]], [[B]] +; CHECK-NEXT: [[XOR:%.*]] = xor i74 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[NOT:%.*]] = xor i74 [[XOR]], -1 -; CHECK-NEXT: [[R:%.*]] = or i74 [[AND]], [[NOT]] -; CHECK-NEXT: ret i74 [[R]] +; CHECK-NEXT: ret i74 [[NOT]] ; %and = and i74 %b, %a %xor = xor i74 %a, %b @@ -669,11 +665,9 @@ define i74 @or_nxor_and_commute2(i74 %a, i74 %b) { define <2 x i4> @or_nxor_and_commute3(<2 x i4> %a, <2 x i4> %b) { ; CHECK-LABEL: @or_nxor_and_commute3( -; CHECK-NEXT: [[AND:%.*]] = and <2 x i4> [[B:%.*]], [[A:%.*]] -; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i4> [[A]], [[B]] +; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i4> [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i4> [[XOR]], -; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[NOT]], [[AND]] -; CHECK-NEXT: ret <2 x i4> [[R]] +; CHECK-NEXT: ret <2 x i4> [[NOT]] ; %and = and <2 x i4> %b, %a %xor = xor <2 x i4> %a, %b @@ -682,6 +676,8 @@ define <2 x i4> @or_nxor_and_commute3(<2 x i4> %a, <2 x i4> %b) { ret <2 x i4> %r } +; negative test - must have common operands + define i4 @or_nxor_and_wrong_val1(i4 %a, i4 %b, i4 %c) { ; CHECK-LABEL: @or_nxor_and_wrong_val1( ; CHECK-NEXT: [[AND:%.*]] = and i4 [[A:%.*]], [[C:%.*]] @@ -697,6 +693,8 @@ define i4 @or_nxor_and_wrong_val1(i4 %a, i4 %b, i4 %c) { ret i4 %r } +; negative test - must have common operands + define i4 @or_nxor_and_wrong_val2(i4 %a, i4 %b, i4 %c) { ; CHECK-LABEL: @or_nxor_and_wrong_val2( ; CHECK-NEXT: [[AND:%.*]] = and i4 [[C:%.*]], [[B:%.*]] @@ -712,6 +710,8 @@ define i4 @or_nxor_and_wrong_val2(i4 %a, i4 %b, i4 %c) { ret i4 %r } +; negative test - undef in 'not' is allowed + define <2 x i4> @or_nxor_and_undef_elt(<2 x i4> %a, <2 x i4> %b) { ; CHECK-LABEL: @or_nxor_and_undef_elt( ; CHECK-NEXT: [[AND:%.*]] = and <2 x i4> [[B:%.*]], [[A:%.*]] @@ -807,7 +807,7 @@ define i4 @or_nxor_or_wrong_val2(i4 %a, i4 %b, i4 %c) { ret i4 %r } -; undef in 'not' is allowed +; negative test - undef in 'not' is allowed define <2 x i4> @or_nxor_or_undef_elt(<2 x i4> %a, <2 x i4> %b) { ; CHECK-LABEL: @or_nxor_or_undef_elt(