[llvm] 861adaf - [InstCombine] Support splat vectors in some and of icmp folds

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 10 13:40:39 PST 2021


Author: Nikita Popov
Date: 2021-11-10T22:37:54+01:00
New Revision: 861adaf2ad20e13df0209c39bddacd16b78e3bb2

URL: https://github.com/llvm/llvm-project/commit/861adaf2ad20e13df0209c39bddacd16b78e3bb2
DIFF: https://github.com/llvm/llvm-project/commit/861adaf2ad20e13df0209c39bddacd16b78e3bb2.diff

LOG: [InstCombine] Support splat vectors in some and of icmp folds

Replace m_ConstantInt() with m_APInt() to support splat vectors
in addition to scalar integers.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/test/Transforms/InstCombine/and.ll
    llvm/test/Transforms/InstCombine/and2.ll
    llvm/test/Transforms/InstCombine/merge-icmp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 26983cf15801..fae19549f081 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1310,19 +1310,20 @@ 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);
 
-  ConstantInt *LHSC, *RHSC;
-  if (!match(LHS->getOperand(1), m_ConstantInt(LHSC)) ||
-      !match(RHS->getOperand(1), m_ConstantInt(RHSC)))
+  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->getValue().isPowerOf2()) ||
+    if ((PredL == ICmpInst::ICMP_ULT && LHSC->isPowerOf2()) ||
         (PredL == ICmpInst::ICMP_EQ && LHSC->isZero())) {
       Value *NewOr = Builder.CreateOr(LHS0, RHS0);
-      return Builder.CreateICmp(PredL, NewOr, LHSC);
+      return Builder.CreateICmp(PredL, NewOr,
+                                ConstantInt::get(NewOr->getType(), *LHSC));
     }
   }
 
