[llvm] 4a0de62 - [llvm] Add interface to order inlining
Liqiang Tao via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 7 03:36:33 PDT 2021
Author: Liqiang Tao
Date: 2021-06-07T18:27:55+08:00
New Revision: 4a0de622c34e0cb86b22a8e5f38dfd388e07e2fc
URL: https://github.com/llvm/llvm-project/commit/4a0de622c34e0cb86b22a8e5f38dfd388e07e2fc
DIFF: https://github.com/llvm/llvm-project/commit/4a0de622c34e0cb86b22a8e5f38dfd388e07e2fc.diff
LOG: [llvm] Add interface to order inlining
This patch abstract Calls in Inliner:run() to InlineOrder.
With this patch, it's possible to customize the inlining order,
e.g. use queue or priority queue.
Reviewed By: kazu
Differential Revision: https://reviews.llvm.org/D103315
Added:
Modified:
llvm/lib/Transforms/IPO/Inliner.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp
index f0dbf3457c15c..38cf2fe30090d 100644
--- a/llvm/lib/Transforms/IPO/Inliner.cpp
+++ b/llvm/lib/Transforms/IPO/Inliner.cpp
@@ -670,6 +670,54 @@ InlinerPass::getAdvisor(const ModuleAnalysisManagerCGSCCProxy::Result &MAM,
return *IAA->getAdvisor();
}
+template <typename T> class InlineOrder {
+public:
+ using reference = T &;
+
+ virtual ~InlineOrder() {}
+
+ virtual size_t size() = 0;
+
+ virtual void push(const T &Elt) = 0;
+
+ virtual void pop() = 0;
+
+ virtual reference front() = 0;
+
+ virtual void erase_if(function_ref<bool(T)> Pred) = 0;
+
+ bool empty() { return !size(); }
+};
+
+template <typename T, typename Container = SmallVector<T, 16>>
+class DefaultInlineOrder : public InlineOrder<T> {
+ using reference = T &;
+
+public:
+ size_t size() override { return Calls.size() - FirstIndex; }
+
+ void push(const T &Elt) override { Calls.push_back(Elt); }
+
+ void pop() override {
+ assert(size() > 0);
+ FirstIndex++;
+ }
+
+ reference front() override {
+ assert(size() > 0);
+ return Calls[FirstIndex];
+ }
+
+ void erase_if(function_ref<bool(T)> Pred) override {
+ Calls.erase(std::remove_if(Calls.begin() + FirstIndex, Calls.end(), Pred),
+ Calls.end());
+ }
+
+private:
+ Container Calls;
+ size_t FirstIndex = 0;
+};
+
PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
CGSCCAnalysisManager &AM, LazyCallGraph &CG,
CGSCCUpdateResult &UR) {
@@ -714,7 +762,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
// this model, but it is uniformly spread across all the functions in the SCC
// and eventually they all become too large to inline, rather than
// incrementally maknig a single function grow in a super linear fashion.
- SmallVector<std::pair<CallBase *, int>, 16> Calls;
+ DefaultInlineOrder<std::pair<CallBase *, int>> Calls;
// Populate the initial list of calls in this SCC.
for (auto &N : InitialC) {
@@ -729,7 +777,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
if (auto *CB = dyn_cast<CallBase>(&I))
if (Function *Callee = CB->getCalledFunction()) {
if (!Callee->isDeclaration())
- Calls.push_back({CB, -1});
+ Calls.push({CB, -1});
else if (!isa<IntrinsicInst>(I)) {
using namespace ore;
setInlineRemark(*CB, "unavailable definition");
@@ -764,17 +812,18 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
// defer deleting these to make it easier to handle the call graph updates.
SmallVector<Function *, 4> DeadFunctions;
- // Loop forward over all of the calls. Note that we cannot cache the size as
- // inlining can introduce new calls that need to be processed.
- for (int I = 0; I < (int)Calls.size(); ++I) {
+ // Loop forward over all of the calls.
+ while (!Calls.empty()) {
// We expect the calls to typically be batched with sequences of calls that
// have the same caller, so we first set up some shared infrastructure for
// this caller. We also do any pruning we can at this layer on the caller
// alone.
- Function &F = *Calls[I].first->getCaller();
+ Function &F = *Calls.front().first->getCaller();
LazyCallGraph::Node &N = *CG.lookup(F);
- if (CG.lookupSCC(N) != C)
+ if (CG.lookupSCC(N) != C) {
+ Calls.pop();
continue;
+ }
LLVM_DEBUG(dbgs() << "Inlining calls in: " << F.getName() << "\n"
<< " Function size: " << F.getInstructionCount()
@@ -788,8 +837,9 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
// We bail out as soon as the caller has to change so we can update the
// call graph and prepare the context of that new caller.
bool DidInline = false;
- for (; I < (int)Calls.size() && Calls[I].first->getCaller() == &F; ++I) {
- auto &P = Calls[I];
+ while (!Calls.empty() && Calls.front().first->getCaller() == &F) {
+ auto &P = Calls.front();
+ Calls.pop();
CallBase *CB = P.first;
const int InlineHistoryID = P.second;
Function &Callee = *CB->getCalledFunction();
@@ -859,7 +909,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
}
if (NewCallee)
if (!NewCallee->isDeclaration())
- Calls.push_back({ICB, NewHistoryID});
+ Calls.push({ICB, NewHistoryID});
}
}
@@ -876,12 +926,9 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
// made dead by this operation on other functions).
Callee.removeDeadConstantUsers();
if (Callee.use_empty() && !CG.isLibFunction(Callee)) {
- Calls.erase(
- std::remove_if(Calls.begin() + I + 1, Calls.end(),
- [&](const std::pair<CallBase *, int> &Call) {
- return Call.first->getCaller() == &Callee;
- }),
- Calls.end());
+ Calls.erase_if([&](const std::pair<CallBase *, int> &Call) {
+ return Call.first->getCaller() == &Callee;
+ });
// Clear the body and queue the function itself for deletion when we
// finish inlining and call graph updates.
// Note that after this point, it is an error to do anything other
@@ -899,10 +946,6 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
Advice->recordInlining();
}
- // Back the call index up by one to put us in a good position to go around
- // the outer loop.
- --I;
-
if (!DidInline)
continue;
Changed = true;
More information about the llvm-commits
mailing list