[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