[llvm] [InstCombine] Fold zext-of-icmp with no shift (PR #68503)

via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 7 21:16:23 PDT 2023


https://github.com/vfdff created https://github.com/llvm/llvm-project/pull/68503

This regression triggers after commit f400daa to fix infinite loop issue.

In this case, we can known the shift count is 0, so it will not be
triggered by the form of (iN (~X) u>> (N - 1)) in commit 21d3871, of
which N indicates the data type bitwidth of X.

Fixes https://github.com/llvm/llvm-project/issues/68465

>From ca258ba5c457694e1d2faf6076782e593349c39f Mon Sep 17 00:00:00 2001
From: zhongyunde 00443407 <zhongyunde at huawei.com>
Date: Sat, 7 Oct 2023 04:43:57 -0400
Subject: [PATCH 1/3] [InstCombine] Refactor the function transformZExtICmp,
 NFC

---
 .../InstCombine/InstCombineCasts.cpp          | 49 +++++++++----------
 1 file changed, 23 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 20c13de33f8189d..515d99006f0afdf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -904,37 +904,34 @@ Instruction *InstCombinerImpl::transformZExtICmp(ICmpInst *Cmp,
     // zext (X == 0) to i32 --> (X>>1)^1 iff X has only the 2nd bit set.
     // zext (X != 0) to i32 --> X        iff X has only the low bit set.
     // zext (X != 0) to i32 --> X>>1     iff X has only the 2nd bit set.
-    if (Op1CV->isZero() && Cmp->isEquality() &&
+
+    // Exactly 1 possible 1? But not the high-bit because that is
+    // canonicalized to this form.
+    KnownBits Known = computeKnownBits(Cmp->getOperand(0), 0, &Zext);
+    APInt KnownZeroMask(~Known.Zero);
+    uint32_t ShAmt = KnownZeroMask.logBase2();
+    bool isExpectShAmt = KnownZeroMask.isPowerOf2() &&
+                         (Zext.getType()->getScalarSizeInBits() != ShAmt + 1);
+    if (Op1CV->isZero() && Cmp->isEquality() && isExpectShAmt &&
         (Cmp->getOperand(0)->getType() == Zext.getType() ||
          Cmp->getPredicate() == ICmpInst::ICMP_NE)) {
-      // If Op1C some other power of two, convert:
-      KnownBits Known = computeKnownBits(Cmp->getOperand(0), 0, &Zext);
-
-      // Exactly 1 possible 1? But not the high-bit because that is
-      // canonicalized to this form.
-      APInt KnownZeroMask(~Known.Zero);
-      if (KnownZeroMask.isPowerOf2() &&
-          (Zext.getType()->getScalarSizeInBits() !=
-           KnownZeroMask.logBase2() + 1)) {
-        uint32_t ShAmt = KnownZeroMask.logBase2();
-        Value *In = Cmp->getOperand(0);
-        if (ShAmt) {
-          // Perform a logical shr by shiftamt.
-          // Insert the shift to put the result in the low bit.
-          In = Builder.CreateLShr(In, ConstantInt::get(In->getType(), ShAmt),
-                                  In->getName() + ".lobit");
-        }
+      Value *In = Cmp->getOperand(0);
+      if (ShAmt) {
+        // Perform a logical shr by shiftamt.
+        // Insert the shift to put the result in the low bit.
+        In = Builder.CreateLShr(In, ConstantInt::get(In->getType(), ShAmt),
+                                In->getName() + ".lobit");
+      }
 
-        // Toggle the low bit for "X == 0".
-        if (Cmp->getPredicate() == ICmpInst::ICMP_EQ)
-          In = Builder.CreateXor(In, ConstantInt::get(In->getType(), 1));
+      // Toggle the low bit for "X == 0".
+      if (Cmp->getPredicate() == ICmpInst::ICMP_EQ)
+        In = Builder.CreateXor(In, ConstantInt::get(In->getType(), 1));
 
-        if (Zext.getType() == In->getType())
-          return replaceInstUsesWith(Zext, In);
+      if (Zext.getType() == In->getType())
+        return replaceInstUsesWith(Zext, In);
 
-        Value *IntCast = Builder.CreateIntCast(In, Zext.getType(), false);
-        return replaceInstUsesWith(Zext, IntCast);
-      }
+      Value *IntCast = Builder.CreateIntCast(In, Zext.getType(), false);
+      return replaceInstUsesWith(Zext, IntCast);
     }
   }
 

>From 19ee87f7634eeb6249c2dd12acc1e70bfdd5e152 Mon Sep 17 00:00:00 2001
From: zhongyunde 00443407 <zhongyunde at huawei.com>
Date: Sat, 7 Oct 2023 23:44:18 -0400
Subject: [PATCH 2/3] [InstCombine] Precommit test for PR68465

---
 llvm/test/Transforms/InstCombine/zext.ll | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll
index 8aa2a10e6abb2ea..00147bb523f474e 100644
--- a/llvm/test/Transforms/InstCombine/zext.ll
+++ b/llvm/test/Transforms/InstCombine/zext.ll
@@ -748,3 +748,16 @@ define i64 @zext_icmp_ne_bool_1(ptr %ptr) {
   %len = zext i1 %cmp to i64
   ret i64 %len
 }
+
+define i32  @zext_icmp_eq0_no_shift(ptr %ptr ) {
+; CHECK-LABEL: @zext_icmp_eq0_no_shift(
+; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[PTR:%.*]], align 1, !range [[RNG1:![0-9]+]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT:    [[RES:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT:    ret i32 [[RES]]
+;
+  %X = load i8, ptr %ptr,align 1, !range !{i8 0, i8 2} ; range [0, 2)
+  %cmp = icmp eq i8 %X, 0
+  %res = zext i1 %cmp to i32
+  ret i32 %res
+}

>From ed13ade474fa5acebea024730ad99160a9d71a7c Mon Sep 17 00:00:00 2001
From: zhongyunde 00443407 <zhongyunde at huawei.com>
Date: Sat, 7 Oct 2023 23:02:13 -0400
Subject: [PATCH 3/3] [InstCombine] Fold zext-of-icmp with no shift

This regression triggers after commit f400daa to fix infinite loop issue.

In this case, we can known the shift count is 0, so it will not be
triggered by the form of (iN (~X) u>> (N - 1)) in commit 21d3871, of
which N indicates the data type bitwidth of X.

Fixes https://github.com/llvm/llvm-project/issues/68465
---
 llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 2 +-
 llvm/test/Transforms/InstCombine/zext.ll             | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 515d99006f0afdf..f7c6fb2a2bf2958 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -914,7 +914,7 @@ Instruction *InstCombinerImpl::transformZExtICmp(ICmpInst *Cmp,
                          (Zext.getType()->getScalarSizeInBits() != ShAmt + 1);
     if (Op1CV->isZero() && Cmp->isEquality() && isExpectShAmt &&
         (Cmp->getOperand(0)->getType() == Zext.getType() ||
-         Cmp->getPredicate() == ICmpInst::ICMP_NE)) {
+         Cmp->getPredicate() == ICmpInst::ICMP_NE || ShAmt == 0)) {
       Value *In = Cmp->getOperand(0);
       if (ShAmt) {
         // Perform a logical shr by shiftamt.
diff --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll
index 00147bb523f474e..29b6601774a89b3 100644
--- a/llvm/test/Transforms/InstCombine/zext.ll
+++ b/llvm/test/Transforms/InstCombine/zext.ll
@@ -752,7 +752,7 @@ define i64 @zext_icmp_ne_bool_1(ptr %ptr) {
 define i32  @zext_icmp_eq0_no_shift(ptr %ptr ) {
 ; CHECK-LABEL: @zext_icmp_eq0_no_shift(
 ; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[PTR:%.*]], align 1, !range [[RNG1:![0-9]+]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[X]], 1
 ; CHECK-NEXT:    [[RES:%.*]] = zext i8 [[TMP1]] to i32
 ; CHECK-NEXT:    ret i32 [[RES]]
 ;



More information about the llvm-commits mailing list