diff options
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/IPO/InlineAlways.cpp | 28 | ||||
| -rw-r--r-- | llvm/lib/Transforms/IPO/InlineSimple.cpp | 16 | ||||
| -rw-r--r-- | llvm/lib/Transforms/IPO/Inliner.cpp | 40 | 
3 files changed, 50 insertions, 34 deletions
| diff --git a/llvm/lib/Transforms/IPO/InlineAlways.cpp b/llvm/lib/Transforms/IPO/InlineAlways.cpp index 749a3fa23de..3c7fac6cc10 100644 --- a/llvm/lib/Transforms/IPO/InlineAlways.cpp +++ b/llvm/lib/Transforms/IPO/InlineAlways.cpp @@ -32,8 +32,6 @@ namespace {    // AlwaysInliner only inlines functions that are mark as "always inline".    class AlwaysInliner : public Inliner { -    // Functions that are never inlined -    SmallPtrSet<const Function*, 16> NeverInline;      InlineCostAnalyzer CA;    public:      // Use extremely low threshold. @@ -46,7 +44,22 @@ namespace {      }      static char ID; // Pass identification, replacement for typeid      InlineCost getInlineCost(CallSite CS) { -      return CA.getInlineCost(CS, NeverInline); +      Function *Callee = CS.getCalledFunction(); +      // We assume indirect calls aren't calling an always-inline function. +      if (!Callee) return InlineCost::getNever(); + +      // We can't inline calls to external functions. +      // FIXME: We shouldn't even get here. +      if (Callee->isDeclaration()) return InlineCost::getNever(); + +      // Return never for anything not marked as always inline. +      if (!Callee->hasFnAttr(Attribute::AlwaysInline)) +        return InlineCost::getNever(); + +      // We still have to check the inline cost in case there are reasons to +      // not inline which trump the always-inline attribute such as setjmp and +      // indirectbr. +      return CA.getInlineCost(CS);      }      float getInlineFudgeFactor(CallSite CS) {        return CA.getInlineFudgeFactor(CS); @@ -58,7 +71,7 @@ namespace {        CA.growCachedCostInfo(Caller, Callee);      }      virtual bool doFinalization(CallGraph &CG) { -      return removeDeadFunctions(CG, &NeverInline); +      return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/true);      }      virtual bool doInitialization(CallGraph &CG);      void releaseMemory() { @@ -84,12 +97,5 @@ Pass *llvm::createAlwaysInlinerPass(bool InsertLifetime) {  // been annotated with the "always inline" attribute.  bool AlwaysInliner::doInitialization(CallGraph &CG) {    CA.setTargetData(getAnalysisIfAvailable<TargetData>()); - -  Module &M = CG.getModule(); - -  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) -    if (!I->isDeclaration() && !I->hasFnAttr(Attribute::AlwaysInline)) -      NeverInline.insert(I); -    return false;  } diff --git a/llvm/lib/Transforms/IPO/InlineSimple.cpp b/llvm/lib/Transforms/IPO/InlineSimple.cpp index b3421ebd648..a7aeed8afc3 100644 --- a/llvm/lib/Transforms/IPO/InlineSimple.cpp +++ b/llvm/lib/Transforms/IPO/InlineSimple.cpp @@ -43,7 +43,16 @@ namespace {      }      static char ID; // Pass identification, replacement for typeid      InlineCost getInlineCost(CallSite CS) { -      return CA.getInlineCost(CS, NeverInline); +      // Filter out functions which should never be inlined due to the global +      // 'llvm.noinline'. +      // FIXME: I'm 99% certain that this is an ancient bit of legacy that we +      // no longer need to support, but I don't want to blindly nuke it just +      // yet. +      if (Function *Callee = CS.getCalledFunction()) +        if (NeverInline.count(Callee)) +          return InlineCost::getNever(); + +      return CA.getInlineCost(CS);      }      float getInlineFudgeFactor(CallSite CS) {        return CA.getInlineFudgeFactor(CS); @@ -81,11 +90,6 @@ bool SimpleInliner::doInitialization(CallGraph &CG) {    Module &M = CG.getModule(); -  for (Module::iterator I = M.begin(), E = M.end(); -       I != E; ++I) -    if (!I->isDeclaration() && I->hasFnAttr(Attribute::NoInline)) -      NeverInline.insert(I); -    // Get llvm.noinline    GlobalVariable *GV = M.getNamedGlobal("llvm.noinline"); diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp index 49042f2493f..9975333976d 100644 --- a/llvm/lib/Transforms/IPO/Inliner.cpp +++ b/llvm/lib/Transforms/IPO/Inliner.cpp @@ -556,25 +556,27 @@ bool Inliner::doFinalization(CallGraph &CG) {  /// removeDeadFunctions - Remove dead functions that are not included in  /// DNR (Do Not Remove) list. -bool Inliner::removeDeadFunctions(CallGraph &CG,  -                                  SmallPtrSet<const Function *, 16> *DNR) { -  SmallPtrSet<CallGraphNode*, 16> FunctionsToRemove; +bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) { +  SmallVector<CallGraphNode*, 16> FunctionsToRemove;    // Scan for all of the functions, looking for ones that should now be removed    // from the program.  Insert the dead ones in the FunctionsToRemove set.    for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) {      CallGraphNode *CGN = I->second; -    if (CGN->getFunction() == 0) -      continue; -          Function *F = CGN->getFunction(); -     +    if (!F || F->isDeclaration()) +      continue; + +    // Handle the case when this function is called and we only want to care +    // about always-inline functions. This is a bit of a hack to share code +    // between here and the InlineAlways pass. +    if (AlwaysInlineOnly && !F->hasFnAttr(Attribute::AlwaysInline)) +      continue; +      // If the only remaining users of the function are dead constants, remove      // them.      F->removeDeadConstantUsers(); -    if (DNR && DNR->count(F)) -      continue;      if (!F->isDefTriviallyDead())        continue; @@ -587,24 +589,28 @@ bool Inliner::removeDeadFunctions(CallGraph &CG,      CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN);      // Removing the node for callee from the call graph and delete it. -    FunctionsToRemove.insert(CGN); +    FunctionsToRemove.push_back(CGN);    } +  if (FunctionsToRemove.empty()) +    return false;    // Now that we know which functions to delete, do so.  We didn't want to do    // this inline, because that would invalidate our CallGraph::iterator    // objects. :(    // -  // Note that it doesn't matter that we are iterating over a non-stable set +  // Note that it doesn't matter that we are iterating over a non-stable order    // here to do this, it doesn't matter which order the functions are deleted    // in. -  bool Changed = false; -  for (SmallPtrSet<CallGraphNode*, 16>::iterator I = FunctionsToRemove.begin(), -       E = FunctionsToRemove.end(); I != E; ++I) { +  std::sort(FunctionsToRemove.begin(), FunctionsToRemove.end()); +  FunctionsToRemove.erase(std::unique(FunctionsToRemove.begin(), +                                      FunctionsToRemove.end()), +                          FunctionsToRemove.end()); +  for (SmallVectorImpl<CallGraphNode *>::iterator I = FunctionsToRemove.begin(), +                                                  E = FunctionsToRemove.end(); +       I != E; ++I) {      resetCachedCostInfo((*I)->getFunction());      delete CG.removeFunctionFromModule(*I);      ++NumDeleted; -    Changed = true;    } - -  return Changed; +  return true;  } | 

