00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef LLVM_ANALYSIS_INLINECOST_H
00015 #define LLVM_ANALYSIS_INLINECOST_H
00016
00017 #include <cassert>
00018 #include <climits>
00019 #include <map>
00020 #include <vector>
00021 #include "llvm/ADT/DenseMap.h"
00022
00023 namespace llvm {
00024
00025 class Value;
00026 class Function;
00027 class BasicBlock;
00028 class CallSite;
00029 template<class PtrType, unsigned SmallSize>
00030 class SmallPtrSet;
00031
00032
00033
00034 struct CodeMetrics {
00037 bool NeverInline;
00038
00040 bool usesDynamicAlloca;
00041
00044 unsigned NumInsts, NumBlocks;
00045
00047 DenseMap<const BasicBlock *, unsigned> NumBBInsts;
00048
00050 unsigned NumCalls;
00051
00055 unsigned NumVectorInsts;
00056
00058 unsigned NumRets;
00059
00060 CodeMetrics() : NeverInline(false), usesDynamicAlloca(false), NumInsts(0),
00061 NumBlocks(0), NumCalls(0), NumVectorInsts(0), NumRets(0) {}
00062
00065 void analyzeBasicBlock(const BasicBlock *BB);
00066
00069 void analyzeFunction(Function *F);
00070 };
00071
00072 namespace InlineConstants {
00073
00074 const int InstrCost = 5;
00075 const int IndirectCallBonus = 500;
00076 const int CallPenalty = 25;
00077 const int LastCallToStaticBonus = -15000;
00078 const int ColdccPenalty = 2000;
00079 const int NoreturnPenalty = 10000;
00080 }
00081
00087 class InlineCost {
00088 enum Kind {
00089 Value,
00090 Always,
00091 Never
00092 };
00093
00094
00095
00096
00097
00098 enum { TYPE_BITS = 2 };
00099 enum { COST_BITS = unsigned(sizeof(unsigned)) * CHAR_BIT - TYPE_BITS };
00100 unsigned TypedCost;
00101
00102 Kind getType() const {
00103 return Kind(TypedCost >> COST_BITS);
00104 }
00105
00106 int getCost() const {
00107
00108 return (int(TypedCost << TYPE_BITS)) >> TYPE_BITS;
00109 }
00110
00111 InlineCost(int C, int T) {
00112 TypedCost = (unsigned(C << TYPE_BITS) >> TYPE_BITS) | (T << COST_BITS);
00113 assert(getCost() == C && "Cost exceeds InlineCost precision");
00114 }
00115 public:
00116 static InlineCost get(int Cost) { return InlineCost(Cost, Value); }
00117 static InlineCost getAlways() { return InlineCost(0, Always); }
00118 static InlineCost getNever() { return InlineCost(0, Never); }
00119
00120 bool isVariable() const { return getType() == Value; }
00121 bool isAlways() const { return getType() == Always; }
00122 bool isNever() const { return getType() == Never; }
00123
00126 int getValue() const {
00127 assert(getType() == Value && "Invalid access of InlineCost");
00128 return getCost();
00129 }
00130 };
00131
00133 class InlineCostAnalyzer {
00134 struct ArgInfo {
00135 public:
00136 unsigned ConstantWeight;
00137 unsigned AllocaWeight;
00138
00139 ArgInfo(unsigned CWeight, unsigned AWeight)
00140 : ConstantWeight(CWeight), AllocaWeight(AWeight) {}
00141 };
00142
00143 struct FunctionInfo {
00144 CodeMetrics Metrics;
00145
00150 std::vector<ArgInfo> ArgumentWeights;
00151
00155 unsigned CountCodeReductionForConstant(Value *V);
00156
00161 unsigned CountCodeReductionForAlloca(Value *V);
00162
00165 void analyzeFunction(Function *F);
00166 };
00167
00168 std::map<const Function *, FunctionInfo> CachedFunctionInfo;
00169
00170 public:
00171
00175 InlineCost getInlineCost(CallSite CS,
00176 SmallPtrSet<const Function *, 16> &NeverInline);
00177
00180 float getInlineFudgeFactor(CallSite CS);
00181
00183 void resetCachedCostInfo(Function* Caller) {
00184 CachedFunctionInfo[Caller] = FunctionInfo();
00185 }
00186
00190 void growCachedCostInfo(Function* Caller, Function* Callee);
00191 };
00192 }
00193
00194 #endif