[llvm] 51d334a - [NFCI] Lazily evaluate SCEVs of PHIs
Max Kazantsev via llvm-commits
llvm-commits at lists.llvm.org
Wed May 26 23:36:20 PDT 2021
Author: Max Kazantsev
Date: 2021-05-27T13:35:31+07:00
New Revision: 51d334a845a082338735b0fdfc620a4b15fa26fe
URL: https://github.com/llvm/llvm-project/commit/51d334a845a082338735b0fdfc620a4b15fa26fe
DIFF: https://github.com/llvm/llvm-project/commit/51d334a845a082338735b0fdfc620a4b15fa26fe.diff
LOG: [NFCI] Lazily evaluate SCEVs of PHIs
Eager evaluation has cost of compile time. Only query them if they are
required for proving predicates.
Added:
Modified:
llvm/lib/Transforms/Scalar/LoopDeletion.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index cd2a3fc48e3b..ed6b078fcf8e 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -136,30 +136,88 @@ static bool isLoopNeverExecuted(Loop *L) {
return true;
}
+BasicBlock *
+getSolePredecessorOnFirstIteration(BasicBlock *BB, Loop *L,
+ const DenseSet<BasicBlockEdge> &LiveEdges) {
+ if (BB == L->getHeader())
+ return L->getLoopPredecessor();
+ BasicBlock *OnlyPred = nullptr;
+ for (auto *Pred : predecessors(BB))
+ if (OnlyPred != Pred && LiveEdges.count({ Pred, BB })) {
+ // 2 live preds.
+ if (OnlyPred)
+ return nullptr;
+ OnlyPred = Pred;
+ }
+
+ assert(OnlyPred && "No live predecessors?");
+ return OnlyPred;
+}
+
+// Forward declaration.
+static const SCEV *
+getSCEVOnFirstIteration(Value *V, Loop *L, DominatorTree &DT,
+ ScalarEvolution &SE,
+ DenseMap<Value *, const SCEV *> &FirstIterSCEV,
+ const DenseSet<BasicBlockEdge> &LiveEdges);
+
static const SCEV *
-getSCEVOnFirstIteration(Value *V, Loop *L, ScalarEvolution &SE,
- DenseMap<Value *, const SCEV *> &FirstIterSCEV) {
+getPHISCEVOnFirstIteration(PHINode *PN, Loop *L, DominatorTree &DT,
+ ScalarEvolution &SE,
+ DenseMap<Value *, const SCEV *> &FirstIterSCEV,
+ const DenseSet<BasicBlockEdge> &LiveEdges) {
+ auto *BB = PN->getParent();
+ if (!L->contains(PN))
+ return SE.getSCEV(PN);
+ // If this block has only one live pred, map its phis onto their SCEVs.
+ // Check if there is only one predecessor on 1st iteration. Note that because
+ // we iterate in RPOT, we have already visited all its (non-latch)
+ // predecessors.
+ auto *OnlyPred = getSolePredecessorOnFirstIteration(BB, L, LiveEdges);
+ if (!OnlyPred)
+ return SE.getSCEV(PN);
+ auto *Incoming = PN->getIncomingValueForBlock(OnlyPred);
+ if (DT.dominates(Incoming, BB->getTerminator()))
+ return getSCEVOnFirstIteration(Incoming, L, DT, SE, FirstIterSCEV,
+ LiveEdges);
+ return SE.getSCEV(PN);
+}
+
+static const SCEV *
+getSCEVOnFirstIteration(Value *V, Loop *L, DominatorTree &DT,
+ ScalarEvolution &SE,
+ DenseMap<Value *, const SCEV *> &FirstIterSCEV,
+ const DenseSet<BasicBlockEdge> &LiveEdges) {
// Fist, check in cache.
auto Existing = FirstIterSCEV.find(V);
if (Existing != FirstIterSCEV.end())
return Existing->second;
+
const SCEV *S = nullptr;
// TODO: Once ScalarEvolution supports getValueOnNthIteration for anything
// else but AddRecs, it's a good use case for it. So far, just consider some
// simple cases, like arithmetic operations.
Value *LHS, *RHS;
using namespace PatternMatch;
- if (match(V, m_Add(m_Value(LHS), m_Value(RHS)))) {
- const SCEV *LHSS = getSCEVOnFirstIteration(LHS, L, SE, FirstIterSCEV);
- const SCEV *RHSS = getSCEVOnFirstIteration(RHS, L, SE, FirstIterSCEV);
+ if (auto *PN = dyn_cast<PHINode>(V)) {
+ S = getPHISCEVOnFirstIteration(PN, L, DT, SE, FirstIterSCEV, LiveEdges);
+ } else if (match(V, m_Add(m_Value(LHS), m_Value(RHS)))) {
+ const SCEV *LHSS =
+ getSCEVOnFirstIteration(LHS, L, DT, SE, FirstIterSCEV, LiveEdges);
+ const SCEV *RHSS =
+ getSCEVOnFirstIteration(RHS, L, DT, SE, FirstIterSCEV, LiveEdges);
S = SE.getAddExpr(LHSS, RHSS);
} else if (match(V, m_Sub(m_Value(LHS), m_Value(RHS)))) {
- const SCEV *LHSS = getSCEVOnFirstIteration(LHS, L, SE, FirstIterSCEV);
- const SCEV *RHSS = getSCEVOnFirstIteration(RHS, L, SE, FirstIterSCEV);
+ const SCEV *LHSS =
+ getSCEVOnFirstIteration(LHS, L, DT, SE, FirstIterSCEV, LiveEdges);
+ const SCEV *RHSS =
+ getSCEVOnFirstIteration(RHS, L, DT, SE, FirstIterSCEV, LiveEdges);
S = SE.getMinusSCEV(LHSS, RHSS);
} else if (match(V, m_Mul(m_Value(LHS), m_Value(RHS)))) {
- const SCEV *LHSS = getSCEVOnFirstIteration(LHS, L, SE, FirstIterSCEV);
- const SCEV *RHSS = getSCEVOnFirstIteration(RHS, L, SE, FirstIterSCEV);
+ const SCEV *LHSS =
+ getSCEVOnFirstIteration(LHS, L, DT, SE, FirstIterSCEV, LiveEdges);
+ const SCEV *RHSS =
+ getSCEVOnFirstIteration(RHS, L, DT, SE, FirstIterSCEV, LiveEdges);
S = SE.getMulExpr(LHSS, RHSS);
} else
S = SE.getSCEV(V);
@@ -185,7 +243,7 @@ static bool canProveExitOnFirstIteration(Loop *L, DominatorTree &DT,
SmallPtrSet<BasicBlock *, 4> LiveBlocks;
// Edges that are reachable on the 1st iteration.
DenseSet<BasicBlockEdge> LiveEdges;
- LiveBlocks.insert(L->getHeader());
+ LiveBlocks.insert(Header);
auto MarkLiveEdge = [&](BasicBlock *From, BasicBlock *To) {
assert(LiveBlocks.count(From) && "Must be live!");
@@ -198,24 +256,6 @@ static bool canProveExitOnFirstIteration(Loop *L, DominatorTree &DT,
MarkLiveEdge(BB, Succ);
};
- // Check if there is only one predecessor on 1st iteration. Note that because
- // we iterate in RPOT, we have already visited all its (non-latch)
- // predecessors.
- auto GetSolePredecessorOnFirstIteration = [&](BasicBlock * BB)->BasicBlock * {
- if (BB == Header)
- return L->getLoopPredecessor();
- BasicBlock *OnlyPred = nullptr;
- for (auto *Pred : predecessors(BB))
- if (OnlyPred != Pred && LiveEdges.count({ Pred, BB })) {
- // 2 live preds.
- if (OnlyPred)
- return nullptr;
- OnlyPred = Pred;
- }
-
- assert(OnlyPred && "No live predecessors?");
- return OnlyPred;
- };
DenseMap<Value *, const SCEV *> FirstIterSCEV;
SmallPtrSet<BasicBlock *, 4> Visited;
@@ -250,19 +290,6 @@ static bool canProveExitOnFirstIteration(Loop *L, DominatorTree &DT,
if (!Visited.count(Pred))
return false;
- // If this block has only one live pred, map its phis onto their SCEVs.
- if (auto *OnlyPred = GetSolePredecessorOnFirstIteration(BB))
- for (auto &PN : BB->phis()) {
- if (!SE.isSCEVable(PN.getType()))
- continue;
- auto *Incoming = PN.getIncomingValueForBlock(OnlyPred);
- if (DT.dominates(Incoming, BB->getTerminator())) {
- const SCEV *IncSCEV =
- getSCEVOnFirstIteration(Incoming, L, SE, FirstIterSCEV);
- FirstIterSCEV[&PN] = IncSCEV;
- }
- }
-
using namespace PatternMatch;
ICmpInst::Predicate Pred;
Value *LHS, *RHS;
@@ -281,8 +308,10 @@ static bool canProveExitOnFirstIteration(Loop *L, DominatorTree &DT,
}
// Can we prove constant true or false for this condition?
- const SCEV *LHSS = getSCEVOnFirstIteration(LHS, L, SE, FirstIterSCEV);
- const SCEV *RHSS = getSCEVOnFirstIteration(RHS, L, SE, FirstIterSCEV);
+ const SCEV *LHSS =
+ getSCEVOnFirstIteration(LHS, L, DT, SE, FirstIterSCEV, LiveEdges);
+ const SCEV *RHSS =
+ getSCEVOnFirstIteration(RHS, L, DT, SE, FirstIterSCEV, LiveEdges);
// Only query for liveness of in-loop edge if another successor is also
// in-loop.
// TODO: isKnownPredicateAt is more powerful, but it's too compile time
More information about the llvm-commits
mailing list