| //===- 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(); | |
| } | |
| } |