[llvm] [DAG] Define computeConstantRange for VSCALE folding (PR #176027)

Neil Phan via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 4 07:14:18 PST 2026


https://github.com/neil-phan updated https://github.com/llvm/llvm-project/pull/176027

>From b62d1615d38bf57c4ca0e0633bbdfedf2a398321 Mon Sep 17 00:00:00 2001
From: neil-phan <hello at neil.place>
Date: Wed, 14 Jan 2026 15:13:58 -0500
Subject: [PATCH 1/9] [SelectionDAG] Define computeConstantRange for VSCALE
 folding

---
 llvm/include/llvm/CodeGen/SelectionDAG.h      | 10 +++
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 36 ++++++++
 .../CodeGen/AArch64/vscale-constant-range.ll  | 86 +++++++++++++++++++
 3 files changed, 132 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/vscale-constant-range.ll

diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 604319095e74f..821dcdaefad62 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2126,6 +2126,16 @@ class SelectionDAG {
   LLVM_ABI KnownBits computeKnownBits(SDValue Op, const APInt &DemandedElts,
                                       unsigned Depth = 0) const;
 
+  /// Determine the possible constant range of an integer or vector of integers.
+  LLVM_ABI ConstantRange computeConstantRange(SDValue Op,
+                                              const APInt &DemandedElts,
+                                              unsigned Depth = 0) const;
+
+  /// Combine constant ranges from computeConstantRange() and
+  /// computeKnownBits().
+  LLVM_ABI ConstantRange computeConstantRangeIncludingKnownBits(
+      SDValue Op, const APInt &DemandedElts, unsigned Depth = 0) const;
+
   /// Used to represent the possible overflow behavior of an operation.
   /// Never: the operation cannot overflow.
   /// Always: the operation will always overflow.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index c8a4dc6e67908..b0ea8e9eed7a8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4563,6 +4563,42 @@ SelectionDAG::computeOverflowForSignedMul(SDValue N0, SDValue N1) const {
   return OFK_Sometime;
 }
 
+ConstantRange SelectionDAG::computeConstantRange(SDValue Op,
+                                                 const APInt &DemandedElts,
+                                                 unsigned Depth) const {
+  EVT VT = Op.getValueType();
+  unsigned BitWidth = VT.getScalarSizeInBits();
+
+  if (Depth >= MaxRecursionDepth)
+    return ConstantRange::getFull(BitWidth);
+
+  if (ConstantSDNode *C = isConstOrConstSplat(Op, DemandedElts))
+    return ConstantRange(C->getAPIntValue());
+
+  unsigned Opcode = Op.getOpcode();
+  switch (Opcode) {
+  case ISD::VSCALE: {
+    const Function &F = getMachineFunction().getFunction();
+    const APInt &Multiplier = Op.getConstantOperandAPInt(0);
+    return getVScaleRange(&F, BitWidth).multiply(Multiplier);
+  }
+  default:
+    break;
+  }
+
+  return ConstantRange::getFull(BitWidth);
+}
+
+ConstantRange SelectionDAG::computeConstantRangeIncludingKnownBits(
+    SDValue Op, const APInt &DemandedElts, unsigned Depth) const {
+  ConstantRange CR = computeConstantRange(Op, DemandedElts, Depth);
+  if (!CR.isFullSet())
+    return CR;
+
+  KnownBits Known = computeKnownBits(Op, DemandedElts, Depth);
+  return ConstantRange::fromKnownBits(Known, false);
+}
+
 bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth) const {
   if (Depth >= MaxRecursionDepth)
     return false; // Limit search depth.
diff --git a/llvm/test/CodeGen/AArch64/vscale-constant-range.ll b/llvm/test/CodeGen/AArch64/vscale-constant-range.ll
new file mode 100644
index 0000000000000..c5227066a7a69
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/vscale-constant-range.ll
@@ -0,0 +1,86 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=aarch64 -mattr=+sve -verify-machineinstrs < %s | FileCheck %s
+
+declare i64 @llvm.vscale.i64()
+
+define i64 @vscale_bounded_range_sub(i64 %x) vscale_range(1, 16) {
+; CHECK-LABEL: vscale_bounded_range_sub:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    rdvl x8, #1
+; CHECK-NEXT:    lsr x8, x8, #4
+; CHECK-NEXT:    sub x0, x8, #1
+; CHECK-NEXT:    ret
+  %vscale = call i64 @llvm.vscale.i64()
+  %sub = sub i64 %vscale, 1
+  ret i64 %sub
+}
+
+define i64 @vscale_exact_value() vscale_range(2, 2) {
+; CHECK-LABEL: vscale_exact_value:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov w0, #2 // =0x2
+; CHECK-NEXT:    ret
+  %vscale = call i64 @llvm.vscale.i64()
+  ret i64 %vscale
+}
+
+define i64 @vscale_mul_bounded(i64 %x) vscale_range(1, 4) {
+; CHECK-LABEL: vscale_mul_bounded:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    cntw x0
+; CHECK-NEXT:    ret
+  %vscale = call i64 @llvm.vscale.i64()
+  %mul = mul i64 %vscale, 4
+  ret i64 %mul
+}
+
+define i64 @vscale_and_mask(i64 %x) vscale_range(1, 4) {
+; CHECK-LABEL: vscale_and_mask:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    rdvl x8, #1
+; CHECK-NEXT:    lsr x0, x8, #4
+; CHECK-NEXT:    ret
+  %vscale = call i64 @llvm.vscale.i64()
+  %masked = and i64 %vscale, 15
+  ret i64 %masked
+}
+
+define i1 @vscale_compare_bounded_true() vscale_range(1, 4) {
+; CHECK-LABEL: vscale_compare_bounded_true:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    rdvl x8, #1
+; CHECK-NEXT:    lsr x8, x8, #4
+; CHECK-NEXT:    cmp x8, #100
+; CHECK-NEXT:    cset w0, lo
+; CHECK-NEXT:    ret
+  %vscale = call i64 @llvm.vscale.i64()
+  %cmp = icmp ult i64 %vscale, 100
+  ret i1 %cmp
+}
+
+define i1 @vscale_or_const_range(i64 %x) vscale_range(1, 4) {
+; CHECK-LABEL: vscale_or_const_range:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    rdvl x8, #1
+; CHECK-NEXT:    lsr x8, x8, #4
+; CHECK-NEXT:    orr x8, x8, #0x8
+; CHECK-NEXT:    cmp x8, #4
+; CHECK-NEXT:    cset w0, hi
+; CHECK-NEXT:    ret
+  %vscale = call i64 @llvm.vscale.i64()
+  %or = or i64 %vscale, 8
+  %cmp = icmp ugt i64 %or, 4
+  ret i1 %cmp
+}
+
+define i1 @vscale_shl_known_bits(i64 %x) vscale_range(1, 4) {
+; CHECK-LABEL: vscale_shl_known_bits:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    mov w0, #1 // =0x1
+; CHECK-NEXT:    ret
+  %vscale = call i64 @llvm.vscale.i64()
+  %shl = shl i64 %vscale, 2
+  %and = and i64 %shl, 3
+  %cmp = icmp eq i64 %and, 0
+  ret i1 %cmp
+}

>From fc05477562d7cf2f938e7e105283139b26f1c9cf Mon Sep 17 00:00:00 2001
From: neil-phan <hello at neil.place>
Date: Thu, 15 Jan 2026 08:30:29 -0500
Subject: [PATCH 2/9] Add isSigned arg and intersection

---
 llvm/include/llvm/CodeGen/SelectionDAG.h       |  3 ++-
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 13 +++++++------
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 821dcdaefad62..a669e51a4678f 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2134,7 +2134,8 @@ class SelectionDAG {
   /// Combine constant ranges from computeConstantRange() and
   /// computeKnownBits().
   LLVM_ABI ConstantRange computeConstantRangeIncludingKnownBits(
-      SDValue Op, const APInt &DemandedElts, unsigned Depth = 0) const;
+      SDValue Op, const APInt &DemandedElts, bool ForSigned,
+      unsigned Depth = 0) const;
 
   /// Used to represent the possible overflow behavior of an operation.
   /// Never: the operation cannot overflow.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index b0ea8e9eed7a8..130a9dc5e9776 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4590,13 +4590,14 @@ ConstantRange SelectionDAG::computeConstantRange(SDValue Op,
 }
 
 ConstantRange SelectionDAG::computeConstantRangeIncludingKnownBits(
-    SDValue Op, const APInt &DemandedElts, unsigned Depth) const {
-  ConstantRange CR = computeConstantRange(Op, DemandedElts, Depth);
-  if (!CR.isFullSet())
-    return CR;
-
+    SDValue Op, const APInt &DemandedElts, bool ForSigned,
+    unsigned Depth) const {
   KnownBits Known = computeKnownBits(Op, DemandedElts, Depth);
-  return ConstantRange::fromKnownBits(Known, false);
+  ConstantRange CR1 = ConstantRange::fromKnownBits(Known, ForSigned);
+  ConstantRange CR2 = computeConstantRange(Op, DemandedElts, Depth);
+  ConstantRange::PreferredRangeType RangeType =
+      ForSigned ? ConstantRange::Signed : ConstantRange::Unsigned;
+  return CR1.intersectWith(CR2, RangeType);
 }
 
 bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth) const {

>From 6a1d556a5ef34b485da83d74bb5f927d359e38fa Mon Sep 17 00:00:00 2001
From: neil-phan <hello at neil.place>
Date: Thu, 15 Jan 2026 08:50:31 -0500
Subject: [PATCH 3/9] Clean up test cases

---
 .../CodeGen/AArch64/vscale-constant-range.ll  | 40 -------------------
 1 file changed, 40 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/vscale-constant-range.ll b/llvm/test/CodeGen/AArch64/vscale-constant-range.ll
index c5227066a7a69..88a911a901ccb 100644
--- a/llvm/test/CodeGen/AArch64/vscale-constant-range.ll
+++ b/llvm/test/CodeGen/AArch64/vscale-constant-range.ll
@@ -3,18 +3,6 @@
 
 declare i64 @llvm.vscale.i64()
 
-define i64 @vscale_bounded_range_sub(i64 %x) vscale_range(1, 16) {
-; CHECK-LABEL: vscale_bounded_range_sub:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    rdvl x8, #1
-; CHECK-NEXT:    lsr x8, x8, #4
-; CHECK-NEXT:    sub x0, x8, #1
-; CHECK-NEXT:    ret
-  %vscale = call i64 @llvm.vscale.i64()
-  %sub = sub i64 %vscale, 1
-  ret i64 %sub
-}
-
 define i64 @vscale_exact_value() vscale_range(2, 2) {
 ; CHECK-LABEL: vscale_exact_value:
 ; CHECK:       // %bb.0:
@@ -45,34 +33,6 @@ define i64 @vscale_and_mask(i64 %x) vscale_range(1, 4) {
   ret i64 %masked
 }
 
-define i1 @vscale_compare_bounded_true() vscale_range(1, 4) {
-; CHECK-LABEL: vscale_compare_bounded_true:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    rdvl x8, #1
-; CHECK-NEXT:    lsr x8, x8, #4
-; CHECK-NEXT:    cmp x8, #100
-; CHECK-NEXT:    cset w0, lo
-; CHECK-NEXT:    ret
-  %vscale = call i64 @llvm.vscale.i64()
-  %cmp = icmp ult i64 %vscale, 100
-  ret i1 %cmp
-}
-
-define i1 @vscale_or_const_range(i64 %x) vscale_range(1, 4) {
-; CHECK-LABEL: vscale_or_const_range:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    rdvl x8, #1
-; CHECK-NEXT:    lsr x8, x8, #4
-; CHECK-NEXT:    orr x8, x8, #0x8
-; CHECK-NEXT:    cmp x8, #4
-; CHECK-NEXT:    cset w0, hi
-; CHECK-NEXT:    ret
-  %vscale = call i64 @llvm.vscale.i64()
-  %or = or i64 %vscale, 8
-  %cmp = icmp ugt i64 %or, 4
-  ret i1 %cmp
-}
-
 define i1 @vscale_shl_known_bits(i64 %x) vscale_range(1, 4) {
 ; CHECK-LABEL: vscale_shl_known_bits:
 ; CHECK:       // %bb.0:

>From bffbf596b039083742230717fdbbbf7092128c2f Mon Sep 17 00:00:00 2001
From: neil-phan <hello at neil.place>
Date: Thu, 15 Jan 2026 12:26:38 -0500
Subject: [PATCH 4/9] Replace overflow mul/sub with constant range impl

---
 llvm/include/llvm/CodeGen/SelectionDAG.h      |  3 +++
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 25 +++++++++++++------
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index a669e51a4678f..1db58c5ae4f97 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2131,6 +2131,9 @@ class SelectionDAG {
                                               const APInt &DemandedElts,
                                               unsigned Depth = 0) const;
 
+  LLVM_ABI ConstantRange computeConstantRangeIncludingKnownBits(
+      SDValue Op, bool ForSigned, unsigned Depth = 0) const;
+
   /// Combine constant ranges from computeConstantRange() and
   /// computeKnownBits().
   LLVM_ABI ConstantRange computeConstantRangeIncludingKnownBits(
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 130a9dc5e9776..34dd0b637fd90 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4513,10 +4513,8 @@ SelectionDAG::computeOverflowForUnsignedSub(SDValue N0, SDValue N1) const {
   if (isNullConstant(N1))
     return OFK_Never;
 
-  KnownBits N0Known = computeKnownBits(N0);
-  KnownBits N1Known = computeKnownBits(N1);
-  ConstantRange N0Range = ConstantRange::fromKnownBits(N0Known, false);
-  ConstantRange N1Range = ConstantRange::fromKnownBits(N1Known, false);
+  ConstantRange N0Range = computeConstantRangeIncludingKnownBits(N0, false);
+  ConstantRange N1Range = computeConstantRangeIncludingKnownBits(N1, false);
   return mapOverflowResult(N0Range.unsignedSubMayOverflow(N1Range));
 }
 
@@ -4526,10 +4524,8 @@ SelectionDAG::computeOverflowForUnsignedMul(SDValue N0, SDValue N1) const {
   if (isNullConstant(N1) || isOneConstant(N1))
     return OFK_Never;
 
-  KnownBits N0Known = computeKnownBits(N0);
-  KnownBits N1Known = computeKnownBits(N1);
-  ConstantRange N0Range = ConstantRange::fromKnownBits(N0Known, false);
-  ConstantRange N1Range = ConstantRange::fromKnownBits(N1Known, false);
+  ConstantRange N0Range = computeConstantRangeIncludingKnownBits(N0, false);
+  ConstantRange N1Range = computeConstantRangeIncludingKnownBits(N1, false);
   return mapOverflowResult(N0Range.unsignedMulMayOverflow(N1Range));
 }
 
@@ -4589,6 +4585,19 @@ ConstantRange SelectionDAG::computeConstantRange(SDValue Op,
   return ConstantRange::getFull(BitWidth);
 }
 
+ConstantRange
+SelectionDAG::computeConstantRangeIncludingKnownBits(SDValue Op, bool ForSigned,
+                                                     unsigned Depth) const {
+  EVT VT = Op.getValueType();
+
+  APInt DemandedElts = VT.isFixedLengthVector()
+                           ? APInt::getAllOnes(VT.getVectorNumElements())
+                           : APInt(1, 1);
+
+  return computeConstantRangeIncludingKnownBits(Op, DemandedElts, ForSigned,
+                                                Depth);
+}
+
 ConstantRange SelectionDAG::computeConstantRangeIncludingKnownBits(
     SDValue Op, const APInt &DemandedElts, bool ForSigned,
     unsigned Depth) const {

>From b26b5004338c701cab219e3da05d11aed4654885 Mon Sep 17 00:00:00 2001
From: Neil Phan <hello at neil.place>
Date: Tue, 3 Feb 2026 11:07:13 -0500
Subject: [PATCH 5/9] Add styling for ForSigned param

Co-authored-by: Simon Pilgrim <git at redking.me.uk>
---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 34dd0b637fd90..8faa8fd82d6d2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4514,7 +4514,8 @@ SelectionDAG::computeOverflowForUnsignedSub(SDValue N0, SDValue N1) const {
     return OFK_Never;
 
   ConstantRange N0Range = computeConstantRangeIncludingKnownBits(N0, false);
-  ConstantRange N1Range = computeConstantRangeIncludingKnownBits(N1, false);
+  ConstantRange N0Range = computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
+  ConstantRange N1Range = computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
   return mapOverflowResult(N0Range.unsignedSubMayOverflow(N1Range));
 }
 

>From 75f52828790ae411e58c66b2df8f4dff18227dab Mon Sep 17 00:00:00 2001
From: neil <hello at neil.place>
Date: Tue, 3 Feb 2026 11:13:48 -0500
Subject: [PATCH 6/9] Add comments and remove leftover code

---
 llvm/include/llvm/CodeGen/SelectionDAG.h       | 5 ++++-
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 1 -
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 1db58c5ae4f97..032da182affdb 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2131,11 +2131,14 @@ class SelectionDAG {
                                               const APInt &DemandedElts,
                                               unsigned Depth = 0) const;
 
+  /// Combine constant ranges from computeConstantRange() and
+  /// computeKnownBits().
   LLVM_ABI ConstantRange computeConstantRangeIncludingKnownBits(
       SDValue Op, bool ForSigned, unsigned Depth = 0) const;
 
   /// Combine constant ranges from computeConstantRange() and
-  /// computeKnownBits().
+  /// computeKnownBits(). The DemandedElts argument allows us to only collect
+  /// the known ranges that are shared by the requested vector elements.
   LLVM_ABI ConstantRange computeConstantRangeIncludingKnownBits(
       SDValue Op, const APInt &DemandedElts, bool ForSigned,
       unsigned Depth = 0) const;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 8faa8fd82d6d2..46bb2a5167f44 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4513,7 +4513,6 @@ SelectionDAG::computeOverflowForUnsignedSub(SDValue N0, SDValue N1) const {
   if (isNullConstant(N1))
     return OFK_Never;
 
-  ConstantRange N0Range = computeConstantRangeIncludingKnownBits(N0, false);
   ConstantRange N0Range = computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
   ConstantRange N1Range = computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
   return mapOverflowResult(N0Range.unsignedSubMayOverflow(N1Range));

>From 9d2c851e88669de198795daf5872c843209ae320 Mon Sep 17 00:00:00 2001
From: neil <hello at neil.place>
Date: Tue, 3 Feb 2026 11:17:56 -0500
Subject: [PATCH 7/9] Add missed formatting

---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 46bb2a5167f44..3f775ec2eb0d0 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4513,8 +4513,10 @@ SelectionDAG::computeOverflowForUnsignedSub(SDValue N0, SDValue N1) const {
   if (isNullConstant(N1))
     return OFK_Never;
 
-  ConstantRange N0Range = computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
-  ConstantRange N1Range = computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
+  ConstantRange N0Range =
+      computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
+  ConstantRange N1Range =
+      computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
   return mapOverflowResult(N0Range.unsignedSubMayOverflow(N1Range));
 }
 

>From ad451dbbcb8111be476af427e92bc6ba27e6590d Mon Sep 17 00:00:00 2001
From: neil <hello at neil.place>
Date: Tue, 3 Feb 2026 16:51:46 -0500
Subject: [PATCH 8/9] Fix typo, add overload, and update DAGCombiner

---
 llvm/include/llvm/CodeGen/SelectionDAG.h       |  6 ++++++
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp  |  5 +----
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 11 ++++++++++-
 3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index ea39c77c82b88..ec656ef8044b3 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2166,6 +2166,12 @@ class SelectionDAG {
                                       unsigned Depth = 0) const;
 
   /// Determine the possible constant range of an integer or vector of integers.
+  LLVM_ABI ConstantRange computeConstantRange(SDValue Op,
+                                              unsigned Depth = 0) const;
+
+  /// Determine the possible constant range of an integer or vector of integers.
+  /// The DemandedElts argument allows us to only collect the known ranges that
+  /// are shared by the requested vector elements.
   LLVM_ABI ConstantRange computeConstantRange(SDValue Op,
                                               const APInt &DemandedElts,
                                               unsigned Depth = 0) const;
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index df69f0870d27a..c9cb82be5407d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6322,13 +6322,10 @@ SDValue DAGCombiner::visitIMINMAX(SDNode *N) {
   }
 
   // If we know the range of vscale, see if we can fold it given a constant.
-  // TODO: Generalize this to other nodes by adding computeConstantRange
   if (N0.getOpcode() == ISD::VSCALE) {
     if (auto *C1 = dyn_cast<ConstantSDNode>(N1)) {
       const Function &F = DAG.getMachineFunction().getFunction();
-      ConstantRange Range =
-          getVScaleRange(&F, VT.getScalarSizeInBits())
-              .multiply(ConstantRange(N0.getConstantOperandAPInt(0)));
+      ConstantRange Range = DAG.computeConstantRange(N0, 0);
 
       const APInt &C1V = C1->getAPIntValue();
       if ((Opcode == ISD::UMAX && Range.getUnsignedMax().ule(C1V)) ||
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 5abb4b73887e3..091bbdf063c78 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4582,7 +4582,7 @@ SelectionDAG::computeOverflowForUnsignedSub(SDValue N0, SDValue N1) const {
     return OFK_Never;
 
   ConstantRange N0Range =
-      computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
+      computeConstantRangeIncludingKnownBits(N0, /*ForSigned=*/false);
   ConstantRange N1Range =
       computeConstantRangeIncludingKnownBits(N1, /*ForSigned=*/false);
   return mapOverflowResult(N0Range.unsignedSubMayOverflow(N1Range));
@@ -4629,6 +4629,15 @@ SelectionDAG::computeOverflowForSignedMul(SDValue N0, SDValue N1) const {
   return OFK_Sometime;
 }
 
+ConstantRange SelectionDAG::computeConstantRange(SDValue Op,
+                                                 unsigned Depth) const {
+  EVT VT = Op.getValueType();
+  APInt DemandedElts = VT.isFixedLengthVector()
+                           ? APInt::getAllOnes(VT.getVectorNumElements())
+                           : APInt(1, 1);
+  return computeConstantRange(Op, DemandedElts, Depth);
+}
+
 ConstantRange SelectionDAG::computeConstantRange(SDValue Op,
                                                  const APInt &DemandedElts,
                                                  unsigned Depth) const {

>From 13d34cdcf84a9e120417923511f0008e42fb04fb Mon Sep 17 00:00:00 2001
From: neil <hello at neil.place>
Date: Wed, 4 Feb 2026 10:14:23 -0500
Subject: [PATCH 9/9] Remove unused var

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c9cb82be5407d..49fa99019efb9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6324,7 +6324,6 @@ SDValue DAGCombiner::visitIMINMAX(SDNode *N) {
   // If we know the range of vscale, see if we can fold it given a constant.
   if (N0.getOpcode() == ISD::VSCALE) {
     if (auto *C1 = dyn_cast<ConstantSDNode>(N1)) {
-      const Function &F = DAG.getMachineFunction().getFunction();
       ConstantRange Range = DAG.computeConstantRange(N0, 0);
 
       const APInt &C1V = C1->getAPIntValue();



More information about the llvm-commits mailing list