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 @@ -64,6 +64,7 @@ #include "llvm/Transforms/Utils/ModuleUtils.h" #include #include +#include #include #include #include @@ -670,40 +671,55 @@ return *IAA->getAdvisor(); } -class InlineOrder { +template class InlineOrder { public: - using T = std::pair; - using iterator = T *; - using const_iterator = const T *; - using reference = T &; + using iterator = typename Container::iterator; + using const_iterator = typename Container::const_iterator; + using reference = typename Container::reference; virtual ~InlineOrder() {} virtual size_t size() = 0; - virtual reference operator[](size_t idx) = 0; - virtual void push_back(const T &Elt) = 0; - virtual T pop() = 0; + + virtual void push(const T &Elt) = 0; + + virtual void pop() = 0; + + virtual reference front() = 0; + virtual iterator erase(const_iterator B, const_iterator E) = 0; + virtual iterator begin() = 0; virtual iterator end() = 0; bool empty() { return !size(); } }; -class DefaultInlineOrder : public InlineOrder { +template > +class DefaultInlineOrder : public InlineOrder { + using Base = InlineOrder; + using iterator = typename Base::iterator; + using const_iterator = typename Base::const_iterator; + using reference = typename Base::reference; + public: size_t size() override { return Calls.size(); } - reference operator[](size_t idx) override { return Calls[idx]; } - void push_back(const T &Elt) override { Calls.push_back(Elt); } - T pop() override { return Calls.pop_back_val(); } + + void push(const T &Elt) override { Calls.push_back(Elt); } + + void pop() override { Calls.pop_front(); } + + reference front() override { return Calls.front(); } + iterator erase(const_iterator CB, const_iterator CE) override { return Calls.erase(CB, CE); } + iterator begin() override { return Calls.begin(); } iterator end() override { return Calls.end(); } private: - SmallVector Calls; + Container Calls; }; PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, @@ -750,7 +766,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; + DefaultInlineOrder> Calls; // Populate the initial list of calls in this SCC. for (auto &N : InitialC) { @@ -765,7 +781,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"); @@ -802,12 +818,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. - 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 // 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) continue; @@ -824,8 +840,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(); @@ -895,7 +912,7 @@ } if (NewCallee) if (!NewCallee->isDeclaration()) - Calls.push_back({ICB, NewHistoryID}); + Calls.push({ICB, NewHistoryID}); } } @@ -913,7 +930,7 @@ Callee.removeDeadConstantUsers(); if (Callee.use_empty() && !CG.isLibFunction(Callee)) { Calls.erase( - std::remove_if(Calls.begin() + I + 1, Calls.end(), + std::remove_if(Calls.begin(), Calls.end(), [&](const std::pair &Call) { return Call.first->getCaller() == &Callee; }), @@ -935,10 +952,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;