@@ -9581,63 +9581,150 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower,
9581
9581
const APInt *C;
9582
9582
switch (BO.getOpcode ()) {
9583
9583
case Instruction::Sub:
9584
- if (match (BO.getOperand (0 ), m_APInt (C))) {
9585
- bool HasNSW = IIQ.hasNoSignedWrap (&BO);
9586
- bool HasNUW = IIQ.hasNoUnsignedWrap (&BO);
9587
-
9588
- // If the caller expects a signed compare, then try to use a signed range.
9589
- // Otherwise if both no-wraps are set, use the unsigned range because it
9590
- // is never larger than the signed range. Example:
9591
- // "sub nuw nsw i8 -2, x" is unsigned [0, 254] vs. signed [-128, 126].
9592
- // "sub nuw nsw i8 2, x" is unsigned [0, 2] vs. signed [-125, 127].
9593
- if (PreferSignedRange && HasNSW && HasNUW)
9594
- HasNUW = false ;
9595
-
9596
- if (HasNUW) {
9597
- // 'sub nuw c, x' produces [0, C].
9598
- Upper = *C + 1 ;
9599
- } else if (HasNSW) {
9600
- if (C->isNegative ()) {
9601
- // 'sub nsw -C, x' produces [SINT_MIN, -C - SINT_MIN].
9602
- Lower = APInt::getSignedMinValue (Width);
9603
- Upper = *C - APInt::getSignedMaxValue (Width);
9604
- } else {
9605
- // Note that sub 0, INT_MIN is not NSW. It techically is a signed wrap
9606
- // 'sub nsw C, x' produces [C - SINT_MAX, SINT_MAX].
9607
- Lower = *C - APInt::getSignedMaxValue (Width);
9608
- Upper = APInt::getSignedMinValue (Width);
9609
- }
9584
+ if (match (BO.getOperand (0 ), m_APInt (C))) {
9585
+ bool HasNSW = IIQ.hasNoSignedWrap (&BO);
9586
+ bool HasNUW = IIQ.hasNoUnsignedWrap (&BO);
9587
+
9588
+ // Build the two candidate ranges as [lo..hi]:
9589
+ // unsignedRange: NUW ⇒ [0 .. C]
9590
+ // signedRange: NSW ⇒ either [SINT_MIN .. -C - SINT_MIN] or [C - SINT_MAX .. SINT_MAX]
9591
+ auto makeUnsignedRange = [&]() {
9592
+ return std::pair<APInt,APInt>(APInt::getZero (Width), *C);
9593
+ };
9594
+ auto makeSignedRange = [&]() {
9595
+ if (C->isNegative ()) {
9596
+ // sub nsw -C, x
9597
+ APInt lo = APInt::getSignedMinValue (Width);
9598
+ APInt hi = *C - APInt::getSignedMinValue (Width);
9599
+ return std::pair<APInt,APInt>(lo, hi);
9600
+ } else {
9601
+ // sub nsw C, x
9602
+ APInt lo = *C - APInt::getSignedMaxValue (Width);
9603
+ APInt hi = APInt::getSignedMaxValue (Width);
9604
+ return std::pair<APInt,APInt>(lo, hi);
9605
+ }
9606
+ };
9607
+
9608
+ // Split a (possibly wrapping) [lo..hi] into up to two non‑wrapping pieces:
9609
+ auto splitPieces = [&](std::pair<APInt,APInt> rng,
9610
+ SmallVectorImpl<std::pair<APInt,APInt>>& pieces) {
9611
+ APInt lo = rng.first , hi = rng.second ;
9612
+ if (lo.ugt (hi)) {
9613
+ // wraps around 2^n
9614
+ pieces.emplace_back (lo, APInt::getMaxValue (Width)); // [lo..2^n-1]
9615
+ pieces.emplace_back (APInt::getZero (Width), hi); // [0..hi]
9616
+ } else {
9617
+ pieces.emplace_back (lo, hi);
9618
+ }
9619
+ };
9620
+
9621
+ SmallVector<std::pair<APInt,APInt>,2 > piecesU, piecesS;
9622
+ if (HasNUW) splitPieces (makeUnsignedRange (), piecesU);
9623
+ if (HasNSW) splitPieces (makeSignedRange (), piecesS);
9624
+
9625
+ // Intersect piecewise:
9626
+ SmallVector<std::pair<APInt,APInt>,2 > inters;
9627
+ for (auto &u : piecesU) {
9628
+ for (auto &s : piecesS) {
9629
+ APInt loI = u.first .ugt (s.first ) ? u.first : s.first ;
9630
+ APInt hiI = u.second .ult (s.second ) ? u.second : s.second ;
9631
+ if (loI.ule (hiI))
9632
+ inters.emplace_back (loI, hiI);
9610
9633
}
9611
9634
}
9612
- break ;
9613
- case Instruction::Add:
9614
- if (match (BO.getOperand (1 ), m_APInt (C)) && !C->isZero ()) {
9615
- bool HasNSW = IIQ.hasNoSignedWrap (&BO);
9616
- bool HasNUW = IIQ.hasNoUnsignedWrap (&BO);
9617
-
9618
- // If the caller expects a signed compare, then try to use a signed
9619
- // range. Otherwise if both no-wraps are set, use the unsigned range
9620
- // because it is never larger than the signed range. Example: "add nuw
9621
- // nsw i8 X, -2" is unsigned [254,255] vs. signed [-128, 125].
9622
- if (PreferSignedRange && HasNSW && HasNUW)
9623
- HasNUW = false ;
9624
-
9625
- if (HasNUW) {
9626
- // 'add nuw x, C' produces [C, UINT_MAX].
9627
- Lower = *C;
9628
- } else if (HasNSW) {
9629
- if (C->isNegative ()) {
9630
- // 'add nsw x, -C' produces [SINT_MIN, SINT_MAX - C].
9631
- Lower = APInt::getSignedMinValue (Width);
9632
- Upper = APInt::getSignedMaxValue (Width) + *C + 1 ;
9633
- } else {
9634
- // 'add nsw x, +C' produces [SINT_MIN + C, SINT_MAX].
9635
- Lower = APInt::getSignedMinValue (Width) + *C;
9636
- Upper = APInt::getSignedMaxValue (Width) + 1 ;
9637
- }
9635
+
9636
+ if (inters.size () == 1 ) {
9637
+ // Exactly one contiguous overlap → use it
9638
+ Lower = inters[0 ].first ;
9639
+ Upper = inters[0 ].second ;
9640
+ } else if (HasNUW && !PreferSignedRange) {
9641
+ // Fallback to plain NUW result [0..C]
9642
+ Lower = APInt::getZero (Width);
9643
+ Upper = *C;
9644
+ } else if (HasNSW) {
9645
+ // Fallback to plain NSW result
9646
+ auto S = makeSignedRange ();
9647
+ Lower = S.first ;
9648
+ Upper = S.second ;
9649
+ }
9650
+ }
9651
+ break ;
9652
+ case Instruction::Add:
9653
+ if (match (BO.getOperand (1 ), m_APInt (C)) && !C->isZero ()) {
9654
+ bool HasNSW = IIQ.hasNoSignedWrap (&BO);
9655
+ bool HasNUW = IIQ.hasNoUnsignedWrap (&BO);
9656
+
9657
+ // If the caller prefers signed ranges when both wraps are forbidden:
9658
+ if (PreferSignedRange && HasNSW && HasNUW)
9659
+ HasNUW = false ;
9660
+
9661
+ // Build the two candidate ranges as [lo..hi] in the unsigned 0..2^n-1 world:
9662
+ // NUW: 'add nuw x, C' ⇒ [ C .. UINT_MAX ]
9663
+ auto makeUnsignedRange = [&]() {
9664
+ APInt lo = *C;
9665
+ APInt hi = APInt::getMaxValue (Width);
9666
+ return std::pair<APInt,APInt>(lo, hi);
9667
+ };
9668
+
9669
+ // NSW: 'add nsw x, C'
9670
+ // if C<0: [ SINT_MIN .. SINT_MAX + C ]
9671
+ // else: [ SINT_MIN + C .. SINT_MAX ]
9672
+ auto makeSignedRange = [&]() {
9673
+ if (C->isNegative ()) {
9674
+ APInt lo = APInt::getSignedMinValue (Width);
9675
+ APInt hi = APInt::getSignedMaxValue (Width) + *C;
9676
+ return std::pair<APInt,APInt>(lo, hi);
9677
+ } else {
9678
+ APInt lo = APInt::getSignedMinValue (Width) + *C;
9679
+ APInt hi = APInt::getSignedMaxValue (Width);
9680
+ return std::pair<APInt,APInt>(lo, hi);
9681
+ }
9682
+ };
9683
+
9684
+ // Split [lo..hi] into up to two non‑wrapping intervals:
9685
+ auto splitPieces = [&](std::pair<APInt,APInt> rng,
9686
+ SmallVectorImpl<std::pair<APInt,APInt>> &dst) {
9687
+ APInt lo = rng.first , hi = rng.second ;
9688
+ if (lo.ugt (hi)) {
9689
+ // wraps around 2^n
9690
+ dst.emplace_back (lo, APInt::getMaxValue (Width));
9691
+ dst.emplace_back (APInt::getZero (Width), hi);
9692
+ } else {
9693
+ dst.emplace_back (lo, hi);
9694
+ }
9695
+ };
9696
+
9697
+ SmallVector<std::pair<APInt,APInt>,2 > piecesU, piecesS;
9698
+ if (HasNUW) splitPieces (makeUnsignedRange (), piecesU);
9699
+ if (HasNSW) splitPieces (makeSignedRange (), piecesS);
9700
+
9701
+ // Intersect piecewise
9702
+ SmallVector<std::pair<APInt,APInt>,2 > inters;
9703
+ for (auto &u : piecesU) {
9704
+ for (auto &s : piecesS) {
9705
+ APInt loI = u.first .ugt (s.first ) ? u.first : s.first ;
9706
+ APInt hiI = u.second .ult (s.second ) ? u.second : s.second ;
9707
+ if (loI.ule (hiI))
9708
+ inters.emplace_back (loI, hiI);
9638
9709
}
9639
9710
}
9640
- break ;
9711
+
9712
+ if (inters.size () == 1 ) {
9713
+ // Exactly one contiguous overlap ⇒ use it
9714
+ Lower = inters[0 ].first ;
9715
+ Upper = inters[0 ].second + 1 ; // make Upper exclusive if you’re following [Lo..Hi)
9716
+ } else if (HasNUW && !PreferSignedRange) {
9717
+ // Fallback to plain NUW [C..UINT_MAX]
9718
+ Lower = *C;
9719
+ Upper = APInt::getMaxValue (Width) + 1 ;
9720
+ } else if (HasNSW) {
9721
+ // Fallback to plain NSW
9722
+ auto S = makeSignedRange ();
9723
+ Lower = S.first ;
9724
+ Upper = S.second + 1 ;
9725
+ }
9726
+ }
9727
+ break ;
9641
9728
9642
9729
case Instruction::And:
9643
9730
if (match (BO.getOperand (1 ), m_APInt (C)))
0 commit comments