diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -670,6 +670,54 @@ return *IAA->getAdvisor(); } +template 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 Pred) = 0; + + bool empty() { return !size(); } +}; + +template > +class DefaultInlineOrder : public InlineOrder { + 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 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 @@ // 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, 16> Calls; + DefaultInlineOrder> Calls; // Populate the initial list of calls in this SCC. for (auto &N : InitialC) { @@ -729,7 +777,7 @@ if (auto *CB = dyn_cast(&I)) if (Function *Callee = CB->getCalledFunction()) { if (!Callee->isDeclaration()) - Calls.push_back({CB, -1}); + Calls.push({CB, -1}); else if (!isa(I)) { using namespace ore; setInlineRemark(*CB, "unavailable definition"); @@ -764,17 +812,18 @@ // defer deleting these to make it easier to handle the call graph updates. SmallVector 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 @@ // 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 @@ } if (NewCallee) if (!NewCallee->isDeclaration()) - Calls.push_back({ICB, NewHistoryID}); + Calls.push({ICB, NewHistoryID}); } } @@ -876,12 +926,9 @@ // 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 &Call) { - return Call.first->getCaller() == &Callee; - }), - Calls.end()); + Calls.erase_if([&](const std::pair &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 @@ 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;