[InstCombine] allow vector splat matching for bitwise logic folds

These transforms are also likely missing a one-use check,
but that's another patch.
This commit is contained in:
Sanjay Patel 2021-10-29 14:21:36 -04:00
parent ae8984111d
commit d0e9879d96
3 changed files with 28 additions and 31 deletions

View File

@ -2699,10 +2699,31 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
return BinaryOperator::CreateXor(Or, ConstantInt::get(I.getType(), *CV));
}
// (A & C)|(B & D)
// (A & C) | (B & D)
Value *A, *B, *C, *D;
if (match(Op0, m_And(m_Value(A), m_Value(C))) &&
match(Op1, m_And(m_Value(B), m_Value(D)))) {
const APInt *MaskC0, *MaskC1;
if (match(C, m_APInt(MaskC0)) && match(D, m_APInt(MaskC1)) &&
*MaskC0 == ~*MaskC1) {
Value *X;
// ((X | B) & C1) | (B & C2) -> (X & C1) | B iff C1 == ~C2
if (match(A, m_c_Or(m_Value(X), m_Specific(B))))
return BinaryOperator::CreateOr(Builder.CreateAnd(X, *MaskC0), B);
// (A & C2) | ((X | A) & C1) -> (X & C2) | A iff C1 == ~C2
if (match(B, m_c_Or(m_Specific(A), m_Value(X))))
return BinaryOperator::CreateOr(Builder.CreateAnd(X, *MaskC1), A);
// ((X ^ B) & C1) | (B & C2) -> (X & C1) ^ B iff C1 == ~C2
if (match(A, m_c_Xor(m_Value(X), m_Specific(B))))
return BinaryOperator::CreateXor(Builder.CreateAnd(X, *MaskC0), B);
// (A & C2) | ((X ^ A) & C1) -> (X & C2) ^ A iff C1 == ~C2
if (match(B, m_c_Xor(m_Specific(A), m_Value(X))))
return BinaryOperator::CreateXor(Builder.CreateAnd(X, *MaskC1), A);
}
// (A & C1)|(B & C2)
ConstantInt *C1, *C2;
if (match(C, m_ConstantInt(C1)) && match(D, m_ConstantInt(C2))) {
@ -2738,24 +2759,6 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
Builder.getInt(C1->getValue()|C2->getValue()));
}
}
if (C1->getValue() == ~C2->getValue()) {
Value *X;
// ((X|B)&C1)|(B&C2) -> (X&C1) | B iff C1 == ~C2
if (match(A, m_c_Or(m_Value(X), m_Specific(B))))
return BinaryOperator::CreateOr(Builder.CreateAnd(X, C1), B);
// (A&C2)|((X|A)&C1) -> (X&C2) | A iff C1 == ~C2
if (match(B, m_c_Or(m_Specific(A), m_Value(X))))
return BinaryOperator::CreateOr(Builder.CreateAnd(X, C2), A);
// ((X^B)&C1)|(B&C2) -> (X&C1) ^ B iff C1 == ~C2
if (match(A, m_c_Xor(m_Value(X), m_Specific(B))))
return BinaryOperator::CreateXor(Builder.CreateAnd(X, C1), B);
// (A&C2)|((X^A)&C1) -> (X&C2) ^ A iff C1 == ~C2
if (match(B, m_c_Xor(m_Specific(A), m_Value(X))))
return BinaryOperator::CreateXor(Builder.CreateAnd(X, C2), A);
}
}
// Don't try to form a select if it's unlikely that we'll get rid of at

View File

@ -57,10 +57,8 @@ define i32 @or_and_not_constant_commute3(i32 %a, i32 %b) {
define <2 x i7> @or_and_not_constant_commute0_splat(<2 x i7> %a, <2 x i7> %b) {
; CHECK-LABEL: @or_and_not_constant_commute0_splat(
; CHECK-NEXT: [[T:%.*]] = or <2 x i7> [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[T1:%.*]] = and <2 x i7> [[T]], <i7 42, i7 42>
; CHECK-NEXT: [[T2:%.*]] = and <2 x i7> [[B]], <i7 -43, i7 -43>
; CHECK-NEXT: [[T3:%.*]] = or <2 x i7> [[T1]], [[T2]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i7> [[A:%.*]], <i7 42, i7 42>
; CHECK-NEXT: [[T3:%.*]] = or <2 x i7> [[TMP1]], [[B:%.*]]
; CHECK-NEXT: ret <2 x i7> [[T3]]
;
%t = or <2 x i7> %b, %a

View File

@ -303,10 +303,8 @@ define i9 @or_and_xor_not_constant_commute1(i9 %a, i9 %b) {
define <2 x i9> @or_and_xor_not_constant_commute2_splat(<2 x i9> %a, <2 x i9> %b) {
; CHECK-LABEL: @or_and_xor_not_constant_commute2_splat(
; CHECK-NEXT: [[OR:%.*]] = xor <2 x i9> [[B:%.*]], [[A:%.*]]
; CHECK-NEXT: [[AND1:%.*]] = and <2 x i9> [[OR]], <i9 42, i9 42>
; CHECK-NEXT: [[AND2:%.*]] = and <2 x i9> [[B]], <i9 -43, i9 -43>
; CHECK-NEXT: [[XOR:%.*]] = or <2 x i9> [[AND2]], [[AND1]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i9> [[A:%.*]], <i9 42, i9 42>
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i9> [[TMP1]], [[B:%.*]]
; CHECK-NEXT: ret <2 x i9> [[XOR]]
;
%or = xor <2 x i9> %b, %a
@ -318,10 +316,8 @@ define <2 x i9> @or_and_xor_not_constant_commute2_splat(<2 x i9> %a, <2 x i9> %b
define <2 x i9> @or_and_xor_not_constant_commute3_splat(<2 x i9> %a, <2 x i9> %b) {
; CHECK-LABEL: @or_and_xor_not_constant_commute3_splat(
; CHECK-NEXT: [[OR:%.*]] = xor <2 x i9> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[AND1:%.*]] = and <2 x i9> [[OR]], <i9 42, i9 42>
; CHECK-NEXT: [[AND2:%.*]] = and <2 x i9> [[B]], <i9 -43, i9 -43>
; CHECK-NEXT: [[XOR:%.*]] = or <2 x i9> [[AND2]], [[AND1]]
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i9> [[A:%.*]], <i9 42, i9 42>
; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i9> [[TMP1]], [[B:%.*]]
; CHECK-NEXT: ret <2 x i9> [[XOR]]
;
%or = xor <2 x i9> %a, %b