summaryrefslogtreecommitdiff
path: root/lib/Transforms/Utils/BasicInliner.cpp
diff options
context:
space:
mode:
authorDevang Patel <dpatel@apple.com>2007-07-25 18:00:25 +0000
committerDevang Patel <dpatel@apple.com>2007-07-25 18:00:25 +0000
commit6899b314225dd5fa5ccc2a5692daaa89c1d623d8 (patch)
tree15cabe7a2eb96e54266eec3cf068869cb523dc9e /lib/Transforms/Utils/BasicInliner.cpp
parentb4d2cac15b19ff1ec0d233ae742884d1632769c6 (diff)
downloadllvm-6899b314225dd5fa5ccc2a5692daaa89c1d623d8.tar.gz
llvm-6899b314225dd5fa5ccc2a5692daaa89c1d623d8.tar.bz2
llvm-6899b314225dd5fa5ccc2a5692daaa89c1d623d8.tar.xz
Add BasicInliner interface.
This interface allows clients to inline bunch of functions with module level call graph information.:wq git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40486 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Utils/BasicInliner.cpp')
-rw-r--r--lib/Transforms/Utils/BasicInliner.cpp171
1 files changed, 171 insertions, 0 deletions
diff --git a/lib/Transforms/Utils/BasicInliner.cpp b/lib/Transforms/Utils/BasicInliner.cpp
new file mode 100644
index 0000000000..871b1a504a
--- /dev/null
+++ b/lib/Transforms/Utils/BasicInliner.cpp
@@ -0,0 +1,171 @@
+//===- BasicInliner.cpp - Basic function level inliner --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Devang Patel and 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/ADT/SmallPtrSet.h"
+#include <vector>
+#include <set>
+
+using namespace llvm;
+
+namespace {
+ cl::opt<unsigned>
+ BasicInlineThreshold("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 VISIBILITY_HIDDEN 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;
+ std::set<const Function *> 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 = CallSite::get(I);
+ if (CS.getInstruction() && CS.getCalledFunction()
+ && !CS.getCalledFunction()->isDeclaration())
+ CallSites.push_back(CS);
+ }
+ }
+
+ DOUT << ": " << 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 taht are never inlinable.
+ if (Callee->isDeclaration() ||
+ CS.getInstruction()->getParent()->getParent() == Callee) {
+ CallSites.erase(CallSites.begin() + index);
+ --index;
+ continue;
+ }
+ int InlineCost = CA.getInlineCost(CS, NeverInline);
+ if (InlineCost >= (int) BasicInlineThreshold) {
+ DOUT << " NOT Inlining: cost = " << InlineCost
+ << ", call: " << *CS.getInstruction();
+ continue;
+ }
+
+ DOUT << " Inlining: cost=" << InlineCost
+ <<", call: " << *CS.getInstruction();
+
+ // Inline
+ if (InlineFunction(CS, NULL, TD)) {
+ if (Callee->use_empty() && Callee->hasInternalLinkage())
+ 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();
+}
+
+}