[llvm] [ValueTracking] If overlap in unsigned and signed range is contiguous, return it (PR #144267)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 15 14:56:58 PDT 2025


github-actions[bot] wrote:

<!--LLVM CODE FORMAT COMMENT: {clang-format}-->


:warning: C/C++ code formatter, clang-format found issues in your code. :warning:

<details>
<summary>
You can test this locally with the following command:
</summary>

``````````bash
git-clang-format --diff HEAD~1 HEAD --extensions cpp -- llvm/lib/Analysis/ValueTracking.cpp
``````````

</details>

<details>
<summary>
View the diff from clang-format here.
</summary>

``````````diff
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index fd75cb2a7..e5cbc6576 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -9581,150 +9581,158 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower,
   const APInt *C;
   switch (BO.getOpcode()) {
   case Instruction::Sub:
-if (match(BO.getOperand(0), m_APInt(C))) {
-    bool HasNSW = IIQ.hasNoSignedWrap(&BO);
-    bool HasNUW = IIQ.hasNoUnsignedWrap(&BO);
-
-    // Build the two candidate ranges as [lo..hi]:
-    //   unsignedRange:  NUW ⇒ [0 .. C]
-    //   signedRange:    NSW ⇒ either [SINT_MIN .. -C - SINT_MIN] or [C - SINT_MAX .. SINT_MAX]
-    auto makeUnsignedRange = [&]() {
-      return std::pair<APInt,APInt>(APInt::getZero(Width), *C);
-    };
-    auto makeSignedRange = [&]() {
-      if (C->isNegative()) {
-        // sub nsw -C, x
-        APInt lo = APInt::getSignedMinValue(Width);
-        APInt hi = *C - APInt::getSignedMinValue(Width);
-        return std::pair<APInt,APInt>(lo, hi);
-      } else {
-        // sub nsw C, x
-        APInt lo = *C - APInt::getSignedMaxValue(Width);
-        APInt hi = APInt::getSignedMaxValue(Width);
-        return std::pair<APInt,APInt>(lo, hi);
-      }
-    };
+    if (match(BO.getOperand(0), m_APInt(C))) {
+      bool HasNSW = IIQ.hasNoSignedWrap(&BO);
+      bool HasNUW = IIQ.hasNoUnsignedWrap(&BO);
+
+      // Build the two candidate ranges as [lo..hi]:
+      //   unsignedRange:  NUW ⇒ [0 .. C]
+      //   signedRange:    NSW ⇒ either [SINT_MIN .. -C - SINT_MIN] or [C -
+      //   SINT_MAX .. SINT_MAX]
+      auto makeUnsignedRange = [&]() {
+        return std::pair<APInt, APInt>(APInt::getZero(Width), *C);
+      };
+      auto makeSignedRange = [&]() {
+        if (C->isNegative()) {
+          // sub nsw -C, x
+          APInt lo = APInt::getSignedMinValue(Width);
+          APInt hi = *C - APInt::getSignedMinValue(Width);
+          return std::pair<APInt, APInt>(lo, hi);
+        } else {
+          // sub nsw C, x
+          APInt lo = *C - APInt::getSignedMaxValue(Width);
+          APInt hi = APInt::getSignedMaxValue(Width);
+          return std::pair<APInt, APInt>(lo, hi);
+        }
+      };
 
-    // Split a (possibly wrapping) [lo..hi] into up to two non‑wrapping pieces:
-    auto splitPieces = [&](std::pair<APInt,APInt> rng,
-                           SmallVectorImpl<std::pair<APInt,APInt>>& pieces) {
-      APInt lo = rng.first, hi = rng.second;
-      if (lo.ugt(hi)) {
-        // wraps around 2^n
-        pieces.emplace_back(lo, APInt::getMaxValue(Width));  // [lo..2^n-1]
-        pieces.emplace_back(APInt::getZero(Width), hi);      // [0..hi]
-      } else {
-        pieces.emplace_back(lo, hi);
+      // Split a (possibly wrapping) [lo..hi] into up to two non‑wrapping
+      // pieces:
+      auto splitPieces = [&](std::pair<APInt, APInt> rng,
+                             SmallVectorImpl<std::pair<APInt, APInt>> &pieces) {
+        APInt lo = rng.first, hi = rng.second;
+        if (lo.ugt(hi)) {
+          // wraps around 2^n
+          pieces.emplace_back(lo, APInt::getMaxValue(Width)); // [lo..2^n-1]
+          pieces.emplace_back(APInt::getZero(Width), hi);     // [0..hi]
+        } else {
+          pieces.emplace_back(lo, hi);
+        }
+      };
+
+      SmallVector<std::pair<APInt, APInt>, 2> piecesU, piecesS;
+      if (HasNUW)
+        splitPieces(makeUnsignedRange(), piecesU);
+      if (HasNSW)
+        splitPieces(makeSignedRange(), piecesS);
+
+      // Intersect piecewise:
+      SmallVector<std::pair<APInt, APInt>, 2> inters;
+      for (auto &u : piecesU) {
+        for (auto &s : piecesS) {
+          APInt loI = u.first.ugt(s.first) ? u.first : s.first;
+          APInt hiI = u.second.ult(s.second) ? u.second : s.second;
+          if (loI.ule(hiI))
+            inters.emplace_back(loI, hiI);
+        }
       }
-    };
 
-    SmallVector<std::pair<APInt,APInt>,2> piecesU, piecesS;
-    if (HasNUW) splitPieces(makeUnsignedRange(), piecesU);
-    if (HasNSW) splitPieces(makeSignedRange(),   piecesS);
-
-    // Intersect piecewise:
-    SmallVector<std::pair<APInt,APInt>,2> inters;
-    for (auto &u : piecesU) {
-      for (auto &s : piecesS) {
-        APInt loI = u.first.ugt(s.first) ? u.first : s.first;
-        APInt hiI = u.second.ult(s.second) ? u.second : s.second;
-        if (loI.ule(hiI))
-          inters.emplace_back(loI, hiI);
+      if (inters.size() == 1) {
+        // Exactly one contiguous overlap → use it
+        Lower = inters[0].first;
+        Upper = inters[0].second;
+      } else if (HasNUW && !PreferSignedRange) {
+        // Fallback to plain NUW result [0..C]
+        Lower = APInt::getZero(Width);
+        Upper = *C;
+      } else if (HasNSW) {
+        // Fallback to plain NSW result
+        auto S = makeSignedRange();
+        Lower = S.first;
+        Upper = S.second;
       }
     }
+    break;
+  case Instruction::Add:
+    if (match(BO.getOperand(1), m_APInt(C)) && !C->isZero()) {
+      bool HasNSW = IIQ.hasNoSignedWrap(&BO);
+      bool HasNUW = IIQ.hasNoUnsignedWrap(&BO);
+
+      // If the caller prefers signed ranges when both wraps are forbidden:
+      if (PreferSignedRange && HasNSW && HasNUW)
+        HasNUW = false;
+
+      // Build the two candidate ranges as [lo..hi] in the unsigned 0..2^n-1
+      // world:
+      //  NUW: 'add nuw x, C' ⇒ [ C .. UINT_MAX ]
+      auto makeUnsignedRange = [&]() {
+        APInt lo = *C;
+        APInt hi = APInt::getMaxValue(Width);
+        return std::pair<APInt, APInt>(lo, hi);
+      };
 
-    if (inters.size() == 1) {
-      // Exactly one contiguous overlap → use it
-      Lower = inters[0].first;
-      Upper = inters[0].second;
-    } else if (HasNUW && !PreferSignedRange) {
-      // Fallback to plain NUW result [0..C]
-      Lower = APInt::getZero(Width);
-      Upper = *C;
-    } else if (HasNSW) {
-      // Fallback to plain NSW result
-      auto S = makeSignedRange();
-      Lower = S.first;
-      Upper = S.second;
-    }
-  }
-  break;
-case Instruction::Add:
-  if (match(BO.getOperand(1), m_APInt(C)) && !C->isZero()) {
-    bool HasNSW = IIQ.hasNoSignedWrap(&BO);
-    bool HasNUW = IIQ.hasNoUnsignedWrap(&BO);
-
-    // If the caller prefers signed ranges when both wraps are forbidden:
-    if (PreferSignedRange && HasNSW && HasNUW)
-      HasNUW = false;
-
-    // Build the two candidate ranges as [lo..hi] in the unsigned 0..2^n-1 world:
-    //  NUW: 'add nuw x, C' ⇒ [ C .. UINT_MAX ]
-    auto makeUnsignedRange = [&]() {
-      APInt lo = *C;
-      APInt hi = APInt::getMaxValue(Width);
-      return std::pair<APInt,APInt>(lo, hi);
-    };
+      //  NSW: 'add nsw x, C'
+      //    if C<0:  [ SINT_MIN .. SINT_MAX + C ]
+      //    else:    [ SINT_MIN + C .. SINT_MAX ]
+      auto makeSignedRange = [&]() {
+        if (C->isNegative()) {
+          APInt lo = APInt::getSignedMinValue(Width);
+          APInt hi = APInt::getSignedMaxValue(Width) + *C;
+          return std::pair<APInt, APInt>(lo, hi);
+        } else {
+          APInt lo = APInt::getSignedMinValue(Width) + *C;
+          APInt hi = APInt::getSignedMaxValue(Width);
+          return std::pair<APInt, APInt>(lo, hi);
+        }
+      };
 
-    //  NSW: 'add nsw x, C'
-    //    if C<0:  [ SINT_MIN .. SINT_MAX + C ]
-    //    else:    [ SINT_MIN + C .. SINT_MAX ]
-    auto makeSignedRange = [&]() {
-      if (C->isNegative()) {
-        APInt lo = APInt::getSignedMinValue(Width);
-        APInt hi = APInt::getSignedMaxValue(Width) + *C;
-        return std::pair<APInt,APInt>(lo, hi);
-      } else {
-        APInt lo = APInt::getSignedMinValue(Width) + *C;
-        APInt hi = APInt::getSignedMaxValue(Width);
-        return std::pair<APInt,APInt>(lo, hi);
-      }
-    };
+      // Split [lo..hi] into up to two non‑wrapping intervals:
+      auto splitPieces = [&](std::pair<APInt, APInt> rng,
+                             SmallVectorImpl<std::pair<APInt, APInt>> &dst) {
+        APInt lo = rng.first, hi = rng.second;
+        if (lo.ugt(hi)) {
+          // wraps around 2^n
+          dst.emplace_back(lo, APInt::getMaxValue(Width));
+          dst.emplace_back(APInt::getZero(Width), hi);
+        } else {
+          dst.emplace_back(lo, hi);
+        }
+      };
 
-    // Split [lo..hi] into up to two non‑wrapping intervals:
-    auto splitPieces = [&](std::pair<APInt,APInt> rng,
-                           SmallVectorImpl<std::pair<APInt,APInt>> &dst) {
-      APInt lo = rng.first, hi = rng.second;
-      if (lo.ugt(hi)) {
-        // wraps around 2^n
-        dst.emplace_back(lo, APInt::getMaxValue(Width));
-        dst.emplace_back(APInt::getZero(Width), hi);
-      } else {
-        dst.emplace_back(lo, hi);
+      SmallVector<std::pair<APInt, APInt>, 2> piecesU, piecesS;
+      if (HasNUW)
+        splitPieces(makeUnsignedRange(), piecesU);
+      if (HasNSW)
+        splitPieces(makeSignedRange(), piecesS);
+
+      // Intersect piecewise
+      SmallVector<std::pair<APInt, APInt>, 2> inters;
+      for (auto &u : piecesU) {
+        for (auto &s : piecesS) {
+          APInt loI = u.first.ugt(s.first) ? u.first : s.first;
+          APInt hiI = u.second.ult(s.second) ? u.second : s.second;
+          if (loI.ule(hiI))
+            inters.emplace_back(loI, hiI);
+        }
       }
-    };
 
-    SmallVector<std::pair<APInt,APInt>,2> piecesU, piecesS;
-    if (HasNUW) splitPieces(makeUnsignedRange(), piecesU);
-    if (HasNSW) splitPieces(makeSignedRange(),   piecesS);
-
-    // Intersect piecewise
-    SmallVector<std::pair<APInt,APInt>,2> inters;
-    for (auto &u : piecesU) {
-      for (auto &s : piecesS) {
-        APInt loI = u.first.ugt(s.first) ? u.first : s.first;
-        APInt hiI = u.second.ult(s.second) ? u.second : s.second;
-        if (loI.ule(hiI))
-          inters.emplace_back(loI, hiI);
+      if (inters.size() == 1) {
+        // Exactly one contiguous overlap ⇒ use it
+        Lower = inters[0].first;
+        Upper = inters[0].second +
+                1; // make Upper exclusive if you’re following [Lo..Hi)
+      } else if (HasNUW && !PreferSignedRange) {
+        // Fallback to plain NUW [C..UINT_MAX]
+        Lower = *C;
+        Upper = APInt::getMaxValue(Width) + 1;
+      } else if (HasNSW) {
+        // Fallback to plain NSW
+        auto S = makeSignedRange();
+        Lower = S.first;
+        Upper = S.second + 1;
       }
     }
-
-    if (inters.size() == 1) {
-      // Exactly one contiguous overlap ⇒ use it
-      Lower = inters[0].first;
-      Upper = inters[0].second + 1;  // make Upper exclusive if you’re following [Lo..Hi)
-    } else if (HasNUW && !PreferSignedRange) {
-      // Fallback to plain NUW [C..UINT_MAX]
-      Lower = *C;
-      Upper = APInt::getMaxValue(Width) + 1;
-    } else if (HasNSW) {
-      // Fallback to plain NSW
-      auto S = makeSignedRange();
-      Lower = S.first;
-      Upper = S.second + 1;
-    }
-  }
-  break;
+    break;
 
   case Instruction::And:
     if (match(BO.getOperand(1), m_APInt(C)))

``````````

</details>


https://github.com/llvm/llvm-project/pull/144267


More information about the llvm-commits mailing list