|  | //===- BasicInliner.cpp - Basic function level inliner --------------------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // This file defines a simple function based inliner that does not use | 
|  | // call graph information. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #define DEBUG_TYPE "basicinliner" | 
|  | #include "llvm/Module.h" | 
|  | #include "llvm/Function.h" | 
|  | #include "llvm/Transforms/Utils/BasicInliner.h" | 
|  | #include "llvm/Transforms/Utils/Cloning.h" | 
|  | #include "llvm/Support/CallSite.h" | 
|  | #include "llvm/Support/CommandLine.h" | 
|  | #include "llvm/Support/Debug.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  | #include "llvm/ADT/SmallPtrSet.h" | 
|  | #include <vector> | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | static cl::opt<unsigned> | 
|  | BasicInlineThreshold("basic-inline-threshold", cl::Hidden, cl::init(200), | 
|  | cl::desc("Control the amount of basic inlining to perform (default = 200)")); | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | /// BasicInlinerImpl - BasicInliner implemantation class. This hides | 
|  | /// container info, used by basic inliner, from public interface. | 
|  | struct BasicInlinerImpl { | 
|  |  | 
|  | BasicInlinerImpl(const BasicInlinerImpl&); // DO NOT IMPLEMENT | 
|  | void operator=(const BasicInlinerImpl&); // DO NO IMPLEMENT | 
|  | public: | 
|  | BasicInlinerImpl(TargetData *T) : TD(T) {} | 
|  |  | 
|  | /// addFunction - Add function into the list of functions to process. | 
|  | /// All functions must be inserted using this interface before invoking | 
|  | /// inlineFunctions(). | 
|  | void addFunction(Function *F) { | 
|  | Functions.push_back(F); | 
|  | } | 
|  |  | 
|  | /// neverInlineFunction - Sometimes a function is never to be inlined | 
|  | /// because of one or other reason. | 
|  | void neverInlineFunction(Function *F) { | 
|  | NeverInline.insert(F); | 
|  | } | 
|  |  | 
|  | /// inlineFuctions - Walk all call sites in all functions supplied by | 
|  | /// client. Inline as many call sites as possible. Delete completely | 
|  | /// inlined functions. | 
|  | void inlineFunctions(); | 
|  |  | 
|  | private: | 
|  | TargetData *TD; | 
|  | std::vector<Function *> Functions; | 
|  | SmallPtrSet<const Function *, 16> NeverInline; | 
|  | SmallPtrSet<Function *, 8> DeadFunctions; | 
|  | InlineCostAnalyzer CA; | 
|  | }; | 
|  |  | 
|  | /// inlineFuctions - Walk all call sites in all functions supplied by | 
|  | /// client. Inline as many call sites as possible. Delete completely | 
|  | /// inlined functions. | 
|  | void BasicInlinerImpl::inlineFunctions() { | 
|  |  | 
|  | // Scan through and identify all call sites ahead of time so that we only | 
|  | // inline call sites in the original functions, not call sites that result | 
|  | // from inlining other functions. | 
|  | std::vector<CallSite> CallSites; | 
|  |  | 
|  | for (std::vector<Function *>::iterator FI = Functions.begin(), | 
|  | FE = Functions.end(); FI != FE; ++FI) { | 
|  | Function *F = *FI; | 
|  | for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) | 
|  | for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { | 
|  | CallSite CS(cast<Value>(I)); | 
|  | if (CS && CS.getCalledFunction() | 
|  | && !CS.getCalledFunction()->isDeclaration()) | 
|  | CallSites.push_back(CS); | 
|  | } | 
|  | } | 
|  |  | 
|  | DEBUG(dbgs() << ": " << CallSites.size() << " call sites.\n"); | 
|  |  | 
|  | // Inline call sites. | 
|  | bool Changed = false; | 
|  | do { | 
|  | Changed = false; | 
|  | for (unsigned index = 0; index != CallSites.size() && !CallSites.empty(); | 
|  | ++index) { | 
|  | CallSite CS = CallSites[index]; | 
|  | if (Function *Callee = CS.getCalledFunction()) { | 
|  |  | 
|  | // Eliminate calls that are never inlinable. | 
|  | if (Callee->isDeclaration() || | 
|  | CS.getInstruction()->getParent()->getParent() == Callee) { | 
|  | CallSites.erase(CallSites.begin() + index); | 
|  | --index; | 
|  | continue; | 
|  | } | 
|  | InlineCost IC = CA.getInlineCost(CS, NeverInline); | 
|  | if (IC.isAlways()) { | 
|  | DEBUG(dbgs() << "  Inlining: cost=always" | 
|  | <<", call: " << *CS.getInstruction()); | 
|  | } else if (IC.isNever()) { | 
|  | DEBUG(dbgs() << "  NOT Inlining: cost=never" | 
|  | <<", call: " << *CS.getInstruction()); | 
|  | continue; | 
|  | } else { | 
|  | int Cost = IC.getValue(); | 
|  |  | 
|  | if (Cost >= (int) BasicInlineThreshold) { | 
|  | DEBUG(dbgs() << "  NOT Inlining: cost = " << Cost | 
|  | << ", call: " <<  *CS.getInstruction()); | 
|  | continue; | 
|  | } else { | 
|  | DEBUG(dbgs() << "  Inlining: cost = " << Cost | 
|  | << ", call: " <<  *CS.getInstruction()); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Inline | 
|  | InlineFunctionInfo IFI(0, TD); | 
|  | if (InlineFunction(CS, IFI)) { | 
|  | if (Callee->use_empty() && (Callee->hasLocalLinkage() || | 
|  | Callee->hasAvailableExternallyLinkage())) | 
|  | DeadFunctions.insert(Callee); | 
|  | Changed = true; | 
|  | CallSites.erase(CallSites.begin() + index); | 
|  | --index; | 
|  | } | 
|  | } | 
|  | } | 
|  | } while (Changed); | 
|  |  | 
|  | // Remove completely inlined functions from module. | 
|  | for(SmallPtrSet<Function *, 8>::iterator I = DeadFunctions.begin(), | 
|  | E = DeadFunctions.end(); I != E; ++I) { | 
|  | Function *D = *I; | 
|  | Module *M = D->getParent(); | 
|  | M->getFunctionList().remove(D); | 
|  | } | 
|  | } | 
|  |  | 
|  | BasicInliner::BasicInliner(TargetData *TD) { | 
|  | Impl = new BasicInlinerImpl(TD); | 
|  | } | 
|  |  | 
|  | BasicInliner::~BasicInliner() { | 
|  | delete Impl; | 
|  | } | 
|  |  | 
|  | /// addFunction - Add function into the list of functions to process. | 
|  | /// All functions must be inserted using this interface before invoking | 
|  | /// inlineFunctions(). | 
|  | void BasicInliner::addFunction(Function *F) { | 
|  | Impl->addFunction(F); | 
|  | } | 
|  |  | 
|  | /// neverInlineFunction - Sometimes a function is never to be inlined because | 
|  | /// of one or other reason. | 
|  | void BasicInliner::neverInlineFunction(Function *F) { | 
|  | Impl->neverInlineFunction(F); | 
|  | } | 
|  |  | 
|  | /// inlineFuctions - Walk all call sites in all functions supplied by | 
|  | /// client. Inline as many call sites as possible. Delete completely | 
|  | /// inlined functions. | 
|  | void BasicInliner::inlineFunctions() { | 
|  | Impl->inlineFunctions(); | 
|  | } | 
|  |  | 
|  | } |