DenseMap<const SCEV *, ConstantRange> &Cache =
SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED ? UnsignedRanges
: SignedRanges;
+ ConstantRange::PreferredRangeType RangeType =
+ SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED
+ ? ConstantRange::Unsigned : ConstantRange::Signed;
// See if we've computed this range already.
DenseMap<const SCEV *, ConstantRange>::iterator I = Cache.find(S);
ConstantRange X = getRangeRef(Add->getOperand(0), SignHint);
for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i)
X = X.add(getRangeRef(Add->getOperand(i), SignHint));
- return setRange(Add, SignHint, ConservativeResult.intersectWith(X));
+ return setRange(Add, SignHint,
+ ConservativeResult.intersectWith(X, RangeType));
}
if (const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(S)) {
ConstantRange X = getRangeRef(Mul->getOperand(0), SignHint);
for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i)
X = X.multiply(getRangeRef(Mul->getOperand(i), SignHint));
- return setRange(Mul, SignHint, ConservativeResult.intersectWith(X));
+ return setRange(Mul, SignHint,
+ ConservativeResult.intersectWith(X, RangeType));
}
if (const SCEVSMaxExpr *SMax = dyn_cast<SCEVSMaxExpr>(S)) {
ConstantRange X = getRangeRef(SMax->getOperand(0), SignHint);
for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i)
X = X.smax(getRangeRef(SMax->getOperand(i), SignHint));
- return setRange(SMax, SignHint, ConservativeResult.intersectWith(X));
+ return setRange(SMax, SignHint,
+ ConservativeResult.intersectWith(X, RangeType));
}
if (const SCEVUMaxExpr *UMax = dyn_cast<SCEVUMaxExpr>(S)) {
ConstantRange X = getRangeRef(UMax->getOperand(0), SignHint);
for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i)
X = X.umax(getRangeRef(UMax->getOperand(i), SignHint));
- return setRange(UMax, SignHint, ConservativeResult.intersectWith(X));
+ return setRange(UMax, SignHint,
+ ConservativeResult.intersectWith(X, RangeType));
}
if (const SCEVUDivExpr *UDiv = dyn_cast<SCEVUDivExpr>(S)) {
ConstantRange X = getRangeRef(UDiv->getLHS(), SignHint);
ConstantRange Y = getRangeRef(UDiv->getRHS(), SignHint);
return setRange(UDiv, SignHint,
- ConservativeResult.intersectWith(X.udiv(Y)));
+ ConservativeResult.intersectWith(X.udiv(Y), RangeType));
}
if (const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(S)) {
ConstantRange X = getRangeRef(ZExt->getOperand(), SignHint);
return setRange(ZExt, SignHint,
- ConservativeResult.intersectWith(X.zeroExtend(BitWidth)));
+ ConservativeResult.intersectWith(X.zeroExtend(BitWidth),
+ RangeType));
}
if (const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(S)) {
ConstantRange X = getRangeRef(SExt->getOperand(), SignHint);
return setRange(SExt, SignHint,
- ConservativeResult.intersectWith(X.signExtend(BitWidth)));
+ ConservativeResult.intersectWith(X.signExtend(BitWidth),
+ RangeType));
}
if (const SCEVTruncateExpr *Trunc = dyn_cast<SCEVTruncateExpr>(S)) {
ConstantRange X = getRangeRef(Trunc->getOperand(), SignHint);
return setRange(Trunc, SignHint,
- ConservativeResult.intersectWith(X.truncate(BitWidth)));
+ ConservativeResult.intersectWith(X.truncate(BitWidth),
+ RangeType));
}
if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(AddRec->getStart()))
if (!C->getValue()->isZero())
ConservativeResult = ConservativeResult.intersectWith(
- ConstantRange(C->getAPInt(), APInt(BitWidth, 0)));
+ ConstantRange(C->getAPInt(), APInt(BitWidth, 0)), RangeType);
// If there's no signed wrap, and all the operands have the same sign or
// zero, the value won't ever change sign.
if (AllNonNeg)
ConservativeResult = ConservativeResult.intersectWith(
ConstantRange(APInt(BitWidth, 0),
- APInt::getSignedMinValue(BitWidth)));
+ APInt::getSignedMinValue(BitWidth)), RangeType);
else if (AllNonPos)
ConservativeResult = ConservativeResult.intersectWith(
ConstantRange(APInt::getSignedMinValue(BitWidth),
- APInt(BitWidth, 1)));
+ APInt(BitWidth, 1)), RangeType);
}
// TODO: non-affine addrec
BitWidth);
if (!RangeFromAffine.isFullSet())
ConservativeResult =
- ConservativeResult.intersectWith(RangeFromAffine);
+ ConservativeResult.intersectWith(RangeFromAffine, RangeType);
auto RangeFromFactoring = getRangeViaFactoring(
AddRec->getStart(), AddRec->getStepRecurrence(*this), MaxBECount,
BitWidth);
if (!RangeFromFactoring.isFullSet())
ConservativeResult =
- ConservativeResult.intersectWith(RangeFromFactoring);
+ ConservativeResult.intersectWith(RangeFromFactoring, RangeType);
}
}
// Check if the IR explicitly contains !range metadata.
Optional<ConstantRange> MDRange = GetRangeFromMetadata(U->getValue());
if (MDRange.hasValue())
- ConservativeResult = ConservativeResult.intersectWith(MDRange.getValue());
+ ConservativeResult = ConservativeResult.intersectWith(MDRange.getValue(),
+ RangeType);
// Split here to avoid paying the compile-time cost of calling both
// computeKnownBits and ComputeNumSignBits. This restriction can be lifted
KnownBits Known = computeKnownBits(U->getValue(), DL, 0, &AC, nullptr, &DT);
if (Known.One != ~Known.Zero + 1)
ConservativeResult =
- ConservativeResult.intersectWith(ConstantRange(Known.One,
- ~Known.Zero + 1));
+ ConservativeResult.intersectWith(
+ ConstantRange(Known.One, ~Known.Zero + 1), RangeType);
} else {
assert(SignHint == ScalarEvolution::HINT_RANGE_SIGNED &&
"generalize as needed!");
if (NS > 1)
ConservativeResult = ConservativeResult.intersectWith(
ConstantRange(APInt::getSignedMinValue(BitWidth).ashr(NS - 1),
- APInt::getSignedMaxValue(BitWidth).ashr(NS - 1) + 1));
+ APInt::getSignedMaxValue(BitWidth).ashr(NS - 1) + 1),
+ RangeType);
}
// A range of Phi is a subset of union of all ranges of its input.
if (RangeFromOps.isFullSet())
break;
}
- ConservativeResult = ConservativeResult.intersectWith(RangeFromOps);
+ ConservativeResult =
+ ConservativeResult.intersectWith(RangeFromOps, RangeType);
bool Erased = PendingPhiRanges.erase(Phi);
assert(Erased && "Failed to erase Phi properly?");
(void) Erased;
MaxBECountValue, BitWidth, /* Signed = */ false);
// Finally, intersect signed and unsigned ranges.
- return SR.intersectWith(UR);
+ return SR.intersectWith(UR, ConstantRange::Smallest);
}
ConstantRange ScalarEvolution::getRangeViaFactoring(const SCEV *Start,
; CHECK-NEXT: %tmp1 = udiv i32 %val, 16
; CHECK-NEXT: --> (%val /u 16) U: [0,268435456) S: [0,268435456)
; CHECK-NEXT: %tmp2 = mul i32 %tmp1, 16
-; CHECK-NEXT: --> (16 * (%val /u 16))<nuw> U: [0,-15) S: [0,-15)
+; CHECK-NEXT: --> (16 * (%val /u 16))<nuw> U: [0,-15) S: [-2147483648,2147483633)
; CHECK-NEXT: Determining loop execution counts for: @div
;
%tmp1 = udiv i32 %val, 16
; CHECK-LABEL: 'mask_b'
; CHECK-NEXT: Classifying expressions for: @mask_b
; CHECK-NEXT: %masked = and i32 %val, -16
-; CHECK-NEXT: --> (16 * (%val /u 16))<nuw> U: [0,-15) S: [0,-15)
+; CHECK-NEXT: --> (16 * (%val /u 16))<nuw> U: [0,-15) S: [-2147483648,2147483633)
; CHECK-NEXT: Determining loop execution counts for: @mask_b
;
%masked = and i32 %val, -16
; CHECK-NEXT: %lowbitscleared = lshr i32 %val, 4
; CHECK-NEXT: --> (%val /u 16) U: [0,268435456) S: [0,268435456)
; CHECK-NEXT: %masked = shl i32 %lowbitscleared, 4
-; CHECK-NEXT: --> (16 * (%val /u 16))<nuw> U: [0,-15) S: [0,-15)
+; CHECK-NEXT: --> (16 * (%val /u 16))<nuw> U: [0,-15) S: [-2147483648,2147483633)
; CHECK-NEXT: Determining loop execution counts for: @mask_d
;
%lowbitscleared = lshr i32 %val, 4
; CHECK: %iv.m1 = sub i32 %iv, 1
; CHECK-NEXT: --> {(-1 + %start)<nsw>,+,%step}<%loop> U: [-1,120) S: [-1,120)
; CHECK: %iv.m2 = sub i32 %iv, 2
-; CHECK-NEXT: --> {(-2 + %start)<nsw>,+,%step}<%loop> U: [-2,119) S: [-2,119)
+; CHECK-NEXT: --> {(-2 + %start)<nsw>,+,%step}<%loop> U: [0,-1) S: [-2,119)
; CHECK: %iv.m3 = sub i32 %iv, 3
; CHECK-NEXT: --> {(-3 + %start)<nsw>,+,%step}<%loop> U: [-3,118) S: [-3,118)
; CHECK: %iv.m4 = sub i32 %iv, 4
-; CHECK-NEXT: --> {(-4 + %start)<nsw>,+,%step}<%loop> U: [-4,117) S: [-4,117)
+; CHECK-NEXT: --> {(-4 + %start)<nsw>,+,%step}<%loop> U: [0,-3) S: [-4,117)
; CHECK: %iv.m5 = sub i32 %iv, 5
; CHECK-NEXT: --> {(-5 + %start)<nsw>,+,%step}<%loop> U: [-5,116) S: [-5,116)
; CHECK: %iv.m6 = sub i32 %iv, 6
-; CHECK-NEXT: --> {(-6 + %start)<nsw>,+,%step}<%loop> U: [-6,115) S: [-6,115)
+; CHECK-NEXT: --> {(-6 + %start)<nsw>,+,%step}<%loop> U: [0,-1) S: [-6,115)
; CHECK: %iv.m7 = sub i32 %iv, 7
; CHECK-NEXT: --> {(-7 + %start)<nsw>,+,%step}<%loop> U: [-7,114) S: [-7,114)
%iv.next = add i32 %iv, %step.plus.one
%iv.sext = sext i32 %iv to i64
; CHECK: %iv.sext = sext i32 %iv to i64
-; CHECK-NEXT: --> {(sext i32 %start to i64),+,(1 + (sext i32 %step to i64))<nsw>}<nsw><%loop> U: [0,128) S: [0,128)
+; CHECK-NEXT: --> {(sext i32 %start to i64),+,(1 + (sext i32 %step to i64))<nuw><nsw>}<nsw><%loop> U: [0,128) S: [0,128)
%loop.iv.inc = add i16 %loop.iv, 1
%be.cond = icmp ne i16 %loop.iv.inc, 128
br i1 %be.cond, label %loop, label %leave