[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