summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp87
1 files changed, 73 insertions, 14 deletions
diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
index 9011c0433c9..42c74c3a3cc 100644
--- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
@@ -112,7 +112,7 @@ static cl::opt<bool> SkipProfitabilityChecks("irce-skip-profitability-checks",
cl::Hidden, cl::init(false));
static cl::opt<bool> AllowUnsignedLatchCondition("irce-allow-unsigned-latch",
- cl::Hidden, cl::init(false));
+ cl::Hidden, cl::init(true));
static const char *ClonedLoopTag = "irce.loop.clone";
@@ -154,10 +154,11 @@ class InductiveRangeCheck {
Value *Length = nullptr;
Use *CheckUse = nullptr;
RangeCheckKind Kind = RANGE_CHECK_UNKNOWN;
+ bool IsSigned = true;
static RangeCheckKind parseRangeCheckICmp(Loop *L, ICmpInst *ICI,
ScalarEvolution &SE, Value *&Index,
- Value *&Length);
+ Value *&Length, bool &IsSigned);
static void
extractRangeChecksFromCond(Loop *L, ScalarEvolution &SE, Use &ConditionUse,
@@ -168,6 +169,7 @@ public:
const SCEV *getOffset() const { return Offset; }
const SCEV *getScale() const { return Scale; }
Value *getLength() const { return Length; }
+ bool isSigned() const { return IsSigned; }
void print(raw_ostream &OS) const {
OS << "InductiveRangeCheck:\n";
@@ -295,7 +297,7 @@ StringRef InductiveRangeCheck::rangeCheckKindToStr(
InductiveRangeCheck::RangeCheckKind
InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI,
ScalarEvolution &SE, Value *&Index,
- Value *&Length) {
+ Value *&Length, bool &IsSigned) {
auto IsNonNegativeAndNotLoopVarying = [&SE, L](Value *V) {
const SCEV *S = SE.getSCEV(V);
if (isa<SCEVCouldNotCompute>(S))
@@ -317,6 +319,7 @@ InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI,
std::swap(LHS, RHS);
LLVM_FALLTHROUGH;
case ICmpInst::ICMP_SGE:
+ IsSigned = true;
if (match(RHS, m_ConstantInt<0>())) {
Index = LHS;
return RANGE_CHECK_LOWER;
@@ -327,6 +330,7 @@ InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI,
std::swap(LHS, RHS);
LLVM_FALLTHROUGH;
case ICmpInst::ICMP_SGT:
+ IsSigned = true;
if (match(RHS, m_ConstantInt<-1>())) {
Index = LHS;
return RANGE_CHECK_LOWER;
@@ -343,6 +347,7 @@ InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI,
std::swap(LHS, RHS);
LLVM_FALLTHROUGH;
case ICmpInst::ICMP_UGT:
+ IsSigned = false;
if (IsNonNegativeAndNotLoopVarying(LHS)) {
Index = RHS;
Length = LHS;
@@ -375,7 +380,8 @@ void InductiveRangeCheck::extractRangeChecksFromCond(
const auto &RChkA = SubChecks[0];
const auto &RChkB = SubChecks[1];
if ((RChkA.Length == RChkB.Length || !RChkA.Length || !RChkB.Length) &&
- RChkA.Offset == RChkB.Offset && RChkA.Scale == RChkB.Scale) {
+ RChkA.Offset == RChkB.Offset && RChkA.Scale == RChkB.Scale &&
+ RChkA.IsSigned == RChkB.IsSigned) {
// If RChkA.Kind == RChkB.Kind then we just found two identical checks.
// But if one of them is a RANGE_CHECK_LOWER and the other is a
// RANGE_CHECK_UPPER (only possibility if they're different) then
@@ -384,6 +390,7 @@ void InductiveRangeCheck::extractRangeChecksFromCond(
(InductiveRangeCheck::RangeCheckKind)(RChkA.Kind | RChkB.Kind);
SubChecks[0].Length = RChkA.Length ? RChkA.Length : RChkB.Length;
SubChecks[0].CheckUse = &ConditionUse;
+ SubChecks[0].IsSigned = RChkA.IsSigned;
// We updated one of the checks in place, now erase the other.
SubChecks.pop_back();
@@ -399,7 +406,8 @@ void InductiveRangeCheck::extractRangeChecksFromCond(
return;
Value *Length = nullptr, *Index;
- auto RCKind = parseRangeCheckICmp(L, ICI, SE, Index, Length);
+ bool IsSigned;
+ auto RCKind = parseRangeCheckICmp(L, ICI, SE, Index, Length, IsSigned);
if (RCKind == InductiveRangeCheck::RANGE_CHECK_UNKNOWN)
return;
@@ -416,6 +424,7 @@ void InductiveRangeCheck::extractRangeChecksFromCond(
IRC.Scale = IndexAddRec->getStepRecurrence(SE);
IRC.CheckUse = &ConditionUse;
IRC.Kind = RCKind;
+ IRC.IsSigned = IsSigned;
Checks.push_back(IRC);
}
@@ -917,9 +926,6 @@ LoopStructure::parseLoopStructure(ScalarEvolution &SE,
IsSignedPredicate =
Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGT;
- // FIXME: We temporarily disable unsigned latch conditions by default
- // because of found problems with intersecting signed and unsigned ranges.
- // We are going to turn it on once the problems are fixed.
if (!IsSignedPredicate && !AllowUnsignedLatchCondition) {
FailureReason = "unsigned latch conditions are explicitly prohibited";
return None;
@@ -1001,9 +1007,6 @@ LoopStructure::parseLoopStructure(ScalarEvolution &SE,
IsSignedPredicate =
Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGT;
- // FIXME: We temporarily disable unsigned latch conditions by default
- // because of found problems with intersecting signed and unsigned ranges.
- // We are going to turn it on once the problems are fixed.
if (!IsSignedPredicate && !AllowUnsignedLatchCondition) {
FailureReason = "unsigned latch conditions are explicitly prohibited";
return None;
@@ -1670,9 +1673,9 @@ InductiveRangeCheck::computeSafeIterationSpace(
}
static Optional<InductiveRangeCheck::Range>
-IntersectRange(ScalarEvolution &SE,
- const Optional<InductiveRangeCheck::Range> &R1,
- const InductiveRangeCheck::Range &R2) {
+IntersectSignedRange(ScalarEvolution &SE,
+ const Optional<InductiveRangeCheck::Range> &R1,
+ const InductiveRangeCheck::Range &R2) {
if (R2.isEmpty(SE, /* IsSigned */ true))
return None;
if (!R1.hasValue())
@@ -1698,6 +1701,35 @@ IntersectRange(ScalarEvolution &SE,
return Ret;
}
+static Optional<InductiveRangeCheck::Range>
+IntersectUnsignedRange(ScalarEvolution &SE,
+ const Optional<InductiveRangeCheck::Range> &R1,
+ const InductiveRangeCheck::Range &R2) {
+ if (R2.isEmpty(SE, /* IsSigned */ false))
+ return None;
+ if (!R1.hasValue())
+ return R2;
+ auto &R1Value = R1.getValue();
+ // We never return empty ranges from this function, and R1 is supposed to be
+ // a result of intersection. Thus, R1 is never empty.
+ assert(!R1Value.isEmpty(SE, /* IsSigned */ false) &&
+ "We should never have empty R1!");
+
+ // TODO: we could widen the smaller range and have this work; but for now we
+ // bail out to keep things simple.
+ if (R1Value.getType() != R2.getType())
+ return None;
+
+ const SCEV *NewBegin = SE.getUMaxExpr(R1Value.getBegin(), R2.getBegin());
+ const SCEV *NewEnd = SE.getUMinExpr(R1Value.getEnd(), R2.getEnd());
+
+ // If the resulting range is empty, just return None.
+ auto Ret = InductiveRangeCheck::Range(NewBegin, NewEnd);
+ if (Ret.isEmpty(SE, /* IsSigned */ false))
+ return None;
+ return Ret;
+}
+
bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
if (skipLoop(L))
return false;
@@ -1756,11 +1788,38 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
Instruction *ExprInsertPt = Preheader->getTerminator();
SmallVector<InductiveRangeCheck, 4> RangeChecksToEliminate;
+ auto RangeIsNonNegative = [&](InductiveRangeCheck::Range &R) {
+ return SE.isKnownNonNegative(R.getBegin()) &&
+ SE.isKnownNonNegative(R.getEnd());
+ };
+ // Basing on the type of latch predicate, we interpret the IV iteration range
+ // as signed or unsigned range. We use different min/max functions (signed or
+ // unsigned) when intersecting this range with safe iteration ranges implied
+ // by range checks.
+ auto IntersectRange =
+ LS.IsSignedPredicate ? IntersectSignedRange : IntersectUnsignedRange;
IRBuilder<> B(ExprInsertPt);
for (InductiveRangeCheck &IRC : RangeChecks) {
auto Result = IRC.computeSafeIterationSpace(SE, IndVar);
if (Result.hasValue()) {
+ // Intersecting a signed and an unsigned ranges may produce incorrect
+ // results because we can use neither signed nor unsigned min/max for
+ // reliably correct intersection if a range contains negative values
+ // which are either actually negative or big positive. Intersection is
+ // safe in two following cases:
+ // 1. Both ranges are signed/unsigned, then we use signed/unsigned min/max
+ // respectively for their intersection;
+ // 2. IRC safe iteration space only contains values from [0, SINT_MAX].
+ // The interpretation of these values is unambiguous.
+ // We take the type of IV iteration range as a reference (we will
+ // intersect it with the resulting range of all IRC's later in
+ // calculateSubRanges). Only ranges of IRC of the same type are considered
+ // for removal unless we prove that its range doesn't contain ambiguous
+ // values.
+ if (IRC.isSigned() != LS.IsSignedPredicate &&
+ !RangeIsNonNegative(Result.getValue()))
+ continue;
auto MaybeSafeIterRange =
IntersectRange(SE, SafeIterRange, Result.getValue());
if (MaybeSafeIterRange.hasValue()) {
OpenPOWER on IntegriCloud