[PATCH] D112634: [InstCombine] canonicalize icmp with trunc op into mask and cmp, part 2

Sanjay Patel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 27 10:00:29 PDT 2021


spatel created this revision.
spatel added a reviewer: lebedev.ri.
Herald added subscribers: hiraditya, mcrosier.
spatel requested review of this revision.
Herald added a project: LLVM.

If C is a high-bit mask:
(trunc X) u< C --> (X & C) != C (are any masked-high-bits clear?)

This extends the fold added with:
acabad9ff6bf <https://reviews.llvm.org/rGacabad9ff6bf13e00305d9d8621ee8eafc1f8b08>

We discussed using decomposeBitTestICmp() to generalize this, but that function doesn't line up with the other fold that I was imagining (maybe there's some way to adapt/invert the logic?).

This patch also modifies the code to create the mask constant from the earlier patch in an attempt to make the bit-masking relationships clearer. I can make that an NFC pre-commit to be safer.

Here are Alive2 generalizations for both of the folds:
https://alive2.llvm.org/ce/z/u-ZpC_  (the previous patch)
https://alive2.llvm.org/ce/z/Kdp4jc  (this patch)


https://reviews.llvm.org/D112634

Files:
  llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
  llvm/test/Transforms/InstCombine/icmp-trunc.ll


Index: llvm/test/Transforms/InstCombine/icmp-trunc.ll
===================================================================
--- llvm/test/Transforms/InstCombine/icmp-trunc.ll
+++ llvm/test/Transforms/InstCombine/icmp-trunc.ll
@@ -71,8 +71,8 @@
 
 define i1 @ult_192(i32 %x) {
 ; CHECK-LABEL: @ult_192(
-; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[X:%.*]] to i8
-; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T]], -64
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], 192
+; CHECK-NEXT:    [[R:%.*]] = icmp ne i32 [[TMP1]], 192
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %t = trunc i32 %x to i8
@@ -82,8 +82,8 @@
 
 define <2 x i1> @ult_2044_splat(<2 x i16> %x) {
 ; CHECK-LABEL: @ult_2044_splat(
-; CHECK-NEXT:    [[T:%.*]] = trunc <2 x i16> [[X:%.*]] to <2 x i11>
-; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i11> [[T]], <i11 -4, i11 -4>
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i16> [[X:%.*]], <i16 2044, i16 2044>
+; CHECK-NEXT:    [[R:%.*]] = icmp ne <2 x i16> [[TMP1]], <i16 2044, i16 2044>
 ; CHECK-NEXT:    ret <2 x i1> [[R]]
 ;
   %t = trunc <2 x i16> %x to <2 x i11>
Index: llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4598,19 +4598,30 @@
   // The trunc masks high bits while the compare may effectively mask low bits.
   Value *X;
   const APInt *C;
-  if (match(Op0, m_OneUse(m_Trunc(m_Value(X)))) && match(Op1, m_Power2(C))) {
-    if (Pred == ICmpInst::ICMP_ULT) {
-      // (trunc X) u< Pow2C --> (X & MaskC) == 0
-      unsigned SrcBits = X->getType()->getScalarSizeInBits();
-      unsigned DstBits = Op0->getType()->getScalarSizeInBits();
-      APInt MaskC = APInt::getOneBitSet(SrcBits, DstBits) - C->zext(SrcBits);
+  if (!match(Op0, m_OneUse(m_Trunc(m_Value(X)))) || !match(Op1, m_APInt(C)))
+    return nullptr;
+
+  unsigned SrcBits = X->getType()->getScalarSizeInBits();
+  if (Pred == ICmpInst::ICMP_ULT) {
+    // If C is a power-of-2:
+    // (trunc X) u< C --> X & (~C + 1) == 0 (are all masked-high-bits clear?)
+    if (C->isPowerOf2()) {
+      Constant *MaskC = ConstantInt::get(X->getType(), (~*C + 1).zext(SrcBits));
       Value *And = Builder.CreateAnd(X, MaskC);
       Constant *Zero = ConstantInt::getNullValue(X->getType());
       return new ICmpInst(ICmpInst::ICMP_EQ, And, Zero);
     }
-    // TODO: Handle ugt.
+    // If C is a high-bit mask:
+    // (trunc X) u< C --> (X & C) != C (are any masked-high-bits clear?)
+    if ((~(*C)).isMask()) {
+      Constant *MaskC = ConstantInt::get(X->getType(), C->zext(SrcBits));
+      Value *And = Builder.CreateAnd(X, MaskC);
+      return new ICmpInst(ICmpInst::ICMP_NE, And, MaskC);
+    }
   }
 
+  // TODO: Handle ugt.
+
   return nullptr;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D112634.382703.patch
Type: text/x-patch
Size: 2831 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20211027/7efdfd1c/attachment.bin>


More information about the llvm-commits mailing list