diff options
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp | 87 |
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()) { |

