@@ -9576,15 +9576,48 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower,
9576
9576
unsigned Width = Lower.getBitWidth ();
9577
9577
const APInt *C;
9578
9578
switch (BO.getOpcode ()) {
9579
- case Instruction::Add :
9580
- if (match (BO.getOperand (1 ), m_APInt (C)) && !C-> isZero ( )) {
9579
+ case Instruction::Sub :
9580
+ if (match (BO.getOperand (0 ), m_APInt (C))) {
9581
9581
bool HasNSW = IIQ.hasNoSignedWrap (&BO);
9582
9582
bool HasNUW = IIQ.hasNoUnsignedWrap (&BO);
9583
9583
9584
9584
// If the caller expects a signed compare, then try to use a signed range.
9585
9585
// Otherwise if both no-wraps are set, use the unsigned range because it
9586
9586
// is never larger than the signed range. Example:
9587
- // "add nuw nsw i8 X, -2" is unsigned [254,255] vs. signed [-128, 125].
9587
+ // "sub nuw nsw i8 -2, x" is unsigned [0, 254] vs. signed [-128, 126].
9588
+ // "sub nuw nsw i8 2, x" is unsigned [0, 2] vs. signed [-125, 127].
9589
+ if (PreferSignedRange && HasNSW && HasNUW)
9590
+ HasNUW = false ;
9591
+
9592
+ if (HasNUW) {
9593
+ // 'sub nuw c, x' produces [0, C].
9594
+ Upper = *C + 1 ;
9595
+ } else if (HasNSW) {
9596
+ if (C->isNegative ()) {
9597
+ // 'sub nsw -C, x' produces [SINT_MIN, SINT_MAX - (C - 1)].
9598
+ // Because to be negative, C must be - 1, and the highest result is
9599
+ // INT_MIN, so -INT_MIN - 1 is INT_MAX, so it is SINT_MAX - (C - 1),
9600
+ // or SINT_MAX - C + 1
9601
+ Lower = APInt::getSignedMinValue (Width);
9602
+ Upper = APInt::getSignedMaxValue (Width) + *C + 2 ;
9603
+ } else {
9604
+ // Note that sub 0, INT_MIN is not NSW. It techically is a signed wrap
9605
+ // 'sub nsw C, x' produces [SINT_MIN + 1 + C, SINT_MAX].
9606
+ Lower = APInt::getSignedMinValue (Width) + *C + 1 ;
9607
+ Upper = APInt::getSignedMaxValue (Width) + 1 ;
9608
+ }
9609
+ }
9610
+ }
9611
+ break ;
9612
+ case Instruction::Add:
9613
+ if (match (BO.getOperand (1 ), m_APInt (C)) && !C->isZero ()) {
9614
+ bool HasNSW = IIQ.hasNoSignedWrap (&BO);
9615
+ bool HasNUW = IIQ.hasNoUnsignedWrap (&BO);
9616
+
9617
+ // If the caller expects a signed compare, then try to use a signed
9618
+ // range. Otherwise if both no-wraps are set, use the unsigned range
9619
+ // because it is never larger than the signed range. Example: "add nuw
9620
+ // nsw i8 X, -2" is unsigned [254,255] vs. signed [-128, 125].
9588
9621
if (PreferSignedRange && HasNSW && HasNUW)
9589
9622
HasNUW = false ;
9590
9623
@@ -9609,8 +9642,8 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower,
9609
9642
if (match (BO.getOperand (1 ), m_APInt (C)))
9610
9643
// 'and x, C' produces [0, C].
9611
9644
Upper = *C + 1 ;
9612
- // X & -X is a power of two or zero. So we can cap the value at max power of
9613
- // two.
9645
+ // X & -X is a power of two or zero. So we can cap the value at max power
9646
+ // of two.
9614
9647
if (match (BO.getOperand (0 ), m_Neg (m_Specific (BO.getOperand (1 )))) ||
9615
9648
match (BO.getOperand (1 ), m_Neg (m_Specific (BO.getOperand (0 )))))
9616
9649
Upper = APInt::getSignedMinValue (Width) + 1 ;
@@ -9679,10 +9712,10 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower,
9679
9712
// If lowbit is set, value can never be zero.
9680
9713
if ((*C)[0 ])
9681
9714
Lower = APInt::getOneBitSet (Width, 0 );
9682
- // If we are shifting a constant the largest it can be is if the longest
9683
- // sequence of consecutive ones is shifted to the highbits (breaking
9684
- // ties for which sequence is higher). At the moment we take a liberal
9685
- // upper bound on this by just popcounting the constant.
9715
+ // If we are shifting a constant the largest it can be is if the
9716
+ // longest sequence of consecutive ones is shifted to the highbits
9717
+ // (breaking ties for which sequence is higher). At the moment we take
9718
+ // a liberal upper bound on this by just popcounting the constant.
9686
9719
// TODO: There may be a bitwise trick for it longest/highest
9687
9720
// consecutative sequence of ones (naive method is O(Width) loop).
9688
9721
Upper = APInt::getHighBitsSet (Width, C->popcount ()) + 1 ;
0 commit comments