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 /*InsertLifetime*/true) { 42 initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); 43 } 44 static char ID; // Pass identification, replacement for typeid 45 InlineCost getInlineCost(CallSite CS) { 46 return CA.getInlineCost(CS, NeverInline); 47 } 48 float getInlineFudgeFactor(CallSite CS) { 49 return CA.getInlineFudgeFactor(CS); 50 } 51 void resetCachedCostInfo(Function *Caller) { 52 CA.resetCachedCostInfo(Caller); 53 } 54 void growCachedCostInfo(Function* Caller, Function* Callee) { 55 CA.growCachedCostInfo(Caller, Callee); 56 } 57 virtual bool doInitialization(CallGraph &CG); 58 void releaseMemory() { 59 CA.clear(); 60 } 61 }; 62 } 63 64 char SimpleInliner::ID = 0; 65 INITIALIZE_PASS_BEGIN(SimpleInliner, "inline", 66 "Function Integration/Inlining", false, false) 67 INITIALIZE_AG_DEPENDENCY(CallGraph) 68 INITIALIZE_PASS_END(SimpleInliner, "inline", 69 "Function Integration/Inlining", false, false) 70 71 Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); } 72 73 Pass *llvm::createFunctionInliningPass(int Threshold) { 74 return new SimpleInliner(Threshold); 75 } 76 77 // doInitialization - Initializes the vector of functions that have been 78 // annotated with the noinline attribute. 79 bool SimpleInliner::doInitialization(CallGraph &CG) { 80 CA.setTargetData(getAnalysisIfAvailable<TargetData>()); 81 82 Module &M = CG.getModule(); 83 84 for (Module::iterator I = M.begin(), E = M.end(); 85 I != E; ++I) 86 if (!I->isDeclaration() && I->hasFnAttr(Attribute::NoInline)) 87 NeverInline.insert(I); 88 89 // Get llvm.noinline 90 GlobalVariable *GV = M.getNamedGlobal("llvm.noinline"); 91 92 if (GV == 0) 93 return false; 94 95 // Don't crash on invalid code 96 if (!GV->hasDefinitiveInitializer()) 97 return false; 98 99 const ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); 100 101 if (InitList == 0) 102 return false; 103 104 // Iterate over each element and add to the NeverInline set 105 for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { 106 107 // Get Source 108 const Constant *Elt = InitList->getOperand(i); 109 110 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(Elt)) 111 if (CE->getOpcode() == Instruction::BitCast) 112 Elt = CE->getOperand(0); 113 114 // Insert into set of functions to never inline 115 if (const Function *F = dyn_cast<Function>(Elt)) 116 NeverInline.insert(F); 117 } 118 119 return false; 120 } 121 122