@@ -9576,6 +9576,60 @@ 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::Sub:
9580
+ if (match (BO.getOperand (1 ), m_APInt (C)) && !C->isZero ()) {
9581
+ bool HasNSW = IIQ.hasNoSignedWrap (&BO);
9582
+ bool HasNUW = IIQ.hasNoUnsignedWrap (&BO);
9583
+
9584
+ // If the caller expects a signed compare, then try to use a signed range.
9585
+ // Otherwise if both no-wraps are set, use the unsigned range because it
9586
+ // is never larger than the signed range. Example:
9587
+ // "sub nuw nsw i8 X, -2" is unsigned [0, 127] vs. signed [-128, 126].
9588
+ if (PreferSignedRange && HasNSW && HasNUW)
9589
+ HasNUW = false ;
9590
+
9591
+ if (HasNUW) {
9592
+ // 'sub nuw x, C' produces [0, UINT_MAX - C].
9593
+ Upper = APInt::getAllOnes (Width) - *C + 1 ;
9594
+ } else if (HasNSW) {
9595
+ if (C->isNegative ()) {
9596
+ // 'sub nsw x, -C' produces [SINT_MIN + C, SINT_MAX].
9597
+ Lower = APInt::getSignedMinValue (Width) + *C;
9598
+ Upper = APInt::getSignedMaxValue (Width) + 1 ;
9599
+ } else {
9600
+ // 'sub nsw x, +C' produces [SINT_MIN, SINT_MAX - C].
9601
+ Lower = APInt::getSignedMinValue (Width);
9602
+ Upper = APInt::getSignedMaxValue (Width) - *C + 1 ;
9603
+ }
9604
+ }
9605
+ } else if (match (BO.getOperand (0 ), m_APInt (C))) {
9606
+ bool HasNSW = IIQ.hasNoSignedWrap (&BO);
9607
+ bool HasNUW = IIQ.hasNoUnsignedWrap (&BO);
9608
+
9609
+ // If the caller expects a signed compare, then try to use a signed range.
9610
+ // Otherwise if both no-wraps are set, use the unsigned range because it
9611
+ // is never larger than the signed range. Example:
9612
+ // "sub nuw nsw i8 X, -2" is unsigned [0, 127] vs. signed [-128, 126].
9613
+ if (PreferSignedRange && HasNSW && HasNUW)
9614
+ HasNUW = false ;
9615
+
9616
+ if (HasNUW) {
9617
+ // 'sub nuw c, x' produces [0, C].
9618
+ Upper = *C + 1 ;
9619
+ } else if (HasNSW) {
9620
+ if (C->isNegative ()) {
9621
+ // 'sub nsw C, x' produces [SINT_MIN, SINT_MAX - C].
9622
+ Lower = APInt::getSignedMinValue (Width);
9623
+ Upper = APInt::getSignedMaxValue (Width) - *C + 1 ;
9624
+ } else {
9625
+ // Note that sub 0, INT_MIN is not NSW. It techically is a signed wrap
9626
+ // 'sub nsw C, x' produces [SINT_MIN + 1 + C, SINT_MAX].
9627
+ Lower = APInt::getSignedMinValue (Width) + *C + 1 ;
9628
+ Upper = APInt::getSignedMaxValue (Width) + 1 ;
9629
+ }
9630
+ }
9631
+ }
9632
+ break ;
9579
9633
case Instruction::Add:
9580
9634
if (match (BO.getOperand (1 ), m_APInt (C)) && !C->isZero ()) {
9581
9635
bool HasNSW = IIQ.hasNoSignedWrap (&BO);
0 commit comments