forked from OSchip/llvm-project
[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:
parent
ae8984111d
commit
d0e9879d96
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue