@@ -6799,10 +6799,11 @@ const ConstantRange &ScalarEvolution::getRangeRef(
6799
6799
MaxBECount = MaxBECount.zext(BitWidth);
6800
6800
6801
6801
if (MaxBECount.getBitWidth() == BitWidth) {
6802
- auto RangeFromAffine = getRangeForAffineAR(
6802
+ auto [ RangeFromAffine, Flags] = getRangeForAffineAR(
6803
6803
AddRec->getStart(), AddRec->getStepRecurrence(*this), MaxBECount);
6804
6804
ConservativeResult =
6805
6805
ConservativeResult.intersectWith(RangeFromAffine, RangeType);
6806
+ const_cast<SCEVAddRecExpr *>(AddRec)->setNoWrapFlags(Flags);
6806
6807
6807
6808
auto RangeFromFactoring = getRangeViaFactoring(
6808
6809
AddRec->getStart(), AddRec->getStepRecurrence(*this), MaxBECount);
@@ -6978,24 +6979,24 @@ const ConstantRange &ScalarEvolution::getRangeRef(
6978
6979
// Given a StartRange, Step and MaxBECount for an expression compute a range of
6979
6980
// values that the expression can take. Initially, the expression has a value
6980
6981
// from StartRange and then is changed by Step up to MaxBECount times. Signed
6981
- // argument defines if we treat Step as signed or unsigned.
6982
- static ConstantRange getRangeForAffineARHelper(APInt Step,
6983
- const ConstantRange &StartRange,
6984
- const APInt &MaxBECount ,
6985
- bool Signed) {
6982
+ // argument defines if we treat Step as signed or unsigned. The second return
6983
+ // value indicates that no wrapping occurred.
6984
+ static std::pair< ConstantRange, bool>
6985
+ getRangeForAffineARHelper(APInt Step, const ConstantRange &StartRange ,
6986
+ const APInt &MaxBECount, bool Signed) {
6986
6987
unsigned BitWidth = Step.getBitWidth();
6987
6988
assert(BitWidth == StartRange.getBitWidth() &&
6988
6989
BitWidth == MaxBECount.getBitWidth() && "mismatched bit widths");
6989
6990
// If either Step or MaxBECount is 0, then the expression won't change, and we
6990
6991
// just need to return the initial range.
6991
6992
if (Step == 0 || MaxBECount == 0)
6992
- return StartRange;
6993
+ return { StartRange, true} ;
6993
6994
6994
6995
// If we don't know anything about the initial value (i.e. StartRange is
6995
6996
// FullRange), then we don't know anything about the final range either.
6996
6997
// Return FullRange.
6997
6998
if (StartRange.isFullSet())
6998
- return ConstantRange::getFull(BitWidth);
6999
+ return { ConstantRange::getFull(BitWidth), false} ;
6999
7000
7000
7001
// If Step is signed and negative, then we use its absolute value, but we also
7001
7002
// note that we're moving in the opposite direction.
@@ -7011,7 +7012,7 @@ static ConstantRange getRangeForAffineARHelper(APInt Step,
7011
7012
// Check if Offset is more than full span of BitWidth. If it is, the
7012
7013
// expression is guaranteed to overflow.
7013
7014
if (APInt::getMaxValue(StartRange.getBitWidth()).udiv(Step).ult(MaxBECount))
7014
- return ConstantRange::getFull(BitWidth);
7015
+ return { ConstantRange::getFull(BitWidth), false} ;
7015
7016
7016
7017
// Offset is by how much the expression can change. Checks above guarantee no
7017
7018
// overflow here.
@@ -7023,14 +7024,21 @@ static ConstantRange getRangeForAffineARHelper(APInt Step,
7023
7024
// if the expression is decreasing and will be increased by Offset otherwise.
7024
7025
APInt StartLower = StartRange.getLower();
7025
7026
APInt StartUpper = StartRange.getUpper() - 1;
7026
- APInt MovedBoundary = Descending ? (StartLower - std::move(Offset))
7027
- : (StartUpper + std::move(Offset));
7027
+ bool Overflow;
7028
+ APInt MovedBoundary;
7029
+ if (Signed) {
7030
+ MovedBoundary = Descending ? StartLower.ssub_ov(Offset, Overflow)
7031
+ : StartUpper.sadd_ov(Offset, Overflow);
7032
+ Overflow |= Offset.isNegative();
7033
+ } else {
7034
+ MovedBoundary = StartUpper.uadd_ov(std::move(Offset), Overflow);
7035
+ }
7028
7036
7029
7037
// It's possible that the new minimum/maximum value will fall into the initial
7030
7038
// range (due to wrap around). This means that the expression can take any
7031
7039
// value in this bitwidth, and we have to return full range.
7032
7040
if (StartRange.contains(MovedBoundary))
7033
- return ConstantRange::getFull(BitWidth);
7041
+ return { ConstantRange::getFull(BitWidth), false} ;
7034
7042
7035
7043
APInt NewLower =
7036
7044
Descending ? std::move(MovedBoundary) : std::move(StartLower);
@@ -7039,12 +7047,13 @@ static ConstantRange getRangeForAffineARHelper(APInt Step,
7039
7047
NewUpper += 1;
7040
7048
7041
7049
// No overflow detected, return [StartLower, StartUpper + Offset + 1) range.
7042
- return ConstantRange::getNonEmpty(std::move(NewLower), std::move(NewUpper));
7050
+ return {ConstantRange::getNonEmpty(std::move(NewLower), std::move(NewUpper)),
7051
+ !Overflow};
7043
7052
}
7044
7053
7045
- ConstantRange ScalarEvolution::getRangeForAffineAR(const SCEV *Start,
7046
- const SCEV *Step,
7047
- const APInt &MaxBECount) {
7054
+ std::pair<ConstantRange, SCEV::NoWrapFlags>
7055
+ ScalarEvolution::getRangeForAffineAR(const SCEV *Start, const SCEV *Step,
7056
+ const APInt &MaxBECount) {
7048
7057
assert(getTypeSizeInBits(Start->getType()) ==
7049
7058
getTypeSizeInBits(Step->getType()) &&
7050
7059
getTypeSizeInBits(Start->getType()) == MaxBECount.getBitWidth() &&
@@ -7056,19 +7065,26 @@ ConstantRange ScalarEvolution::getRangeForAffineAR(const SCEV *Start,
7056
7065
7057
7066
// If Step can be both positive and negative, we need to find ranges for the
7058
7067
// maximum absolute step values in both directions and union them.
7059
- ConstantRange SR = getRangeForAffineARHelper(
7060
- StepSRange.getSignedMin(), StartSRange, MaxBECount, /* Signed = */ true);
7061
- SR = SR.unionWith(getRangeForAffineARHelper(StepSRange.getSignedMax(),
7062
- StartSRange, MaxBECount,
7063
- /* Signed = */ true));
7068
+ auto [SR1, NSW1] = getRangeForAffineARHelper(
7069
+ StepSRange.getSignedMin(), StartSRange, MaxBECount, /*Signed=*/true);
7070
+ auto [SR2, NSW2] = getRangeForAffineARHelper(StepSRange.getSignedMax(),
7071
+ StartSRange, MaxBECount,
7072
+ /*Signed=*/true);
7073
+ ConstantRange SR = SR1.unionWith(SR2);
7064
7074
7065
7075
// Next, consider step unsigned.
7066
- ConstantRange UR = getRangeForAffineARHelper(
7076
+ auto [UR, NUW] = getRangeForAffineARHelper(
7067
7077
getUnsignedRangeMax(Step), getUnsignedRange(Start), MaxBECount,
7068
- /* Signed = */ false);
7078
+ /*Signed=*/false);
7079
+
7080
+ SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap;
7081
+ if (NUW)
7082
+ Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNUW);
7083
+ if (NSW1 && NSW2)
7084
+ Flags = ScalarEvolution::setFlags(Flags, SCEV::FlagNSW);
7069
7085
7070
7086
// Finally, intersect signed and unsigned ranges.
7071
- return SR.intersectWith(UR, ConstantRange::Smallest);
7087
+ return { SR.intersectWith(UR, ConstantRange::Smallest), Flags} ;
7072
7088
}
7073
7089
7074
7090
ConstantRange ScalarEvolution::getRangeForAffineNoSelfWrappingAR(
@@ -7246,9 +7262,9 @@ ConstantRange ScalarEvolution::getRangeViaFactoring(const SCEV *Start,
7246
7262
const SCEV *FalseStep = this->getConstant(StepPattern.FalseValue);
7247
7263
7248
7264
ConstantRange TrueRange =
7249
- this->getRangeForAffineAR(TrueStart, TrueStep, MaxBECount);
7265
+ this->getRangeForAffineAR(TrueStart, TrueStep, MaxBECount).first ;
7250
7266
ConstantRange FalseRange =
7251
- this->getRangeForAffineAR(FalseStart, FalseStep, MaxBECount);
7267
+ this->getRangeForAffineAR(FalseStart, FalseStep, MaxBECount).first ;
7252
7268
7253
7269
return TrueRange.unionWith(FalseRange);
7254
7270
}
0 commit comments