forked from OSchip/llvm-project
[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, i.e. use queue or priority queue. Reviewed By: kazu Differential Revision: https://reviews.llvm.org/D103315
This commit is contained in:
parent
551a697c5c
commit
478dc47292
|
@ -670,6 +670,54 @@ InlinerPass::getAdvisor(const ModuleAnalysisManagerCGSCCProxy::Result &MAM,
|
||||||
return *IAA->getAdvisor();
|
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.end() - Calls.begin() - FirstIndex; }
|
||||||
|
|
||||||
|
void push(const T &Elt) override { Calls.push_back(Elt); }
|
||||||
|
|
||||||
|
void pop() override {
|
||||||
|
assert(size() > 0);
|
||||||
|
FirstIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
reference front() override {
|
||||||
|
assert(Calls.begin() + FirstIndex < Calls.end());
|
||||||
|
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,
|
PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
||||||
CGSCCAnalysisManager &AM, LazyCallGraph &CG,
|
CGSCCAnalysisManager &AM, LazyCallGraph &CG,
|
||||||
CGSCCUpdateResult &UR) {
|
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
|
// 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
|
// and eventually they all become too large to inline, rather than
|
||||||
// incrementally maknig a single function grow in a super linear fashion.
|
// 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.
|
// Populate the initial list of calls in this SCC.
|
||||||
for (auto &N : InitialC) {
|
for (auto &N : InitialC) {
|
||||||
|
@ -729,7 +777,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
||||||
if (auto *CB = dyn_cast<CallBase>(&I))
|
if (auto *CB = dyn_cast<CallBase>(&I))
|
||||||
if (Function *Callee = CB->getCalledFunction()) {
|
if (Function *Callee = CB->getCalledFunction()) {
|
||||||
if (!Callee->isDeclaration())
|
if (!Callee->isDeclaration())
|
||||||
Calls.push_back({CB, -1});
|
Calls.push({CB, -1});
|
||||||
else if (!isa<IntrinsicInst>(I)) {
|
else if (!isa<IntrinsicInst>(I)) {
|
||||||
using namespace ore;
|
using namespace ore;
|
||||||
setInlineRemark(*CB, "unavailable definition");
|
setInlineRemark(*CB, "unavailable definition");
|
||||||
|
@ -766,12 +814,12 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
||||||
|
|
||||||
// Loop forward over all of the calls. Note that we cannot cache the size as
|
// 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.
|
// inlining can introduce new calls that need to be processed.
|
||||||
for (int I = 0; I < (int)Calls.size(); ++I) {
|
while (!Calls.empty()) {
|
||||||
// We expect the calls to typically be batched with sequences of calls that
|
// 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
|
// 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
|
// this caller. We also do any pruning we can at this layer on the caller
|
||||||
// alone.
|
// alone.
|
||||||
Function &F = *Calls[I].first->getCaller();
|
Function &F = *(Calls.front()).first->getCaller();
|
||||||
LazyCallGraph::Node &N = *CG.lookup(F);
|
LazyCallGraph::Node &N = *CG.lookup(F);
|
||||||
if (CG.lookupSCC(N) != C)
|
if (CG.lookupSCC(N) != C)
|
||||||
continue;
|
continue;
|
||||||
|
@ -788,8 +836,9 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
||||||
// We bail out as soon as the caller has to change so we can update the
|
// 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.
|
// call graph and prepare the context of that new caller.
|
||||||
bool DidInline = false;
|
bool DidInline = false;
|
||||||
for (; I < (int)Calls.size() && Calls[I].first->getCaller() == &F; ++I) {
|
while (!Calls.empty() && Calls.front().first->getCaller() == &F) {
|
||||||
auto &P = Calls[I];
|
auto &P = Calls.front();
|
||||||
|
Calls.pop();
|
||||||
CallBase *CB = P.first;
|
CallBase *CB = P.first;
|
||||||
const int InlineHistoryID = P.second;
|
const int InlineHistoryID = P.second;
|
||||||
Function &Callee = *CB->getCalledFunction();
|
Function &Callee = *CB->getCalledFunction();
|
||||||
|
@ -859,7 +908,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
||||||
}
|
}
|
||||||
if (NewCallee)
|
if (NewCallee)
|
||||||
if (!NewCallee->isDeclaration())
|
if (!NewCallee->isDeclaration())
|
||||||
Calls.push_back({ICB, NewHistoryID});
|
Calls.push({ICB, NewHistoryID});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,12 +925,9 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
||||||
// made dead by this operation on other functions).
|
// made dead by this operation on other functions).
|
||||||
Callee.removeDeadConstantUsers();
|
Callee.removeDeadConstantUsers();
|
||||||
if (Callee.use_empty() && !CG.isLibFunction(Callee)) {
|
if (Callee.use_empty() && !CG.isLibFunction(Callee)) {
|
||||||
Calls.erase(
|
Calls.erase_if([&](const std::pair<CallBase *, int> &Call) {
|
||||||
std::remove_if(Calls.begin() + I + 1, Calls.end(),
|
return Call.first->getCaller() == &Callee;
|
||||||
[&](const std::pair<CallBase *, int> &Call) {
|
});
|
||||||
return Call.first->getCaller() == &Callee;
|
|
||||||
}),
|
|
||||||
Calls.end());
|
|
||||||
// Clear the body and queue the function itself for deletion when we
|
// Clear the body and queue the function itself for deletion when we
|
||||||
// finish inlining and call graph updates.
|
// finish inlining and call graph updates.
|
||||||
// Note that after this point, it is an error to do anything other
|
// Note that after this point, it is an error to do anything other
|
||||||
|
@ -899,10 +945,6 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
||||||
Advice->recordInlining();
|
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)
|
if (!DidInline)
|
||||||
continue;
|
continue;
|
||||||
Changed = true;
|
Changed = true;
|
||||||
|
|
Loading…
Reference in New Issue