//===- InlineCost.cpp - Cost analysis for inliner ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements heuristics for inlining decisions. // //===----------------------------------------------------------------------===// #ifndef LLVM_TRANSFORMS_UTILS_INLINECOST_H #define LLVM_TRANSFORMS_UTILS_INLINECOST_H #include "llvm/ADT/SmallPtrSet.h" #include #include #include namespace llvm { class Value; class Function; class CallSite; /// InlineCost - Represent the cost of inlining a function. This /// supports special values for functions which should "always" or /// "never" be inlined. Otherwise, the cost represents a unitless /// amount; smaller values increase the likelyhood of the function /// being inlined. class InlineCost { enum Kind { Value, Always, Never }; int Cost : 30; unsigned Type : 2; InlineCost(int C, int T) : Cost(C), Type(T) { assert(Cost == C && "Cost exceeds InlineCost precision"); } public: static InlineCost get(int Cost) { return InlineCost(Cost, Value); } static InlineCost getAlways() { return InlineCost(0, Always); } static InlineCost getNever() { return InlineCost(0, Never); } bool isVariable() const { return Type == Value; } bool isAlways() const { return Type == Always; } bool isNever() const { return Type == Never; } /// getValue() - Return a "variable" inline cost's amount. It is /// an error to call this on an "always" or "never" InlineCost. int getValue() const { assert(Type == Value && "Invalid access of InlineCost"); return Cost; } }; /// InlineCostAnalyzer - Cost analyzer used by inliner. class InlineCostAnalyzer { struct ArgInfo { public: unsigned ConstantWeight; unsigned AllocaWeight; ArgInfo(unsigned CWeight, unsigned AWeight) : ConstantWeight(CWeight), AllocaWeight(AWeight) {} }; // FunctionInfo - For each function, calculate the size of it in blocks and // instructions. struct FunctionInfo { /// NeverInline - True if this callee should never be inlined into a /// caller. bool NeverInline; /// NumInsts, NumBlocks - Keep track of how large each function is, which /// is used to estimate the code size cost of inlining it. unsigned NumInsts, NumBlocks; /// NumVectorInsts - Keep track of how many instructions produce vector /// values. The inliner is being more aggressive with inlining vector /// kernels. unsigned NumVectorInsts; /// ArgumentWeights - Each formal argument of the function is inspected to /// see if it is used in any contexts where making it a constant or alloca /// would reduce the code size. If so, we add some value to the argument /// entry here. std::vector ArgumentWeights; FunctionInfo() : NeverInline(false), NumInsts(0), NumBlocks(0), NumVectorInsts(0) {} /// analyzeFunction - Fill in the current structure with information /// gleaned from the specified function. void analyzeFunction(Function *F); /// CountCodeReductionForConstant - Figure out an approximation for how /// many instructions will be constant folded if the specified value is /// constant. unsigned CountCodeReductionForConstant(Value *V); /// CountCodeReductionForAlloca - Figure out an approximation of how much /// smaller the function will be if it is inlined into a context where an /// argument becomes an alloca. /// unsigned CountCodeReductionForAlloca(Value *V); }; std::map CachedFunctionInfo; public: /// getInlineCost - The heuristic used to determine if we should inline the /// function call or not. /// InlineCost getInlineCost(CallSite CS, SmallPtrSet &NeverInline); /// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a /// higher threshold to determine if the function call should be inlined. float getInlineFudgeFactor(CallSite CS); }; } #endif