Home | History | Annotate | Download | only in IPO
      1 //===- InlineSimple.cpp - Code to perform simple function inlining --------===//
      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 bottom-up inlining of functions into callees.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #define DEBUG_TYPE "inline"
     15 #include "llvm/CallingConv.h"
     16 #include "llvm/Instructions.h"
     17 #include "llvm/IntrinsicInst.h"
     18 #include "llvm/Module.h"
     19 #include "llvm/Type.h"
     20 #include "llvm/Analysis/CallGraph.h"
     21 #include "llvm/Analysis/InlineCost.h"
     22 #include "llvm/Support/CallSite.h"
     23 #include "llvm/Transforms/IPO.h"
     24 #include "llvm/Transforms/IPO/InlinerPass.h"
     25 #include "llvm/Target/TargetData.h"
     26 #include "llvm/ADT/SmallPtrSet.h"
     27 
     28 using namespace llvm;
     29 
     30 namespace {
     31 
     32   class SimpleInliner : public Inliner {
     33     // Functions that are never inlined
     34     SmallPtrSet<const Function*, 16> NeverInline;
     35     InlineCostAnalyzer CA;
     36   public:
     37     SimpleInliner() : Inliner(ID) {
     38       initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
     39     }
     40     SimpleInliner(int Threshold) : Inliner(ID, Threshold) {
     41       initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
     42     }
     43     static char ID; // Pass identification, replacement for typeid
     44     InlineCost getInlineCost(CallSite CS) {
     45       return CA.getInlineCost(CS, NeverInline);
     46     }
     47     float getInlineFudgeFactor(CallSite CS) {
     48       return CA.getInlineFudgeFactor(CS);
     49     }
     50     void resetCachedCostInfo(Function *Caller) {
     51       CA.resetCachedCostInfo(Caller);
     52     }
     53     void growCachedCostInfo(Function* Caller, Function* Callee) {
     54       CA.growCachedCostInfo(Caller, Callee);
     55     }
     56     virtual bool doInitialization(CallGraph &CG);
     57     void releaseMemory() {
     58       CA.clear();
     59     }
     60   };
     61 }
     62 
     63 char SimpleInliner::ID = 0;
     64 INITIALIZE_PASS_BEGIN(SimpleInliner, "inline",
     65                 "Function Integration/Inlining", false, false)
     66 INITIALIZE_AG_DEPENDENCY(CallGraph)
     67 INITIALIZE_PASS_END(SimpleInliner, "inline",
     68                 "Function Integration/Inlining", false, false)
     69 
     70 Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); }
     71 
     72 Pass *llvm::createFunctionInliningPass(int Threshold) {
     73   return new SimpleInliner(Threshold);
     74 }
     75 
     76 // doInitialization - Initializes the vector of functions that have been
     77 // annotated with the noinline attribute.
     78 bool SimpleInliner::doInitialization(CallGraph &CG) {
     79   CA.setTargetData(getAnalysisIfAvailable<TargetData>());
     80 
     81   Module &M = CG.getModule();
     82 
     83   for (Module::iterator I = M.begin(), E = M.end();
     84        I != E; ++I)
     85     if (!I->isDeclaration() && I->hasFnAttr(Attribute::NoInline))
     86       NeverInline.insert(I);
     87 
     88   // Get llvm.noinline
     89   GlobalVariable *GV = M.getNamedGlobal("llvm.noinline");
     90 
     91   if (GV == 0)
     92     return false;
     93 
     94   // Don't crash on invalid code
     95   if (!GV->hasDefinitiveInitializer())
     96     return false;
     97 
     98   const ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
     99 
    100   if (InitList == 0)
    101     return false;
    102 
    103   // Iterate over each element and add to the NeverInline set
    104   for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    105 
    106     // Get Source
    107     const Constant *Elt = InitList->getOperand(i);
    108 
    109     if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(Elt))
    110       if (CE->getOpcode() == Instruction::BitCast)
    111         Elt = CE->getOperand(0);
    112 
    113     // Insert into set of functions to never inline
    114     if (const Function *F = dyn_cast<Function>(Elt))
    115       NeverInline.insert(F);
    116   }
    117 
    118   return false;
    119 }
    120 
    121