@@ -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
0 commit comments