diff options
-rw-r--r-- | llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp | 89 |
1 files changed, 39 insertions, 50 deletions
diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp index 1b5cf89b4d9..cfefcb8cd5d 100644 --- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp +++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp @@ -125,9 +125,8 @@ class InductiveRangeCheck { ScalarEvolution &SE, Value *&Index, Value *&Length); - static InductiveRangeCheck::RangeCheckKind - parseRangeCheck(Loop *L, ScalarEvolution &SE, Value *Condition, - Value *&Index, Value *&UpperLimit); + static Optional<InductiveRangeCheck> + parseRangeCheckFromCond(Loop *L, ScalarEvolution &SE, Use &ConditionUse); InductiveRangeCheck() : Offset(nullptr), Scale(nullptr), Length(nullptr), @@ -313,14 +312,17 @@ InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI, llvm_unreachable("default clause returns!"); } -/// Parses an arbitrary condition into a range check. `Length` is set only if -/// the range check is recognized to be `RANGE_CHECK_UPPER` or stronger. -InductiveRangeCheck::RangeCheckKind -InductiveRangeCheck::parseRangeCheck(Loop *L, ScalarEvolution &SE, - Value *Condition, Value *&Index, - Value *&Length) { +/// Parses an arbitrary condition into an inductive range check. +Optional<InductiveRangeCheck> +InductiveRangeCheck::parseRangeCheckFromCond(Loop *L, ScalarEvolution &SE, + Use &ConditionUse) { using namespace llvm::PatternMatch; + Value *Condition = ConditionUse.get(); + + Value *Length, *Index; + InductiveRangeCheck::RangeCheckKind RCKind; + Value *A = nullptr; Value *B = nullptr; @@ -330,31 +332,42 @@ InductiveRangeCheck::parseRangeCheck(Loop *L, ScalarEvolution &SE, ICmpInst *ICmpA = dyn_cast<ICmpInst>(A), *ICmpB = dyn_cast<ICmpInst>(B); if (!ICmpA || !ICmpB) - return InductiveRangeCheck::RANGE_CHECK_UNKNOWN; + return None; auto RCKindA = parseRangeCheckICmp(L, ICmpA, SE, IndexA, LengthA); auto RCKindB = parseRangeCheckICmp(L, ICmpB, SE, IndexB, LengthB); if (RCKindA == InductiveRangeCheck::RANGE_CHECK_UNKNOWN || - RCKindB == InductiveRangeCheck::RANGE_CHECK_UNKNOWN) - return InductiveRangeCheck::RANGE_CHECK_UNKNOWN; - - if (IndexA != IndexB) - return InductiveRangeCheck::RANGE_CHECK_UNKNOWN; - - if (LengthA != nullptr && LengthB != nullptr && LengthA != LengthB) - return InductiveRangeCheck::RANGE_CHECK_UNKNOWN; + RCKindB == InductiveRangeCheck::RANGE_CHECK_UNKNOWN || + IndexA != IndexB || + (LengthA != nullptr && LengthB != nullptr && LengthA != LengthB)) + return None; Index = IndexA; Length = LengthA == nullptr ? LengthB : LengthA; - - return (InductiveRangeCheck::RangeCheckKind)(RCKindA | RCKindB); + RCKind = (InductiveRangeCheck::RangeCheckKind)(RCKindA | RCKindB); + } else if (ICmpInst *ICI = dyn_cast<ICmpInst>(Condition)) { + RCKind = parseRangeCheckICmp(L, ICI, SE, Index, Length); + if (RCKind == InductiveRangeCheck::RANGE_CHECK_UNKNOWN) + return None; + } else { + return None; } - if (ICmpInst *ICI = dyn_cast<ICmpInst>(Condition)) - return parseRangeCheckICmp(L, ICI, SE, Index, Length); + const auto *IndexAddRec = dyn_cast<SCEVAddRecExpr>(SE.getSCEV(Index)); + bool IsAffineIndex = + IndexAddRec && (IndexAddRec->getLoop() == L) && IndexAddRec->isAffine(); + + if (!IsAffineIndex) + return None; - return InductiveRangeCheck::RANGE_CHECK_UNKNOWN; + InductiveRangeCheck IRC; + IRC.Length = Length; + IRC.Offset = IndexAddRec->getStart(); + IRC.Scale = IndexAddRec->getStepRecurrence(SE); + IRC.CheckUse = &ConditionUse; + IRC.Kind = RCKind; + return IRC; } Optional<InductiveRangeCheck> @@ -366,35 +379,11 @@ InductiveRangeCheck::create(BranchInst *BI, Loop *L, ScalarEvolution &SE, BranchProbability LikelyTaken(15, 16); - if (BPI.getEdgeProbability(BI->getParent(), (unsigned) 0) < LikelyTaken) + if (BPI.getEdgeProbability(BI->getParent(), (unsigned)0) < LikelyTaken) return None; - Value *Length = nullptr, *Index = nullptr; - - auto RCKind = InductiveRangeCheck::parseRangeCheck(L, SE, BI->getCondition(), - Index, Length); - - if (RCKind == InductiveRangeCheck::RANGE_CHECK_UNKNOWN) - return None; - - assert(Index && "contract with parseRangeCheck!"); - assert((!(RCKind & InductiveRangeCheck::RANGE_CHECK_UPPER) || Length) && - "contract with parseRangeCheck!"); - - const auto *IndexAddRec = dyn_cast<SCEVAddRecExpr>(SE.getSCEV(Index)); - bool IsAffineIndex = - IndexAddRec && (IndexAddRec->getLoop() == L) && IndexAddRec->isAffine(); - - if (!IsAffineIndex) - return None; - - InductiveRangeCheck IRC; - IRC.Length = Length; - IRC.Offset = IndexAddRec->getStart(); - IRC.Scale = IndexAddRec->getStepRecurrence(SE); - IRC.CheckUse = &BI->getOperandUse(0); - IRC.Kind = RCKind; - return IRC; + return InductiveRangeCheck::parseRangeCheckFromCond(L, SE, + BI->getOperandUse(0)); } namespace { |