Skip to content

Commit a2581a8

Browse files
committed
[ValueTracking] If overlap in unsigned and signed range is contiguous, return it
We have to choose between unsigned and signed if there are two overlaps, aka the range wraps around, meaning [254,255] vs. signed [-128, 125], but [254,255] correspond to [-2 -1] which is in the range [-128, 125]. However, a range that would not work would be one where one has to pick between [0, 129] vs [-127, 127] because 129 is -2 signed.
1 parent b983431 commit a2581a8

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9585,6 +9585,30 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower,
95859585
bool HasNSW = IIQ.hasNoSignedWrap(&BO);
95869586
bool HasNUW = IIQ.hasNoUnsignedWrap(&BO);
95879587

9588+
if (HasNUW && HasNSW) {
9589+
APInt uLo = APInt::getZero(Width);
9590+
APInt uHi = *C + 1;
9591+
9592+
APInt sLo, sHi;
9593+
if (C->isNegative()) {
9594+
sLo = APInt::getSignedMinValue(Width);
9595+
sHi = APInt::getSignedMaxValue(Width) + *C + 2;
9596+
} else {
9597+
sLo = APInt::getSignedMinValue(Width) + *C + 1;
9598+
sHi = APInt::getSignedMaxValue(Width) + 1;
9599+
}
9600+
9601+
APInt iLo = APIntOps::smax(uLo, sLo);
9602+
APInt iHi = APIntOps::smin(uHi, sHi);
9603+
9604+
if (iLo.ult(iHi) && iLo.sge(APInt::getSignedMinValue(Width)) &&
9605+
(iHi - 1).sle(APInt::getSignedMaxValue(Width))) {
9606+
Lower = iLo;
9607+
Upper = iHi;
9608+
break;
9609+
}
9610+
}
9611+
95889612
// If the caller expects a signed compare, then try to use a signed range.
95899613
// Otherwise if both no-wraps are set, use the unsigned range because it
95909614
// is never larger than the signed range. Example:
@@ -9615,6 +9639,31 @@ static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower,
96159639
bool HasNSW = IIQ.hasNoSignedWrap(&BO);
96169640
bool HasNUW = IIQ.hasNoUnsignedWrap(&BO);
96179641

9642+
if (HasNUW && HasNSW) {
9643+
APInt uLo = *C;
9644+
APInt uHi = APInt::getZero(Width);
9645+
9646+
APInt sLo, sHi;
9647+
if (C->isNegative()) {
9648+
sLo = APInt::getSignedMinValue(Width);
9649+
sHi = APInt::getSignedMaxValue(Width) + *C + 1;
9650+
} else {
9651+
sLo = APInt::getSignedMinValue(Width) + *C;
9652+
sHi = APInt::getSignedMaxValue(Width) + 1;
9653+
}
9654+
9655+
APInt iLo = APIntOps::smax(uLo, sLo);
9656+
APInt iHi = APIntOps::smin(uHi, sHi);
9657+
9658+
if (iLo.ult(iHi) &&
9659+
iLo.sge(APInt::getSignedMinValue(Width)) &&
9660+
(iHi - 1).sle(APInt::getSignedMaxValue(Width))) {
9661+
Lower = iLo;
9662+
Upper = iHi;
9663+
break;
9664+
}
9665+
}
9666+
96189667
// If the caller expects a signed compare, then try to use a signed
96199668
// range. Otherwise if both no-wraps are set, use the unsigned range
96209669
// because it is never larger than the signed range. Example: "add nuw

0 commit comments

Comments
 (0)