Home | History | Annotate | Download | only in IPO
      1 //===- InlineAlways.cpp - Code to inline always_inline functions ----------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements a custom inliner that handles only functions that
     11 // are marked as "always inline".
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #define DEBUG_TYPE "inline"
     16 #include "llvm/CallingConv.h"
     17 #include "llvm/Instructions.h"
     18 #include "llvm/IntrinsicInst.h"
     19 #include "llvm/Module.h"
     20 #include "llvm/Type.h"
     21 #include "llvm/Analysis/CallGraph.h"
     22 #include "llvm/Analysis/InlineCost.h"
     23 #include "llvm/Support/CallSite.h"
     24 #include "llvm/Transforms/IPO.h"
     25 #include "llvm/Transforms/IPO/InlinerPass.h"
     26 #include "llvm/ADT/SmallPtrSet.h"
     27 
     28 using namespace llvm;
     29 
     30 namespace {
     31 
     32   // AlwaysInliner only inlines functions that are mark as "always inline".
     33   class AlwaysInliner : public Inliner {
     34     // Functions that are never inlined
     35     SmallPtrSet<const Function*, 16> NeverInline;
     36     InlineCostAnalyzer CA;
     37   public:
     38     // Use extremely low threshold.
     39     AlwaysInliner() : Inliner(ID, -2000000000) {
     40       initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
     41     }
     42     static char ID; // Pass identification, replacement for typeid
     43     InlineCost getInlineCost(CallSite CS) {
     44       return CA.getInlineCost(CS, NeverInline);
     45     }
     46     float getInlineFudgeFactor(CallSite CS) {
     47       return CA.getInlineFudgeFactor(CS);
     48     }
     49     void resetCachedCostInfo(Function *Caller) {
     50       CA.resetCachedCostInfo(Caller);
     51     }
     52     void growCachedCostInfo(Function* Caller, Function* Callee) {
     53       CA.growCachedCostInfo(Caller, Callee);
     54     }
     55     virtual bool doFinalization(CallGraph &CG) {
     56       return removeDeadFunctions(CG, &NeverInline);
     57     }
     58     virtual bool doInitialization(CallGraph &CG);
     59     void releaseMemory() {
     60       CA.clear();
     61     }
     62   };
     63 }
     64 
     65 char AlwaysInliner::ID = 0;
     66 INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
     67                 "Inliner for always_inline functions", false, false)
     68 INITIALIZE_AG_DEPENDENCY(CallGraph)
     69 INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
     70                 "Inliner for always_inline functions", false, false)
     71 
     72 Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); }
     73 
     74 // doInitialization - Initializes the vector of functions that have not
     75 // been annotated with the "always inline" attribute.
     76 bool AlwaysInliner::doInitialization(CallGraph &CG) {
     77   Module &M = CG.getModule();
     78 
     79   for (Module::iterator I = M.begin(), E = M.end();
     80        I != E; ++I)
     81     if (!I->isDeclaration() && !I->hasFnAttr(Attribute::AlwaysInline))
     82       NeverInline.insert(I);
     83 
     84   return false;
     85 }
     86