summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp120
1 files changed, 69 insertions, 51 deletions
diff --git a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
index cfefcb8cd5d..06f564b4034 100644
--- a/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp
@@ -125,8 +125,10 @@ class InductiveRangeCheck {
ScalarEvolution &SE, Value *&Index,
Value *&Length);
- static Optional<InductiveRangeCheck>
- parseRangeCheckFromCond(Loop *L, ScalarEvolution &SE, Use &ConditionUse);
+ static void
+ extractRangeChecksFromCond(Loop *L, ScalarEvolution &SE, Use &ConditionUse,
+ SmallVectorImpl<InductiveRangeCheck> &Checks,
+ SmallPtrSetImpl<Value *> &Visited);
InductiveRangeCheck()
: Offset(nullptr), Scale(nullptr), Length(nullptr),
@@ -189,10 +191,15 @@ public:
Optional<Range> computeSafeIterationSpace(ScalarEvolution &SE,
const SCEVAddRecExpr *IndVar) const;
- /// Create an inductive range check out of BI if possible, else return None.
- static Optional<InductiveRangeCheck> create(BranchInst *BI, Loop *L,
- ScalarEvolution &SE,
- BranchProbabilityInfo &BPI);
+ /// Parse out a set of inductive range checks from \p BI and append them to \p
+ /// Checks.
+ ///
+ /// NB! There may be conditions feeding into \p BI that aren't inductive range
+ /// checks, and hence don't end up in \p Checks.
+ static void
+ extractRangeChecksFromBranch(BranchInst *BI, Loop *L, ScalarEvolution &SE,
+ BranchProbabilityInfo &BPI,
+ SmallVectorImpl<InductiveRangeCheck> &Checks);
};
class InductiveRangeCheckElimination : public LoopPass {
@@ -312,54 +319,64 @@ InductiveRangeCheck::parseRangeCheckICmp(Loop *L, ICmpInst *ICI,
llvm_unreachable("default clause returns!");
}
-/// Parses an arbitrary condition into an inductive range check.
-Optional<InductiveRangeCheck>
-InductiveRangeCheck::parseRangeCheckFromCond(Loop *L, ScalarEvolution &SE,
- Use &ConditionUse) {
+void InductiveRangeCheck::extractRangeChecksFromCond(
+ Loop *L, ScalarEvolution &SE, Use &ConditionUse,
+ SmallVectorImpl<InductiveRangeCheck> &Checks,
+ SmallPtrSetImpl<Value *> &Visited) {
using namespace llvm::PatternMatch;
Value *Condition = ConditionUse.get();
+ if (!Visited.insert(Condition).second)
+ return;
- Value *Length, *Index;
- InductiveRangeCheck::RangeCheckKind RCKind;
-
- Value *A = nullptr;
- Value *B = nullptr;
-
- if (match(Condition, m_And(m_Value(A), m_Value(B)))) {
- Value *IndexA = nullptr, *IndexB = nullptr;
- Value *LengthA = nullptr, *LengthB = nullptr;
- ICmpInst *ICmpA = dyn_cast<ICmpInst>(A), *ICmpB = dyn_cast<ICmpInst>(B);
-
- if (!ICmpA || !ICmpB)
- return None;
+ if (match(Condition, m_And(m_Value(), m_Value()))) {
+ SmallVector<InductiveRangeCheck, 8> SubChecks;
+ extractRangeChecksFromCond(L, SE, cast<User>(Condition)->getOperandUse(0),
+ SubChecks, Visited);
+ extractRangeChecksFromCond(L, SE, cast<User>(Condition)->getOperandUse(1),
+ SubChecks, Visited);
+
+ if (SubChecks.size() == 2) {
+ // Handle a special case where we know how to merge two checks separately
+ // checking the upper and lower bounds into a full range check.
+ 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) {
+
+ // 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
+ // together they form a RANGE_CHECK_BOTH.
+ SubChecks[0].Kind =
+ (InductiveRangeCheck::RangeCheckKind)(RChkA.Kind | RChkB.Kind);
+ SubChecks[0].Length = RChkA.Length ? RChkA.Length : RChkB.Length;
+ SubChecks[0].CheckUse = &ConditionUse;
+
+ // We updated one of the checks in place, now erase the other.
+ SubChecks.pop_back();
+ }
+ }
- auto RCKindA = parseRangeCheckICmp(L, ICmpA, SE, IndexA, LengthA);
- auto RCKindB = parseRangeCheckICmp(L, ICmpB, SE, IndexB, LengthB);
+ Checks.insert(Checks.end(), SubChecks.begin(), SubChecks.end());
+ return;
+ }
- if (RCKindA == InductiveRangeCheck::RANGE_CHECK_UNKNOWN ||
- RCKindB == InductiveRangeCheck::RANGE_CHECK_UNKNOWN ||
- IndexA != IndexB ||
- (LengthA != nullptr && LengthB != nullptr && LengthA != LengthB))
- return None;
+ ICmpInst *ICI = dyn_cast<ICmpInst>(Condition);
+ if (!ICI)
+ return;
- Index = IndexA;
- Length = LengthA == nullptr ? LengthB : LengthA;
- 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;
- }
+ Value *Length = nullptr, *Index;
+ auto RCKind = parseRangeCheckICmp(L, ICI, SE, Index, Length);
+ if (RCKind == InductiveRangeCheck::RANGE_CHECK_UNKNOWN)
+ return;
const auto *IndexAddRec = dyn_cast<SCEVAddRecExpr>(SE.getSCEV(Index));
bool IsAffineIndex =
IndexAddRec && (IndexAddRec->getLoop() == L) && IndexAddRec->isAffine();
if (!IsAffineIndex)
- return None;
+ return;
InductiveRangeCheck IRC;
IRC.Length = Length;
@@ -367,23 +384,24 @@ InductiveRangeCheck::parseRangeCheckFromCond(Loop *L, ScalarEvolution &SE,
IRC.Scale = IndexAddRec->getStepRecurrence(SE);
IRC.CheckUse = &ConditionUse;
IRC.Kind = RCKind;
- return IRC;
+ Checks.push_back(IRC);
}
-Optional<InductiveRangeCheck>
-InductiveRangeCheck::create(BranchInst *BI, Loop *L, ScalarEvolution &SE,
- BranchProbabilityInfo &BPI) {
+void InductiveRangeCheck::extractRangeChecksFromBranch(
+ BranchInst *BI, Loop *L, ScalarEvolution &SE, BranchProbabilityInfo &BPI,
+ SmallVectorImpl<InductiveRangeCheck> &Checks) {
if (BI->isUnconditional() || BI->getParent() == L->getLoopLatch())
- return None;
+ return;
BranchProbability LikelyTaken(15, 16);
if (BPI.getEdgeProbability(BI->getParent(), (unsigned)0) < LikelyTaken)
- return None;
+ return;
- return InductiveRangeCheck::parseRangeCheckFromCond(L, SE,
- BI->getOperandUse(0));
+ SmallPtrSet<Value *, 8> Visited;
+ InductiveRangeCheck::extractRangeChecksFromCond(L, SE, BI->getOperandUse(0),
+ Checks, Visited);
}
namespace {
@@ -1370,8 +1388,8 @@ bool InductiveRangeCheckElimination::runOnLoop(Loop *L, LPPassManager &LPM) {
for (auto BBI : L->getBlocks())
if (BranchInst *TBI = dyn_cast<BranchInst>(BBI->getTerminator()))
- if (auto MaybeIRC = InductiveRangeCheck::create(TBI, L, SE, BPI))
- RangeChecks.push_back(*MaybeIRC);
+ InductiveRangeCheck::extractRangeChecksFromBranch(TBI, L, SE, BPI,
+ RangeChecks);
if (RangeChecks.empty())
return false;
OpenPOWER on IntegriCloud