[llvm] [InstCombine] Improve range computation in `foldICmpAddConstant` (PR #155096)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 23 22:19:36 PDT 2025


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/155096

>From 61c7f29df90616a5a522874ba6a42806dc1a2480 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 23 Aug 2025 20:37:59 +0800
Subject: [PATCH 1/3] [InstCombine] Improve range computation in
 `foldICmpAddConstant`

---
 .../InstCombine/InstCombineCompares.cpp       | 26 +++++++++----------
 llvm/test/Transforms/InstCombine/icmp-add.ll  | 16 ++++--------
 2 files changed, 17 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 2386e7ad47fb7..3a8e043038153 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3320,20 +3320,18 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
     Type *NewCmpTy = V->getType();
     unsigned NewCmpBW = NewCmpTy->getScalarSizeInBits();
     if (shouldChangeType(Ty, NewCmpTy)) {
-      if (CR.getActiveBits() <= NewCmpBW) {
-        ConstantRange SrcCR = CR.truncate(NewCmpBW);
-        CmpInst::Predicate EquivPred;
-        APInt EquivInt;
-        APInt EquivOffset;
-
-        SrcCR.getEquivalentICmp(EquivPred, EquivInt, EquivOffset);
-        return new ICmpInst(
-            EquivPred,
-            EquivOffset.isZero()
-                ? V
-                : Builder.CreateAdd(V, ConstantInt::get(NewCmpTy, EquivOffset)),
-            ConstantInt::get(NewCmpTy, EquivInt));
-      }
+      ConstantRange SrcCR = CR.truncate(NewCmpBW, TruncInst::NoUnsignedWrap);
+      CmpInst::Predicate EquivPred;
+      APInt EquivInt;
+      APInt EquivOffset;
+
+      SrcCR.getEquivalentICmp(EquivPred, EquivInt, EquivOffset);
+      return new ICmpInst(
+          EquivPred,
+          EquivOffset.isZero()
+              ? V
+              : Builder.CreateAdd(V, ConstantInt::get(NewCmpTy, EquivOffset)),
+          ConstantInt::get(NewCmpTy, EquivInt));
     }
   }
 
diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index cb428097f2ae1..2cfde5a2801fc 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -3209,13 +3209,11 @@ entry:
   ret i1 %cmp
 }
 
-; TODO: should be canonicalized to (x - 4) u> 2
 define i1 @zext_range_check_ugt(i8 %x) {
 ; CHECK-LABEL: @zext_range_check_ugt(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i32 [[CONV]], -7
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[TMP0]], -3
+; CHECK-NEXT:    [[TMP0:%.*]] = add i8 [[X:%.*]], -7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[TMP0]], -3
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
 entry:
@@ -3225,13 +3223,11 @@ entry:
   ret i1 %cmp
 }
 
-; TODO: should be canonicalized to (x - 4) u> 2
 define i1 @zext_range_check_ult_alter(i8 %x) {
 ; CHECK-LABEL: @zext_range_check_ult_alter(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], -7
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], -3
+; CHECK-NEXT:    [[TMP0:%.*]] = add i8 [[X:%.*]], -7
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[TMP0]], -3
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
 entry:
@@ -3289,9 +3285,7 @@ entry:
 define i1 @zext_range_check_ult_range_check_failure(i8 %x) {
 ; CHECK-LABEL: @zext_range_check_ult_range_check_failure(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CONV:%.*]] = zext i8 [[X:%.*]] to i32
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CONV]], -4
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ADD]], 253
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 3
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
 entry:

>From 11562a316e6f6338fff45d1e94896ebd16e54c0c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 23 Aug 2025 23:35:19 +0800
Subject: [PATCH 2/3] [InstCombine] Update test name. NFC.

---
 llvm/test/Transforms/InstCombine/icmp-add.ll | 26 ++++++++++----------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index 2cfde5a2801fc..8449c7c5ea935 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -3237,6 +3237,19 @@ entry:
   ret i1 %cmp
 }
 
+define i1 @zext_range_check_ult_alter2(i8 %x) {
+; CHECK-LABEL: @zext_range_check_ult_alter2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 3
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+entry:
+  %conv = zext i8 %x to i32
+  %add = add i32 %conv, -4
+  %cmp = icmp ult i32 %add, 253
+  ret i1 %cmp
+}
+
 define i1 @zext_range_check_mergable(i8 %x) {
 ; CHECK-LABEL: @zext_range_check_mergable(
 ; CHECK-NEXT:    [[COND:%.*]] = icmp slt i8 [[X:%.*]], 7
@@ -3282,19 +3295,6 @@ entry:
   ret i1 %cmp
 }
 
-define i1 @zext_range_check_ult_range_check_failure(i8 %x) {
-; CHECK-LABEL: @zext_range_check_ult_range_check_failure(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[X:%.*]], 3
-; CHECK-NEXT:    ret i1 [[CMP]]
-;
-entry:
-  %conv = zext i8 %x to i32
-  %add = add i32 %conv, -4
-  %cmp = icmp ult i32 %add, 253
-  ret i1 %cmp
-}
-
 ; PR 152851
 
 define i1 @val_is_aligend_const_pow2(i32 %num) {

>From c6bfc34d96f8f07a55069f1cc7bfb58a70392620 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 24 Aug 2025 13:19:13 +0800
Subject: [PATCH 3/3] [ConstantRange] Update comments. NFC.

---
 llvm/include/llvm/IR/ConstantRange.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/include/llvm/IR/ConstantRange.h b/llvm/include/llvm/IR/ConstantRange.h
index 4b2fda364fdf4..f4d4f1f555fa4 100644
--- a/llvm/include/llvm/IR/ConstantRange.h
+++ b/llvm/include/llvm/IR/ConstantRange.h
@@ -381,6 +381,7 @@ class [[nodiscard]] ConstantRange {
   /// strictly smaller than the current type.  The returned range will
   /// correspond to the possible range of values if the source range had been
   /// truncated to the specified type with wrap type \p NoWrapKind.
+  /// Note that the result of trunc nuw is exact.
   LLVM_ABI ConstantRange truncate(uint32_t BitWidth,
                                   unsigned NoWrapKind = 0) const;
 



More information about the llvm-commits mailing list