X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FIPO%2FInlineSimple.cpp;h=d9a2b9e6b67da3dd95bafdbb1732ce034d37b9db;hb=2f6d42351ac4c1d72762a9193c1c8abdb79f2d77;hp=966ac2eab5a2f5979cbf73aff91f3662024b94a4;hpb=884d6c4e10501116a8ff45616231564a2738dadd;p=oota-llvm.git diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp index 966ac2eab5a..d9a2b9e6b67 100644 --- a/lib/Transforms/IPO/InlineSimple.cpp +++ b/lib/Transforms/IPO/InlineSimple.cpp @@ -1,104 +1,105 @@ //===- InlineSimple.cpp - Code to perform simple function inlining --------===// // +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// // This file implements bottom-up inlining of functions into callees. // //===----------------------------------------------------------------------===// -#include "Inliner.h" -#include "llvm/Function.h" -#include "llvm/iMemory.h" -#include "llvm/Support/CallSite.h" #include "llvm/Transforms/IPO.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AssumptionTracker.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/InlineCost.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/Transforms/IPO/InlinerPass.h" + +using namespace llvm; + +#define DEBUG_TYPE "inline" namespace { - // FunctionInfo - For each function, calculate the size of it in blocks and - // instructions. - struct FunctionInfo { - unsigned NumInsts, NumBlocks; - - FunctionInfo() : NumInsts(0), NumBlocks(0) {} - }; - - class SimpleInliner : public Inliner { - std::map CachedFunctionInfo; - public: - int getInlineCost(CallSite CS); - }; - RegisterOpt X("inline", "Function Integration/Inlining"); -} -Pass *createFunctionInliningPass() { return new SimpleInliner(); } +/// \brief Actual inliner pass implementation. +/// +/// The common implementation of the inlining logic is shared between this +/// inliner pass and the always inliner pass. The two passes use different cost +/// analyses to determine when to inline. +class SimpleInliner : public Inliner { + InlineCostAnalysis *ICA; + +public: + SimpleInliner() : Inliner(ID), ICA(nullptr) { + initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); + } -// getInlineCost - The heuristic used to determine if we should inline the -// function call or not. -// -int SimpleInliner::getInlineCost(CallSite CS) { - Instruction *TheCall = CS.getInstruction(); - const Function *Callee = CS.getCalledFunction(); - const Function *Caller = TheCall->getParent()->getParent(); - - // Don't inline a directly recursive call. - if (Caller == Callee) return 2000000000; - - // InlineCost - This value measures how good of an inline candidate this call - // site is to inline. A lower inline cost make is more likely for the call to - // be inlined. This value may go negative. - // - int InlineCost = 0; - - // If there is only one call of the function, and it has internal linkage, - // make it almost guaranteed to be inlined. - // - if (Callee->use_size() == 1 && Callee->hasInternalLinkage()) - InlineCost -= 30000; - - // Add to the inline quality for properties that make the call valueable to - // inline. This includes factors that indicate that the result of inlining - // the function will be optimizable. Currently this just looks at arguments - // passed into the function. - // - for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); - I != E; ++I) { - // Each argument passed in has a cost at both the caller and the callee - // sides. This favors functions that take many arguments over functions - // that take few arguments. - InlineCost -= 20; - - // If this is a function being passed in, it is very likely that we will be - // able to turn an indirect function call into a direct function call. - if (isa(I)) - InlineCost -= 100; - - // If a constant, global variable or alloca is passed in, inlining this - // function is likely to allow significant future optimization possibilities - // (constant propagation, scalar promotion, and scalarization), so encourage - // the inlining of the function. - // - else if (isa(I) || isa(I) || isa(I)) - InlineCost -= 60; + SimpleInliner(int Threshold) + : Inliner(ID, Threshold, /*InsertLifetime*/ true), ICA(nullptr) { + initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); } - // Now that we have considered all of the factors that make the call site more - // likely to be inlined, look at factors that make us not want to inline it. - FunctionInfo &CalleeFI = CachedFunctionInfo[Callee]; - - // If we haven't calculated this information yet... - if (CalleeFI.NumBlocks == 0) { - unsigned NumInsts = 0, NumBlocks = 0; - - // Look at the size of the callee. Each basic block counts as 20 units, and - // each instruction counts as 10. - for (Function::const_iterator BB = Callee->begin(), E = Callee->end(); - BB != E; ++BB) { - NumInsts += BB->size(); - NumBlocks++; - } - CalleeFI.NumBlocks = NumBlocks; - CalleeFI.NumInsts = NumInsts; + static char ID; // Pass identification, replacement for typeid + + InlineCost getInlineCost(CallSite CS) override { + return ICA->getInlineCost(CS, getInlineThreshold(CS)); } - // Look at the size of the callee. Each basic block counts as 21 units, and - // each instruction counts as 10. - InlineCost += CalleeFI.NumInsts*10 + CalleeFI.NumBlocks*20; - return InlineCost; + bool runOnSCC(CallGraphSCC &SCC) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +static int computeThresholdFromOptLevels(unsigned OptLevel, + unsigned SizeOptLevel) { + if (OptLevel > 2) + return 275; + if (SizeOptLevel == 1) // -Os + return 75; + if (SizeOptLevel == 2) // -Oz + return 25; + return 225; +} + +} // end anonymous namespace + +char SimpleInliner::ID = 0; +INITIALIZE_PASS_BEGIN(SimpleInliner, "inline", + "Function Integration/Inlining", false, false) +INITIALIZE_AG_DEPENDENCY(AliasAnalysis) +INITIALIZE_PASS_DEPENDENCY(AssumptionTracker) +INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) +INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis) +INITIALIZE_PASS_END(SimpleInliner, "inline", + "Function Integration/Inlining", false, false) + +Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); } + +Pass *llvm::createFunctionInliningPass(int Threshold) { + return new SimpleInliner(Threshold); +} + +Pass *llvm::createFunctionInliningPass(unsigned OptLevel, + unsigned SizeOptLevel) { + return new SimpleInliner( + computeThresholdFromOptLevels(OptLevel, SizeOptLevel)); +} + +bool SimpleInliner::runOnSCC(CallGraphSCC &SCC) { + ICA = &getAnalysis(); + return Inliner::runOnSCC(SCC); +} + +void SimpleInliner::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + Inliner::getAnalysisUsage(AU); }