[llvm] [InstCombine] Fold `ceil(X / (2 ^ C)) == 0` -> `X == 0` (PR #143683)

Iris Shi via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 13 05:00:56 PDT 2025


https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/143683

>From 8d56b3a2312bc9325d0701c4a92970c92fea237c Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Wed, 11 Jun 2025 19:00:27 +0800
Subject: [PATCH 1/5] pre-commit test

---
 .../test/Transforms/InstCombine/ceil-shift.ll | 205 ++++++++++++++++++
 1 file changed, 205 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/ceil-shift.ll

diff --git a/llvm/test/Transforms/InstCombine/ceil-shift.ll b/llvm/test/Transforms/InstCombine/ceil-shift.ll
new file mode 100644
index 0000000000000..64038293fa982
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/ceil-shift.ll
@@ -0,0 +1,205 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @ceil_shift4(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift4(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP6:%.*]] = lshr i32 [[ARG0]], 4
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 15
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP6]], [[TMP4]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    ret i1 [[TMP1]]
+;
+  %1 = lshr i32 %arg0, 4
+  %2 = and i32 %arg0, 15
+  %3 = icmp ne i32 %2, 0
+  %4 = zext i1 %3 to i32
+  %5 = add i32 %1, %4
+  %6 = icmp eq i32 %5, 0
+  ret i1 %6
+}
+
+define i1 @ceil_shift6(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift6(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP6:%.*]] = lshr i32 [[ARG0]], 6
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 63
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP6]], [[TMP4]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    ret i1 [[TMP1]]
+;
+  %1 = lshr i32 %arg0, 6
+  %2 = and i32 %arg0, 63
+  %3 = icmp ne i32 %2, 0
+  %4 = zext i1 %3 to i32
+  %5 = add i32 %1, %4
+  %6 = icmp eq i32 %5, 0
+  ret i1 %6
+}
+
+define i1 @ceil_shift11(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift11(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP6:%.*]] = lshr i32 [[ARG0]], 11
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 2047
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP6]], [[TMP4]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    ret i1 [[TMP1]]
+;
+  %1 = lshr i32 %arg0, 11
+  %2 = and i32 %arg0, 2047
+  %3 = icmp ne i32 %2, 0
+  %4 = zext i1 %3 to i32
+  %5 = add i32 %1, %4
+  %6 = icmp eq i32 %5, 0
+  ret i1 %6
+}
+
+define i1 @ceil_shift0(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift0(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
+; CHECK-NEXT:    ret i1 [[TMP1]]
+;
+  %1 = lshr i32 %arg0, 0
+  %2 = and i32 %arg0, 0
+  %3 = icmp ne i32 %2, 0
+  %4 = zext i1 %3 to i32
+  %5 = add i32 %1, %4
+  %6 = icmp eq i32 %5, 0
+  ret i1 %6
+}
+
+declare void @use(i32)
+
+define i1 @ceil_shift4_used_1(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift4_used_1(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
+; CHECK-NEXT:    call void @use(i32 [[TMP1]])
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 15
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    ret i1 [[TMP6]]
+;
+  %1 = lshr i32 %arg0, 4
+  call void @use(i32 %1)
+  %2 = and i32 %arg0, 15
+  %3 = icmp ne i32 %2, 0
+  %4 = zext i1 %3 to i32
+  %5 = add i32 %1, %4
+  %6 = icmp eq i32 %5, 0
+  ret i1 %6
+}
+
+define i1 @ceil_shift4_used_5(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift4_used_5(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 15
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = add nuw nsw i32 [[TMP1]], [[TMP4]]
+; CHECK-NEXT:    call void @use(i32 [[TMP5]])
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    ret i1 [[TMP6]]
+;
+  %1 = lshr i32 %arg0, 4
+  %2 = and i32 %arg0, 15
+  %3 = icmp ne i32 %2, 0
+  %4 = zext i1 %3 to i32
+  %5 = add i32 %1, %4
+  call void @use(i32 %5)
+  %6 = icmp eq i32 %5, 0
+  ret i1 %6
+}
+
+define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {
+; CHECK-LABEL: define <4 x i1> @ceil_shift4_v4i32(
+; CHECK-SAME: <4 x i32> [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP6:%.*]] = lshr <4 x i32> [[ARG0]], splat (i32 16)
+; CHECK-NEXT:    [[TMP2:%.*]] = and <4 x i32> [[ARG0]], splat (i32 65535)
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne <4 x i32> [[TMP2]], zeroinitializer
+; CHECK-NEXT:    [[TMP4:%.*]] = zext <4 x i1> [[TMP3]] to <4 x i32>
+; CHECK-NEXT:    [[TMP5:%.*]] = or <4 x i32> [[TMP6]], [[TMP4]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <4 x i32> [[TMP5]], zeroinitializer
+; CHECK-NEXT:    ret <4 x i1> [[TMP1]]
+;
+  %1 = lshr <4 x i32> %arg0, splat (i32 16)
+  %2 = and <4 x i32> %arg0, splat (i32 65535)
+  %3 = icmp ne <4 x i32> %2, zeroinitializer
+  %4 = zext <4 x i1> %3 to <4 x i32>
+  %5 = add <4 x i32> %1, %4
+  %6 = icmp eq <4 x i32> %5, zeroinitializer
+  ret <4 x i1> %6
+}
+
+define <8 x i1> @ceil_shift4_v8i16(<8 x i16> %arg0) {
+; CHECK-LABEL: define <8 x i1> @ceil_shift4_v8i16(
+; CHECK-SAME: <8 x i16> [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP6:%.*]] = lshr <8 x i16> [[ARG0]], splat (i16 4)
+; CHECK-NEXT:    [[TMP2:%.*]] = and <8 x i16> [[ARG0]], splat (i16 15)
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne <8 x i16> [[TMP2]], zeroinitializer
+; CHECK-NEXT:    [[TMP4:%.*]] = zext <8 x i1> [[TMP3]] to <8 x i16>
+; CHECK-NEXT:    [[TMP5:%.*]] = or <8 x i16> [[TMP6]], [[TMP4]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <8 x i16> [[TMP5]], zeroinitializer
+; CHECK-NEXT:    ret <8 x i1> [[TMP1]]
+;
+  %1 = lshr <8 x i16> %arg0, splat (i16 4)
+  %2 = and <8 x i16> %arg0, splat (i16 15)
+  %3 = icmp ne <8 x i16> %2, zeroinitializer
+  %4 = zext <8 x i1> %3 to <8 x i16>
+  %5 = add <8 x i16> %1, %4
+  %6 = icmp eq <8 x i16> %5, zeroinitializer
+  ret <8 x i1> %6
+}
+
+; negative tests
+
+define i1 @ceil_shift_not_mask_1(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift_not_mask_1(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 31
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    ret i1 [[TMP6]]
+;
+  %1 = lshr i32 %arg0, 4
+  %2 = and i32 %arg0, 31
+  %3 = icmp ne i32 %2, 0
+  %4 = zext i1 %3 to i32
+  %5 = add i32 %1, %4
+  %6 = icmp eq i32 %5, 0
+  ret i1 %6
+}
+
+define i1 @ceil_shift_not_mask_2(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift_not_mask_2(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[ARG0]], 5
+; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 15
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
+; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
+; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    ret i1 [[TMP6]]
+;
+  %1 = lshr i32 %arg0, 5
+  %2 = and i32 %arg0, 15
+  %3 = icmp ne i32 %2, 0
+  %4 = zext i1 %3 to i32
+  %5 = add i32 %1, %4
+  %6 = icmp eq i32 %5, 0
+  ret i1 %6
+}

>From 7088b465c2dc55dd29330e7266533e63fe4f2433 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Wed, 11 Jun 2025 18:13:10 +0800
Subject: [PATCH 2/5] [InstCombine] Fold `ceil(X >> C) == 0 -> X == 0`

---
 .../InstCombine/InstCombineCompares.cpp        | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index c112fae351817..4569a2cd82d2a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -20,6 +20,7 @@
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/Analysis/Utils/Local.h"
 #include "llvm/Analysis/VectorUtils.h"
+#include "llvm/IR/CmpPredicate.h"
 #include "llvm/IR/ConstantRange.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/InstrTypes.h"
@@ -1298,6 +1299,23 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
     // eq/ne (mul X, Y)) with (icmp eq/ne X/Y) and if X/Y is known non-zero that
     // will fold to a constant elsewhere.
   }
+
+  // (X >> C) + ((X & ((1 << C) - 1)) != 0) == 0 -> X == 0
+  if (Pred == ICmpInst::ICMP_EQ) {
+    Value *X;
+    const APInt *C1, *C2;
+    CmpPredicate PredNE;
+    if (match(Cmp.getOperand(0),
+              m_OneUse(
+                  m_Add(m_LShr(m_Value(X), m_APInt(C1)),
+                        m_ZExt(m_ICmp(PredNE, m_And(m_Deferred(X), m_APInt(C2)),
+                                      m_Zero()))))) &&
+        PredNE == CmpInst::ICMP_NE &&
+        *C2 == APInt::getLowBitsSet(C2->getBitWidth(), C1->getZExtValue()))
+      return new ICmpInst(ICmpInst::ICMP_EQ, X,
+                          ConstantInt::getNullValue(X->getType()));
+  }
+
   return nullptr;
 }
 

>From f1b58a2ad5e680998d8b550fd409daba457d0cf4 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Wed, 11 Jun 2025 19:01:06 +0800
Subject: [PATCH 3/5] update test

---
 .../test/Transforms/InstCombine/ceil-shift.ll | 41 +++----------------
 1 file changed, 6 insertions(+), 35 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/ceil-shift.ll b/llvm/test/Transforms/InstCombine/ceil-shift.ll
index 64038293fa982..853985eff258d 100644
--- a/llvm/test/Transforms/InstCombine/ceil-shift.ll
+++ b/llvm/test/Transforms/InstCombine/ceil-shift.ll
@@ -4,12 +4,7 @@
 define i1 @ceil_shift4(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift4(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP6:%.*]] = lshr i32 [[ARG0]], 4
-; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 15
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
-; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
-; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP6]], [[TMP4]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %1 = lshr i32 %arg0, 4
@@ -24,12 +19,7 @@ define i1 @ceil_shift4(i32 %arg0) {
 define i1 @ceil_shift6(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift6(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP6:%.*]] = lshr i32 [[ARG0]], 6
-; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 63
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
-; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
-; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP6]], [[TMP4]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %1 = lshr i32 %arg0, 6
@@ -44,12 +34,7 @@ define i1 @ceil_shift6(i32 %arg0) {
 define i1 @ceil_shift11(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift11(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP6:%.*]] = lshr i32 [[ARG0]], 11
-; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 2047
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
-; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
-; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP6]], [[TMP4]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %1 = lshr i32 %arg0, 11
@@ -83,11 +68,7 @@ define i1 @ceil_shift4_used_1(i32 %arg0) {
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
 ; CHECK-NEXT:    call void @use(i32 [[TMP1]])
-; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 15
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
-; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
-; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]
-; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP6]]
 ;
   %1 = lshr i32 %arg0, 4
@@ -125,12 +106,7 @@ define i1 @ceil_shift4_used_5(i32 %arg0) {
 define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {
 ; CHECK-LABEL: define <4 x i1> @ceil_shift4_v4i32(
 ; CHECK-SAME: <4 x i32> [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP6:%.*]] = lshr <4 x i32> [[ARG0]], splat (i32 16)
-; CHECK-NEXT:    [[TMP2:%.*]] = and <4 x i32> [[ARG0]], splat (i32 65535)
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne <4 x i32> [[TMP2]], zeroinitializer
-; CHECK-NEXT:    [[TMP4:%.*]] = zext <4 x i1> [[TMP3]] to <4 x i32>
-; CHECK-NEXT:    [[TMP5:%.*]] = or <4 x i32> [[TMP6]], [[TMP4]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <4 x i32> [[TMP5]], zeroinitializer
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <4 x i32> [[ARG0]], zeroinitializer
 ; CHECK-NEXT:    ret <4 x i1> [[TMP1]]
 ;
   %1 = lshr <4 x i32> %arg0, splat (i32 16)
@@ -145,12 +121,7 @@ define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {
 define <8 x i1> @ceil_shift4_v8i16(<8 x i16> %arg0) {
 ; CHECK-LABEL: define <8 x i1> @ceil_shift4_v8i16(
 ; CHECK-SAME: <8 x i16> [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP6:%.*]] = lshr <8 x i16> [[ARG0]], splat (i16 4)
-; CHECK-NEXT:    [[TMP2:%.*]] = and <8 x i16> [[ARG0]], splat (i16 15)
-; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne <8 x i16> [[TMP2]], zeroinitializer
-; CHECK-NEXT:    [[TMP4:%.*]] = zext <8 x i1> [[TMP3]] to <8 x i16>
-; CHECK-NEXT:    [[TMP5:%.*]] = or <8 x i16> [[TMP6]], [[TMP4]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <8 x i16> [[TMP5]], zeroinitializer
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <8 x i16> [[ARG0]], zeroinitializer
 ; CHECK-NEXT:    ret <8 x i1> [[TMP1]]
 ;
   %1 = lshr <8 x i16> %arg0, splat (i16 4)

>From 518c6e653c3cbc4e34bc329764a02cba356cb7af Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Fri, 13 Jun 2025 19:58:36 +0800
Subject: [PATCH 4/5] 1

---
 .../test/Transforms/InstCombine/ceil-shift.ll | 227 ++++++++++++------
 1 file changed, 148 insertions(+), 79 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/ceil-shift.ll b/llvm/test/Transforms/InstCombine/ceil-shift.ll
index 853985eff258d..fe58dc5f15c9c 100644
--- a/llvm/test/Transforms/InstCombine/ceil-shift.ll
+++ b/llvm/test/Transforms/InstCombine/ceil-shift.ll
@@ -4,46 +4,81 @@
 define i1 @ceil_shift4(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift4(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
+; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
+; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 15
+; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
+; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
+; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
-  %1 = lshr i32 %arg0, 4
-  %2 = and i32 %arg0, 15
-  %3 = icmp ne i32 %2, 0
-  %4 = zext i1 %3 to i32
-  %5 = add i32 %1, %4
-  %6 = icmp eq i32 %5, 0
-  ret i1 %6
+  %quot = lshr i32 %arg0, 4
+  %rem = and i32 %arg0, 15
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %quot_or_rem = or i32 %quot, %zext_has_rem
+  %is_zero = icmp eq i32 %quot_or_rem, 0
+  ret i1 %is_zero
+}
+
+define i1 @ceil_shift4_add(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift4_add(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
+; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 15
+; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
+; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
+; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    ret i1 [[TMP6]]
+;
+  %quot = lshr i32 %arg0, 4
+  %rem = and i32 %arg0, 15
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %ceil = add i32 %quot, %zext_has_rem
+  %res = icmp eq i32 %ceil, 0
+  ret i1 %res
 }
 
 define i1 @ceil_shift6(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift6(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
+; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 6
+; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 63
+; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
+; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
+; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
-  %1 = lshr i32 %arg0, 6
-  %2 = and i32 %arg0, 63
-  %3 = icmp ne i32 %2, 0
-  %4 = zext i1 %3 to i32
-  %5 = add i32 %1, %4
-  %6 = icmp eq i32 %5, 0
-  ret i1 %6
+  %quot = lshr i32 %arg0, 6
+  %rem = and i32 %arg0, 63
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %quot_or_rem = or i32 %quot, %zext_has_rem
+  %res = icmp eq i32 %quot_or_rem, 0
+  ret i1 %res
 }
 
 define i1 @ceil_shift11(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift11(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
+; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 11
+; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 2047
+; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
+; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
+; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
-  %1 = lshr i32 %arg0, 11
-  %2 = and i32 %arg0, 2047
-  %3 = icmp ne i32 %2, 0
-  %4 = zext i1 %3 to i32
-  %5 = add i32 %1, %4
-  %6 = icmp eq i32 %5, 0
-  ret i1 %6
+  %quot = lshr i32 %arg0, 11
+  %rem = and i32 %arg0, 2047
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %quot_or_rem = or i32 %quot, %zext_has_rem
+  %res = icmp eq i32 %quot_or_rem, 0
+  ret i1 %res
 }
 
 define i1 @ceil_shift0(i32 %arg0) {
@@ -52,13 +87,33 @@ define i1 @ceil_shift0(i32 %arg0) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
-  %1 = lshr i32 %arg0, 0
-  %2 = and i32 %arg0, 0
-  %3 = icmp ne i32 %2, 0
-  %4 = zext i1 %3 to i32
-  %5 = add i32 %1, %4
-  %6 = icmp eq i32 %5, 0
-  ret i1 %6
+  %quot = lshr i32 %arg0, 0
+  %rem = and i32 %arg0, 0
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %quot_or_rem = or i32 %quot, %zext_has_rem
+  %res = icmp eq i32 %quot_or_rem, 0
+  ret i1 %res
+}
+
+define i1 @ceil_shift4_comm(i32 %arg0) {
+; CHECK-LABEL: define i1 @ceil_shift4_comm(
+; CHECK-SAME: i32 [[ARG0:%.*]]) {
+; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
+; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 15
+; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
+; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
+; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
+; CHECK-NEXT:    ret i1 [[TMP6]]
+;
+  %quot = lshr i32 %arg0, 4
+  %rem = and i32 %arg0, 15
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %quot_or_rem = or i32 %zext_has_rem, %quot
+  %res = icmp eq i32 %quot_or_rem, 0
+  ret i1 %res
 }
 
 declare void @use(i32)
@@ -68,17 +123,21 @@ define i1 @ceil_shift4_used_1(i32 %arg0) {
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
 ; CHECK-NEXT:    call void @use(i32 [[TMP1]])
-; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0
+; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 15
+; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
+; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
+; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[TMP1]], [[ZEXT_HAS_REM]]
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
 ; CHECK-NEXT:    ret i1 [[TMP6]]
 ;
-  %1 = lshr i32 %arg0, 4
-  call void @use(i32 %1)
-  %2 = and i32 %arg0, 15
-  %3 = icmp ne i32 %2, 0
-  %4 = zext i1 %3 to i32
-  %5 = add i32 %1, %4
-  %6 = icmp eq i32 %5, 0
-  ret i1 %6
+  %quot = lshr i32 %arg0, 4
+  call void @use(i32 %quot)
+  %rem = and i32 %arg0, 15
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %quot_or_rem = or i32 %quot, %zext_has_rem
+  %res = icmp eq i32 %quot_or_rem, 0
+  ret i1 %res
 }
 
 define i1 @ceil_shift4_used_5(i32 %arg0) {
@@ -88,49 +147,59 @@ define i1 @ceil_shift4_used_5(i32 %arg0) {
 ; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[ARG0]], 15
 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
 ; CHECK-NEXT:    [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
-; CHECK-NEXT:    [[TMP5:%.*]] = add nuw nsw i32 [[TMP1]], [[TMP4]]
+; CHECK-NEXT:    [[TMP5:%.*]] = or i32 [[TMP1]], [[TMP4]]
 ; CHECK-NEXT:    call void @use(i32 [[TMP5]])
 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
 ; CHECK-NEXT:    ret i1 [[TMP6]]
 ;
-  %1 = lshr i32 %arg0, 4
-  %2 = and i32 %arg0, 15
-  %3 = icmp ne i32 %2, 0
-  %4 = zext i1 %3 to i32
-  %5 = add i32 %1, %4
-  call void @use(i32 %5)
-  %6 = icmp eq i32 %5, 0
-  ret i1 %6
+  %quot = lshr i32 %arg0, 4
+  %rem = and i32 %arg0, 15
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %quot_or_rem = or i32 %quot, %zext_has_rem
+  call void @use(i32 %quot_or_rem)
+  %res = icmp eq i32 %quot_or_rem, 0
+  ret i1 %res
 }
 
 define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {
 ; CHECK-LABEL: define <4 x i1> @ceil_shift4_v4i32(
 ; CHECK-SAME: <4 x i32> [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <4 x i32> [[ARG0]], zeroinitializer
+; CHECK-NEXT:    [[QUOT:%.*]] = lshr <4 x i32> [[ARG0]], splat (i32 16)
+; CHECK-NEXT:    [[REM:%.*]] = and <4 x i32> [[ARG0]], splat (i32 65535)
+; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne <4 x i32> [[REM]], zeroinitializer
+; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext <4 x i1> [[HAS_REM]] to <4 x i32>
+; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or <4 x i32> [[QUOT]], [[ZEXT_HAS_REM]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <4 x i32> [[QUOT_OR_REM]], zeroinitializer
 ; CHECK-NEXT:    ret <4 x i1> [[TMP1]]
 ;
-  %1 = lshr <4 x i32> %arg0, splat (i32 16)
-  %2 = and <4 x i32> %arg0, splat (i32 65535)
-  %3 = icmp ne <4 x i32> %2, zeroinitializer
-  %4 = zext <4 x i1> %3 to <4 x i32>
-  %5 = add <4 x i32> %1, %4
-  %6 = icmp eq <4 x i32> %5, zeroinitializer
-  ret <4 x i1> %6
+  %quot = lshr <4 x i32> %arg0, splat (i32 16)
+  %rem = and <4 x i32> %arg0, splat (i32 65535)
+  %has_rem = icmp ne <4 x i32> %rem, zeroinitializer
+  %zext_has_rem = zext <4 x i1> %has_rem to <4 x i32>
+  %quot_or_rem = or <4 x i32> %quot, %zext_has_rem
+  %res = icmp eq <4 x i32> %quot_or_rem, zeroinitializer
+  ret <4 x i1> %res
 }
 
 define <8 x i1> @ceil_shift4_v8i16(<8 x i16> %arg0) {
 ; CHECK-LABEL: define <8 x i1> @ceil_shift4_v8i16(
 ; CHECK-SAME: <8 x i16> [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <8 x i16> [[ARG0]], zeroinitializer
+; CHECK-NEXT:    [[QUOT:%.*]] = lshr <8 x i16> [[ARG0]], splat (i16 4)
+; CHECK-NEXT:    [[REM:%.*]] = and <8 x i16> [[ARG0]], splat (i16 15)
+; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne <8 x i16> [[REM]], zeroinitializer
+; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext <8 x i1> [[HAS_REM]] to <8 x i16>
+; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or <8 x i16> [[QUOT]], [[ZEXT_HAS_REM]]
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <8 x i16> [[QUOT_OR_REM]], zeroinitializer
 ; CHECK-NEXT:    ret <8 x i1> [[TMP1]]
 ;
-  %1 = lshr <8 x i16> %arg0, splat (i16 4)
-  %2 = and <8 x i16> %arg0, splat (i16 15)
-  %3 = icmp ne <8 x i16> %2, zeroinitializer
-  %4 = zext <8 x i1> %3 to <8 x i16>
-  %5 = add <8 x i16> %1, %4
-  %6 = icmp eq <8 x i16> %5, zeroinitializer
-  ret <8 x i1> %6
+  %quot = lshr <8 x i16> %arg0, splat (i16 4)
+  %rem = and <8 x i16> %arg0, splat (i16 15)
+  %has_rem = icmp ne <8 x i16> %rem, zeroinitializer
+  %zext_has_rem = zext <8 x i1> %has_rem to <8 x i16>
+  %quot_or_rem = or <8 x i16> %quot, %zext_has_rem
+  %res = icmp eq <8 x i16> %quot_or_rem, zeroinitializer
+  ret <8 x i1> %res
 }
 
 ; negative tests
@@ -146,13 +215,13 @@ define i1 @ceil_shift_not_mask_1(i32 %arg0) {
 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
 ; CHECK-NEXT:    ret i1 [[TMP6]]
 ;
-  %1 = lshr i32 %arg0, 4
-  %2 = and i32 %arg0, 31
-  %3 = icmp ne i32 %2, 0
-  %4 = zext i1 %3 to i32
-  %5 = add i32 %1, %4
-  %6 = icmp eq i32 %5, 0
-  ret i1 %6
+  %quot = lshr i32 %arg0, 4
+  %rem = and i32 %arg0, 31
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %quot_or_rem = or i32 %quot, %zext_has_rem
+  %res = icmp eq i32 %quot_or_rem, 0
+  ret i1 %res
 }
 
 define i1 @ceil_shift_not_mask_2(i32 %arg0) {
@@ -166,11 +235,11 @@ define i1 @ceil_shift_not_mask_2(i32 %arg0) {
 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP5]], 0
 ; CHECK-NEXT:    ret i1 [[TMP6]]
 ;
-  %1 = lshr i32 %arg0, 5
-  %2 = and i32 %arg0, 15
-  %3 = icmp ne i32 %2, 0
-  %4 = zext i1 %3 to i32
-  %5 = add i32 %1, %4
-  %6 = icmp eq i32 %5, 0
-  ret i1 %6
+  %quot = lshr i32 %arg0, 5
+  %rem = and i32 %arg0, 15
+  %has_rem = icmp ne i32 %rem, 0
+  %zext_has_rem = zext i1 %has_rem to i32
+  %quot_or_rem = or i32 %quot, %zext_has_rem
+  %res = icmp eq i32 %quot_or_rem, 0
+  ret i1 %res
 }

>From 0348a12e5365a3b8c7b647f6bd4fed5c9e1ff2dc Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Fri, 13 Jun 2025 20:00:11 +0800
Subject: [PATCH 5/5] address review comments

---
 .../InstCombine/InstCombineCompares.cpp       | 15 +++--
 .../test/Transforms/InstCombine/ceil-shift.ll | 55 +++----------------
 2 files changed, 15 insertions(+), 55 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 4569a2cd82d2a..0e1461cc72caf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1300,17 +1300,16 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
     // will fold to a constant elsewhere.
   }
 
-  // (X >> C) + ((X & ((1 << C) - 1)) != 0) == 0 -> X == 0
-  if (Pred == ICmpInst::ICMP_EQ) {
+  // (X >> C) | ((X & ((1 << C) - 1)) != 0) == 0 -> X == 0
+  if (ICmpInst::isEquality(Pred)) {
     Value *X;
     const APInt *C1, *C2;
-    CmpPredicate PredNE;
     if (match(Cmp.getOperand(0),
-              m_OneUse(
-                  m_Add(m_LShr(m_Value(X), m_APInt(C1)),
-                        m_ZExt(m_ICmp(PredNE, m_And(m_Deferred(X), m_APInt(C2)),
-                                      m_Zero()))))) &&
-        PredNE == CmpInst::ICMP_NE &&
+              m_OneUse(m_c_Or(
+                  m_LShr(m_Value(X), m_APInt(C1)),
+                  m_ZExt(m_SpecificICmp(ICmpInst::ICMP_NE,
+                                        m_And(m_Deferred(X), m_APInt(C2)),
+                                        m_Zero()))))) &&
         *C2 == APInt::getLowBitsSet(C2->getBitWidth(), C1->getZExtValue()))
       return new ICmpInst(ICmpInst::ICMP_EQ, X,
                           ConstantInt::getNullValue(X->getType()));
diff --git a/llvm/test/Transforms/InstCombine/ceil-shift.ll b/llvm/test/Transforms/InstCombine/ceil-shift.ll
index fe58dc5f15c9c..721bdb1d42bad 100644
--- a/llvm/test/Transforms/InstCombine/ceil-shift.ll
+++ b/llvm/test/Transforms/InstCombine/ceil-shift.ll
@@ -4,12 +4,7 @@
 define i1 @ceil_shift4(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift4(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
-; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 15
-; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
-; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
-; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %quot = lshr i32 %arg0, 4
@@ -24,12 +19,7 @@ define i1 @ceil_shift4(i32 %arg0) {
 define i1 @ceil_shift4_add(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift4_add(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
-; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 15
-; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
-; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
-; CHECK-NEXT:    [[TMP1:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
-; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP6]]
 ;
   %quot = lshr i32 %arg0, 4
@@ -44,12 +34,7 @@ define i1 @ceil_shift4_add(i32 %arg0) {
 define i1 @ceil_shift6(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift6(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 6
-; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 63
-; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
-; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
-; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %quot = lshr i32 %arg0, 6
@@ -64,12 +49,7 @@ define i1 @ceil_shift6(i32 %arg0) {
 define i1 @ceil_shift11(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift11(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 11
-; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 2047
-; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
-; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
-; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP1]]
 ;
   %quot = lshr i32 %arg0, 11
@@ -99,12 +79,7 @@ define i1 @ceil_shift0(i32 %arg0) {
 define i1 @ceil_shift4_comm(i32 %arg0) {
 ; CHECK-LABEL: define i1 @ceil_shift4_comm(
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[QUOT:%.*]] = lshr i32 [[ARG0]], 4
-; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 15
-; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
-; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
-; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[QUOT]], [[ZEXT_HAS_REM]]
-; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP6]]
 ;
   %quot = lshr i32 %arg0, 4
@@ -123,11 +98,7 @@ define i1 @ceil_shift4_used_1(i32 %arg0) {
 ; CHECK-SAME: i32 [[ARG0:%.*]]) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[ARG0]], 4
 ; CHECK-NEXT:    call void @use(i32 [[TMP1]])
-; CHECK-NEXT:    [[REM:%.*]] = and i32 [[ARG0]], 15
-; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne i32 [[REM]], 0
-; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext i1 [[HAS_REM]] to i32
-; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or i32 [[TMP1]], [[ZEXT_HAS_REM]]
-; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[QUOT_OR_REM]], 0
+; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[ARG0]], 0
 ; CHECK-NEXT:    ret i1 [[TMP6]]
 ;
   %quot = lshr i32 %arg0, 4
@@ -165,12 +136,7 @@ define i1 @ceil_shift4_used_5(i32 %arg0) {
 define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {
 ; CHECK-LABEL: define <4 x i1> @ceil_shift4_v4i32(
 ; CHECK-SAME: <4 x i32> [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[QUOT:%.*]] = lshr <4 x i32> [[ARG0]], splat (i32 16)
-; CHECK-NEXT:    [[REM:%.*]] = and <4 x i32> [[ARG0]], splat (i32 65535)
-; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne <4 x i32> [[REM]], zeroinitializer
-; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext <4 x i1> [[HAS_REM]] to <4 x i32>
-; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or <4 x i32> [[QUOT]], [[ZEXT_HAS_REM]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <4 x i32> [[QUOT_OR_REM]], zeroinitializer
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <4 x i32> [[ARG0]], zeroinitializer
 ; CHECK-NEXT:    ret <4 x i1> [[TMP1]]
 ;
   %quot = lshr <4 x i32> %arg0, splat (i32 16)
@@ -185,12 +151,7 @@ define <4 x i1> @ceil_shift4_v4i32(<4 x i32> %arg0) {
 define <8 x i1> @ceil_shift4_v8i16(<8 x i16> %arg0) {
 ; CHECK-LABEL: define <8 x i1> @ceil_shift4_v8i16(
 ; CHECK-SAME: <8 x i16> [[ARG0:%.*]]) {
-; CHECK-NEXT:    [[QUOT:%.*]] = lshr <8 x i16> [[ARG0]], splat (i16 4)
-; CHECK-NEXT:    [[REM:%.*]] = and <8 x i16> [[ARG0]], splat (i16 15)
-; CHECK-NEXT:    [[HAS_REM:%.*]] = icmp ne <8 x i16> [[REM]], zeroinitializer
-; CHECK-NEXT:    [[ZEXT_HAS_REM:%.*]] = zext <8 x i1> [[HAS_REM]] to <8 x i16>
-; CHECK-NEXT:    [[QUOT_OR_REM:%.*]] = or <8 x i16> [[QUOT]], [[ZEXT_HAS_REM]]
-; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <8 x i16> [[QUOT_OR_REM]], zeroinitializer
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <8 x i16> [[ARG0]], zeroinitializer
 ; CHECK-NEXT:    ret <8 x i1> [[TMP1]]
 ;
   %quot = lshr <8 x i16> %arg0, splat (i16 4)



More information about the llvm-commits mailing list