Skip to content

Conversation

@lukel97
Copy link
Contributor

@lukel97 lukel97 commented Dec 1, 2025

From the review in #169527 (comment), there are some users where we want to extend or truncate a ConstantRange only if it's not already the destination bitwidth. Previously this asserted, so this PR relaxes it to just be a no-op, similar to IRBuilder::createZExt and friends.

From the review in llvm#169527 (comment), there are some users where we want to extend or truncate a ConstantRange only if it's not already the destination bitwidth. Previously this asserted, so this PR relaxes it to just be a no-op, similar to IRBuilder::createZExt and friends.
@llvmbot
Copy link
Member

llvmbot commented Dec 1, 2025

@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-function-specialization

Author: Luke Lau (lukel97)

Changes

From the review in #169527 (comment), there are some users where we want to extend or truncate a ConstantRange only if it's not already the destination bitwidth. Previously this asserted, so this PR relaxes it to just be a no-op, similar to IRBuilder::createZExt and friends.


Full diff: https://github.com/llvm/llvm-project/pull/170102.diff

3 Files Affected:

  • (modified) llvm/lib/IR/ConstantRange.cpp (+6)
  • (modified) llvm/lib/Transforms/Utils/SCCPSolver.cpp (+3-3)
  • (modified) llvm/unittests/IR/ConstantRangeTest.cpp (+9)
diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp
index b454c9a4cd3ae..9beaee60d0bc1 100644
--- a/llvm/lib/IR/ConstantRange.cpp
+++ b/llvm/lib/IR/ConstantRange.cpp
@@ -841,6 +841,8 @@ ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const {
   if (isEmptySet()) return getEmpty(DstTySize);
 
   unsigned SrcTySize = getBitWidth();
+  if (DstTySize == SrcTySize)
+    return *this;
   assert(SrcTySize < DstTySize && "Not a value extension");
   if (isFullSet() || isUpperWrapped()) {
     // Change into [0, 1 << src bit width)
@@ -858,6 +860,8 @@ ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const {
   if (isEmptySet()) return getEmpty(DstTySize);
 
   unsigned SrcTySize = getBitWidth();
+  if (DstTySize == SrcTySize)
+    return *this;
   assert(SrcTySize < DstTySize && "Not a value extension");
 
   // special case: [X, INT_MIN) -- not really wrapping around
@@ -874,6 +878,8 @@ ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const {
 
 ConstantRange ConstantRange::truncate(uint32_t DstTySize,
                                       unsigned NoWrapKind) const {
+  if (DstTySize == getBitWidth())
+    return *this;
   assert(getBitWidth() > DstTySize && "Not a value truncation");
   if (isEmptySet())
     return getEmpty(DstTySize);
diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
index 951bf1ca62fc2..021bf0618754a 100644
--- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp
+++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp
@@ -2109,10 +2109,10 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {
 
       ConstantRange Count = getValueState(CountArg)
                                 .asConstantRange(CountArg->getType(), false)
-                                .zextOrTrunc(BitWidth);
+                                .zeroExtend(BitWidth);
       ConstantRange MaxLanes = getValueState(VF)
                                    .asConstantRange(VF->getType(), false)
-                                   .zextOrTrunc(BitWidth);
+                                   .zeroExtend(BitWidth);
       if (Scalable)
         MaxLanes =
             MaxLanes.multiply(getVScaleRange(II->getFunction(), BitWidth));
@@ -2126,7 +2126,7 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) {
       if (Count.icmp(CmpInst::ICMP_ULE, MaxLanes))
         Result = Count;
 
-      Result = Result.zextOrTrunc(II->getType()->getScalarSizeInBits());
+      Result = Result.truncate(II->getType()->getScalarSizeInBits());
       return (void)mergeInValue(ValueState[II], II,
                                 ValueLatticeElement::getRange(Result));
     }
diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp
index 53d581c8db7c9..13712a76d3edf 100644
--- a/llvm/unittests/IR/ConstantRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -449,6 +449,9 @@ TEST_F(ConstantRangeTest, Trunc) {
   // trunc([7, 1), 3->2) = [3, 1)
   ConstantRange SevenOne(APInt(3, 7), APInt(3, 1));
   EXPECT_EQ(SevenOne.truncate(2), ConstantRange(APInt(2, 3), APInt(2, 1)));
+
+  ConstantRange Nop = Full.truncate(Full.getBitWidth());
+  EXPECT_EQ(Full, Nop);
 }
 
 TEST_F(ConstantRangeTest, TruncNuw) {
@@ -527,6 +530,9 @@ TEST_F(ConstantRangeTest, ZExt) {
   // zext([5, 0), 3->7) = [5, 8)
   ConstantRange FiveZero(APInt(3, 5), APInt(3, 0));
   EXPECT_EQ(FiveZero.zeroExtend(7), ConstantRange(APInt(7, 5), APInt(7, 8)));
+
+  ConstantRange Nop = Full.zeroExtend(Full.getBitWidth());
+  EXPECT_EQ(Full, Nop);
 }
 
 TEST_F(ConstantRangeTest, SExt) {
@@ -550,6 +556,9 @@ TEST_F(ConstantRangeTest, SExt) {
 
   EXPECT_EQ(ConstantRange(APInt(16, 0x0200), APInt(16, 0x8000)).signExtend(19),
             ConstantRange(APInt(19, 0x0200), APInt(19, 0x8000)));
+
+  ConstantRange Nop = Full.signExtend(Full.getBitWidth());
+  EXPECT_EQ(Full, Nop);
 }
 
 TEST_F(ConstantRangeTest, IntersectWith) {

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We changed APInt to allow this some time ago, makes sense to also do this in ConstantRange.

@lukel97 lukel97 merged commit d0df51b into llvm:main Dec 1, 2025
13 of 14 checks passed
aahrun pushed a commit to aahrun/llvm-project that referenced this pull request Dec 1, 2025
From the review in
llvm#169527 (comment),
there are some users where we want to extend or truncate a ConstantRange
only if it's not already the destination bitwidth. Previously this
asserted, so this PR relaxes it to just be a no-op, similar to
IRBuilder::createZExt and friends.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants