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,54 +670,6 @@ 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.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 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) { @@ -762,7 +714,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. - DefaultInlineOrder> Calls; + SmallVector, 16> Calls; // Populate the initial list of calls in this SCC. for (auto &N : InitialC) { @@ -777,7 +729,7 @@ if (auto *CB = dyn_cast(&I)) if (Function *Callee = CB->getCalledFunction()) { if (!Callee->isDeclaration()) - Calls.push({CB, -1}); + Calls.push_back({CB, -1}); else if (!isa(I)) { using namespace ore; setInlineRemark(*CB, "unavailable definition"); @@ -814,12 +766,12 @@ // 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. - while (!Calls.empty()) { + for (int I = 0; I < (int)Calls.size(); ++I) { // 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.front()).first->getCaller(); + Function &F = *Calls[I].first->getCaller(); LazyCallGraph::Node &N = *CG.lookup(F); if (CG.lookupSCC(N) != C) continue; @@ -836,9 +788,8 @@ // 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; - while (!Calls.empty() && Calls.front().first->getCaller() == &F) { - auto &P = Calls.front(); - Calls.pop(); + for (; I < (int)Calls.size() && Calls[I].first->getCaller() == &F; ++I) { + auto &P = Calls[I]; CallBase *CB = P.first; const int InlineHistoryID = P.second; Function &Callee = *CB->getCalledFunction(); @@ -908,7 +859,7 @@ } if (NewCallee) if (!NewCallee->isDeclaration()) - Calls.push({ICB, NewHistoryID}); + Calls.push_back({ICB, NewHistoryID}); } } @@ -925,9 +876,12 @@ // made dead by this operation on other functions). Callee.removeDeadConstantUsers(); if (Callee.use_empty() && !CG.isLibFunction(Callee)) { - Calls.erase_if([&](const std::pair &Call) { - return Call.first->getCaller() == &Callee; - }); + Calls.erase( + std::remove_if(Calls.begin() + I + 1, Calls.end(), + [&](const std::pair &Call) { + return Call.first->getCaller() == &Callee; + }), + Calls.end()); // 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 @@ -945,6 +899,10 @@ 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;