[InstCombine] Add (icmp ne A, 0) | (icmp ne B, 0) --> (icmp ne (A|B), 0) vector support

Scalar cases were already being handled by foldLogOpOfMaskedICmps (so this was dead code), but refactoring to support non-uniform vectors will take some time, so tweak this fold in the meantime.
This commit is contained in:
Simon Pilgrim 2020-10-19 15:41:07 +01:00
parent b91a236ee1
commit de885f1b2a
2 changed files with 17 additions and 16 deletions

View File

@ -2403,20 +2403,23 @@ Value *InstCombinerImpl::foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
foldUnsignedUnderflowCheck(RHS, LHS, /*IsAnd=*/false, Q, Builder)) foldUnsignedUnderflowCheck(RHS, LHS, /*IsAnd=*/false, Q, Builder))
return X; return X;
// (icmp ne A, 0) | (icmp ne B, 0) --> (icmp ne (A|B), 0)
// TODO: Remove this when foldLogOpOfMaskedICmps can handle vectors.
if (PredL == ICmpInst::ICMP_NE && match(LHS1, m_Zero()) &&
PredR == ICmpInst::ICMP_NE && match(RHS1, m_Zero()) &&
LHS0->getType()->isIntOrIntVectorTy() &&
LHS0->getType() == RHS0->getType()) {
Value *NewOr = Builder.CreateOr(LHS0, RHS0);
return Builder.CreateICmp(PredL, NewOr,
Constant::getNullValue(NewOr->getType()));
}
// This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2). // This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2).
auto *LHSC = dyn_cast<ConstantInt>(LHS1); auto *LHSC = dyn_cast<ConstantInt>(LHS1);
auto *RHSC = dyn_cast<ConstantInt>(RHS1); auto *RHSC = dyn_cast<ConstantInt>(RHS1);
if (!LHSC || !RHSC) if (!LHSC || !RHSC)
return nullptr; return nullptr;
if (LHSC == RHSC && PredL == PredR) {
// (icmp ne A, 0) | (icmp ne B, 0) --> (icmp ne (A|B), 0)
if (PredL == ICmpInst::ICMP_NE && LHSC->isZero()) {
Value *NewOr = Builder.CreateOr(LHS0, RHS0);
return Builder.CreateICmp(PredL, NewOr, LHSC);
}
}
// (icmp ult (X + CA), C1) | (icmp eq X, C2) -> (icmp ule (X + CA), C1) // (icmp ult (X + CA), C1) | (icmp eq X, C2) -> (icmp ule (X + CA), C1)
// iff C2 + CA == C1. // iff C2 + CA == C1.
if (PredL == ICmpInst::ICMP_ULT && PredR == ICmpInst::ICMP_EQ) { if (PredL == ICmpInst::ICMP_ULT && PredR == ICmpInst::ICMP_EQ) {

View File

@ -2200,10 +2200,9 @@ define i1 @or_icmp_ne_A_0_icmp_ne_B_0(i64 %a, i64 %b) {
define <2 x i1> @or_icmp_ne_A_0_icmp_ne_B_0_uniform(<2 x i64> %a, <2 x i64> %b) { define <2 x i1> @or_icmp_ne_A_0_icmp_ne_B_0_uniform(<2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: @or_icmp_ne_A_0_icmp_ne_B_0_uniform( ; CHECK-LABEL: @or_icmp_ne_A_0_icmp_ne_B_0_uniform(
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i64> [[A:%.*]], zeroinitializer ; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i64> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i64> [[B:%.*]], zeroinitializer ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i64> [[TMP1]], zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = or <2 x i1> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
; CHECK-NEXT: ret <2 x i1> [[TMP3]]
; ;
%1 = icmp ne <2 x i64> %a, zeroinitializer %1 = icmp ne <2 x i64> %a, zeroinitializer
%2 = icmp ne <2 x i64> %b, zeroinitializer %2 = icmp ne <2 x i64> %b, zeroinitializer
@ -2213,10 +2212,9 @@ define <2 x i1> @or_icmp_ne_A_0_icmp_ne_B_0_uniform(<2 x i64> %a, <2 x i64> %b)
define <2 x i1> @or_icmp_ne_A_0_icmp_ne_B_0_undef(<2 x i64> %a, <2 x i64> %b) { define <2 x i1> @or_icmp_ne_A_0_icmp_ne_B_0_undef(<2 x i64> %a, <2 x i64> %b) {
; CHECK-LABEL: @or_icmp_ne_A_0_icmp_ne_B_0_undef( ; CHECK-LABEL: @or_icmp_ne_A_0_icmp_ne_B_0_undef(
; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i64> [[A:%.*]], <i64 0, i64 undef> ; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i64> [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i64> [[B:%.*]], <i64 0, i64 undef> ; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i64> [[TMP1]], zeroinitializer
; CHECK-NEXT: [[TMP3:%.*]] = or <2 x i1> [[TMP1]], [[TMP2]] ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
; CHECK-NEXT: ret <2 x i1> [[TMP3]]
; ;
%1 = icmp ne <2 x i64> %a, <i64 0, i64 undef> %1 = icmp ne <2 x i64> %a, <i64 0, i64 undef>
%2 = icmp ne <2 x i64> %b, <i64 0, i64 undef> %2 = icmp ne <2 x i64> %b, <i64 0, i64 undef>