[llvm] 84e273c - [InstCombine] Handle undefs in and of icmp eq zero fold
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 11 10:07:14 PST 2021
Author: Nikita Popov
Date: 2021-11-11T19:07:07+01:00
New Revision: 84e273cced851075df46c78362ad3507a4de61d0
URL: https://github.com/llvm/llvm-project/commit/84e273cced851075df46c78362ad3507a4de61d0
DIFF: https://github.com/llvm/llvm-project/commit/84e273cced851075df46c78362ad3507a4de61d0.diff
LOG: [InstCombine] Handle undefs in and of icmp eq zero fold
For the scalar/splat case, this fold is subsumed by
foldLogOpOfMaskedICmps(). However, the conjugated fold for "or"
also supports splats with undef. Make both code paths consistent
by using m_ZeroInt() for the "and" implementation as well.
https://alive2.llvm.org/ce/z/tN63cu
https://alive2.llvm.org/ce/z/ufB_Ue
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/or.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 230046a20a22c..8b7f7f33b9b15 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1310,23 +1310,21 @@ Value *InstCombinerImpl::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS,
// This only handles icmp of constants: (icmp1 A, C1) & (icmp2 B, C2).
Value *LHS0 = LHS->getOperand(0), *RHS0 = RHS->getOperand(0);
+ // (icmp eq A, 0) & (icmp eq B, 0) --> (icmp eq (A|B), 0)
+ // TODO: Remove this when foldLogOpOfMaskedICmps can handle undefs.
+ if (PredL == ICmpInst::ICMP_EQ && match(LHS->getOperand(1), m_ZeroInt()) &&
+ PredR == ICmpInst::ICMP_EQ && match(RHS->getOperand(1), m_ZeroInt()) &&
+ LHS0->getType() == RHS0->getType()) {
+ Value *NewOr = Builder.CreateOr(LHS0, RHS0);
+ return Builder.CreateICmp(PredL, NewOr,
+ Constant::getNullValue(NewOr->getType()));
+ }
+
const APInt *LHSC, *RHSC;
if (!match(LHS->getOperand(1), m_APInt(LHSC)) ||
!match(RHS->getOperand(1), m_APInt(RHSC)))
return nullptr;
- if (LHSC == RHSC && PredL == PredR) {
- // (icmp ult A, C) & (icmp ult B, C) --> (icmp ult (A|B), C)
- // where C is a power of 2 or
- // (icmp eq A, 0) & (icmp eq B, 0) --> (icmp eq (A|B), 0)
- if ((PredL == ICmpInst::ICMP_ULT && LHSC->isPowerOf2()) ||
- (PredL == ICmpInst::ICMP_EQ && LHSC->isZero())) {
- Value *NewOr = Builder.CreateOr(LHS0, RHS0);
- return Builder.CreateICmp(PredL, NewOr,
- ConstantInt::get(NewOr->getType(), *LHSC));
- }
- }
-
// (trunc x) == C1 & (and x, CA) == C2 -> (and x, CA|CMAX) == C1|C2
// where CMAX is the all ones value for the truncated type,
// iff the lower bits of C2 and CA are zero.
@@ -2468,10 +2466,9 @@ Value *InstCombinerImpl::foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
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() &&
+ // TODO: Remove this when foldLogOpOfMaskedICmps can handle undefs.
+ if (PredL == ICmpInst::ICMP_NE && match(LHS1, m_ZeroInt()) &&
+ PredR == ICmpInst::ICMP_NE && match(RHS1, m_ZeroInt()) &&
LHS0->getType() == RHS0->getType()) {
Value *NewOr = Builder.CreateOr(LHS0, RHS0);
return Builder.CreateICmp(PredL, NewOr,
diff --git a/llvm/test/Transforms/InstCombine/or.ll b/llvm/test/Transforms/InstCombine/or.ll
index 4e66efc0800e1..01ffdacda7a88 100644
--- a/llvm/test/Transforms/InstCombine/or.ll
+++ b/llvm/test/Transforms/InstCombine/or.ll
@@ -248,10 +248,9 @@ define <2 x i1> @and_icmp_eq_0_vector(<2 x i32> %A, <2 x i32> %B) {
define <2 x i1> @and_icmp_eq_0_vector_undef1(<2 x i32> %A, <2 x i32> %B) {
; CHECK-LABEL: @and_icmp_eq_0_vector_undef1(
-; CHECK-NEXT: [[C1:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 0, i32 undef>
-; CHECK-NEXT: [[C2:%.*]] = icmp eq <2 x i32> [[B:%.*]], <i32 0, i32 undef>
-; CHECK-NEXT: [[D:%.*]] = and <2 x i1> [[C1]], [[C2]]
-; CHECK-NEXT: ret <2 x i1> [[D]]
+; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer
+; CHECK-NEXT: ret <2 x i1> [[TMP2]]
;
%C1 = icmp eq <2 x i32> %A, <i32 0, i32 undef>
%C2 = icmp eq <2 x i32> %B, <i32 0, i32 undef>
@@ -261,10 +260,9 @@ define <2 x i1> @and_icmp_eq_0_vector_undef1(<2 x i32> %A, <2 x i32> %B) {
define <2 x i1> @and_icmp_eq_0_vector_undef2(<2 x i32> %A, <2 x i32> %B) {
; CHECK-LABEL: @and_icmp_eq_0_vector_undef2(
-; CHECK-NEXT: [[C1:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 0, i32 undef>
-; CHECK-NEXT: [[C2:%.*]] = icmp eq <2 x i32> [[B:%.*]], <i32 undef, i32 0>
-; CHECK-NEXT: [[D:%.*]] = and <2 x i1> [[C1]], [[C2]]
-; CHECK-NEXT: ret <2 x i1> [[D]]
+; CHECK-NEXT: [[TMP1:%.*]] = or <2 x i32> [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], zeroinitializer
+; CHECK-NEXT: ret <2 x i1> [[TMP2]]
;
%C1 = icmp eq <2 x i32> %A, <i32 0, i32 undef>
%C2 = icmp eq <2 x i32> %B, <i32 undef, i32 0>
More information about the llvm-commits
mailing list