@@ -1332,38 +1333,36 @@ Value *InstCombinerImpl::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS,
   if (PredL == ICmpInst::ICMP_EQ && PredL == PredR && LHS->hasOneUse() &&
       RHS->hasOneUse()) {
     Value *V;
-    ConstantInt *AndC, *SmallC = nullptr, *BigC = nullptr;
+    const APInt *AndC, *SmallC = nullptr, *BigC = nullptr;
 
     // (trunc x) == C1 & (and x, CA) == C2
     // (and x, CA) == C2 & (trunc x) == C1
     if (match(RHS0, m_Trunc(m_Value(V))) &&
-        match(LHS0, m_And(m_Specific(V), m_ConstantInt(AndC)))) {
+        match(LHS0, m_And(m_Specific(V), m_APInt(AndC)))) {
       SmallC = RHSC;
       BigC = LHSC;
     } else if (match(LHS0, m_Trunc(m_Value(V))) &&
-               match(RHS0, m_And(m_Specific(V), m_ConstantInt(AndC)))) {
+               match(RHS0, m_And(m_Specific(V), m_APInt(AndC)))) {
       SmallC = LHSC;
       BigC = RHSC;
     }
 
     if (SmallC && BigC) {
-      unsigned BigBitSize = BigC->getType()->getBitWidth();
-      unsigned SmallBitSize = SmallC->getType()->getBitWidth();
+      unsigned BigBitSize = BigC->getBitWidth();
+      unsigned SmallBitSize = SmallC->getBitWidth();
 
       // Check that the low bits are zero.
       APInt Low = APInt::getLowBitsSet(BigBitSize, SmallBitSize);
-      if ((Low & AndC->getValue()).isZero() &&
-          (Low & BigC->getValue()).isZero()) {
-        Value *NewAnd = Builder.CreateAnd(V, Low | AndC->getValue());
-        APInt N = SmallC->getValue().zext(BigBitSize) | BigC->getValue();
-        Value *NewVal = ConstantInt::get(AndC->getType()->getContext(), N);
+      if ((Low & *AndC).isZero() && (Low & *BigC).isZero()) {
+        Value *NewAnd = Builder.CreateAnd(V, Low | *AndC);
+        APInt N = SmallC->zext(BigBitSize) | *BigC;
+        Value *NewVal = ConstantInt::get(NewAnd->getType(), N);
         return Builder.CreateICmp(PredL, NewAnd, NewVal);
       }
     }
   }
 
-  return foldAndOrOfICmpsUsingRanges(PredL, LHS0, LHSC->getValue(),
-                                     PredR, RHS0, RHSC->getValue(),
+  return foldAndOrOfICmpsUsingRanges(PredL, LHS0, *LHSC, PredR, RHS0, *RHSC,
                                      Builder, /* IsAnd */ true);
 }
 

diff  --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 0e25d2d47103..392d752e40a7 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -307,13 +307,10 @@ define i1 @test23_logical(i32 %A) {
   ret i1 %D
 }
 
-; FIXME: Vectors should fold too.
 define <2 x i1> @test23vec(<2 x i32> %A) {
 ; CHECK-LABEL: @test23vec(
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt <2 x i32> [[A:%.*]], <i32 1, i32 1>
-; CHECK-NEXT:    [[C:%.*]] = icmp slt <2 x i32> [[A]], <i32 3, i32 3>
-; CHECK-NEXT:    [[D:%.*]] = and <2 x i1> [[B]], [[C]]
-; CHECK-NEXT:    ret <2 x i1> [[D]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 2, i32 2>
+; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
 ;
   %B = icmp sgt <2 x i32> %A, <i32 1, i32 1>
   %C = icmp sle <2 x i32> %A, <i32 2, i32 2>
@@ -369,13 +366,11 @@ define i1 @test25_logical(i32 %A) {
   ret i1 %D
 }
 
-; FIXME: Vectors should fold too.
 define <2 x i1> @test25vec(<2 x i32> %A) {
 ; CHECK-LABEL: @test25vec(
-; CHECK-NEXT:    [[B:%.*]] = icmp sgt <2 x i32> [[A:%.*]], <i32 49, i32 49>
-; CHECK-NEXT:    [[C:%.*]] = icmp slt <2 x i32> [[A]], <i32 100, i32 100>
-; CHECK-NEXT:    [[D:%.*]] = and <2 x i1> [[B]], [[C]]
-; CHECK-NEXT:    ret <2 x i1> [[D]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], <i32 -50, i32 -50>
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 50, i32 50>
+; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
 ;
   %B = icmp sge <2 x i32> %A, <i32 50, i32 50>
   %C = icmp slt <2 x i32> %A, <i32 100, i32 100>

diff  --git a/llvm/test/Transforms/InstCombine/and2.ll b/llvm/test/Transforms/InstCombine/and2.ll
index 03be031e930e..bb8776a970ee 100644
--- a/llvm/test/Transforms/InstCombine/and2.ll
+++ b/llvm/test/Transforms/InstCombine/and2.ll
@@ -83,13 +83,11 @@ define i1 @test8_logical(i32 %i) {
   ret i1 %cond
 }
 
-; FIXME: Vectors should fold too.
 define <2 x i1> @test8vec(<2 x i32> %i) {
 ; CHECK-LABEL: @test8vec(
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne <2 x i32> [[I:%.*]], zeroinitializer
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult <2 x i32> [[I]], <i32 14, i32 14>
-; CHECK-NEXT:    [[COND:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
-; CHECK-NEXT:    ret <2 x i1> [[COND]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add <2 x i32> [[I:%.*]], <i32 -1, i32 -1>
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 13, i32 13>
+; CHECK-NEXT:    ret <2 x i1> [[TMP2]]
 ;
   %cmp1 = icmp ne <2 x i32> %i, zeroinitializer
   %cmp2 = icmp ult <2 x i32> %i, <i32 14, i32 14>

diff  --git a/llvm/test/Transforms/InstCombine/merge-icmp.ll b/llvm/test/Transforms/InstCombine/merge-icmp.ll
index 2a1ddf5e69f2..1202324333d8 100644
--- a/llvm/test/Transforms/InstCombine/merge-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/merge-icmp.ll
@@ -34,12 +34,8 @@ define i1 @test1_logical(i16* %x) {
 define <2 x i1> @test1_vector(<2 x i16>* %x) {
 ; CHECK-LABEL: @test1_vector(
 ; CHECK-NEXT:    [[LOAD:%.*]] = load <2 x i16>, <2 x i16>* [[X:%.*]], align 4
-; CHECK-NEXT:    [[TRUNC:%.*]] = trunc <2 x i16> [[LOAD]] to <2 x i8>
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq <2 x i8> [[TRUNC]], <i8 127, i8 127>
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i16> [[LOAD]], <i16 -256, i16 -256>
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq <2 x i16> [[AND]], <i16 17664, i16 17664>
-; CHECK-NEXT:    [[OR:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
-; CHECK-NEXT:    ret <2 x i1> [[OR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i16> [[LOAD]], <i16 17791, i16 17791>
+; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
 ;
   %load = load <2 x i16>, <2 x i16>* %x, align 4
   %trunc = trunc <2 x i16> %load to <2 x i8>
@@ -83,12 +79,8 @@ define i1 @test2_logical(i16* %x) {
 define <2 x i1> @test2_vector(<2 x i16>* %x) {
 ; CHECK-LABEL: @test2_vector(
 ; CHECK-NEXT:    [[LOAD:%.*]] = load <2 x i16>, <2 x i16>* [[X:%.*]], align 4
-; CHECK-NEXT:    [[AND:%.*]] = and <2 x i16> [[LOAD]], <i16 -256, i16 -256>
-; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq <2 x i16> [[AND]], <i16 32512, i16 32512>
-; CHECK-NEXT:    [[TRUNC:%.*]] = trunc <2 x i16> [[LOAD]] to <2 x i8>
-; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq <2 x i8> [[TRUNC]], <i8 69, i8 69>
-; CHECK-NEXT:    [[OR:%.*]] = and <2 x i1> [[CMP1]], [[CMP2]]
-; CHECK-NEXT:    ret <2 x i1> [[OR]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i16> [[LOAD]], <i16 32581, i16 32581>
+; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
 ;
   %load = load <2 x i16>, <2 x i16>* %x, align 4
   %and = and <2 x i16> %load, <i16 -256, i16 -256>


        


More information about the llvm-commits mailing list