diff options
author | Easwaran Raman <eraman@google.com> | 2016-01-14 23:16:29 +0000 |
---|---|---|
committer | Easwaran Raman <eraman@google.com> | 2016-01-14 23:16:29 +0000 |
commit | f4bb2f0dc322e15dddda95eafbb2eb0485f03e69 (patch) | |
tree | a28e6ac212c09266ad6b4d7d25c99b00f3f6b1d3 /llvm/lib/Analysis/InlineCost.cpp | |
parent | 14714c4181d8cb142ed684c9abfba835b9167410 (diff) | |
download | llvm-f4bb2f0dc322e15dddda95eafbb2eb0485f03e69.zip llvm-f4bb2f0dc322e15dddda95eafbb2eb0485f03e69.tar.gz llvm-f4bb2f0dc322e15dddda95eafbb2eb0485f03e69.tar.bz2 |
Refactor threshold computation for inline cost analysis
Differential Revision: http://reviews.llvm.org/D15401
llvm-svn: 257832
Diffstat (limited to 'llvm/lib/Analysis/InlineCost.cpp')
-rw-r--r-- | llvm/lib/Analysis/InlineCost.cpp | 110 |
1 files changed, 106 insertions, 4 deletions
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index a86a703..2b9e06e 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -39,6 +39,32 @@ using namespace llvm; STATISTIC(NumCallsAnalyzed, "Number of call sites analyzed"); +// Threshold to use when optsize is specified (and there is no +// -inline-threshold). +const int OptSizeThreshold = 75; + +// Threshold to use when -Oz is specified (and there is no -inline-threshold). +const int OptMinSizeThreshold = 25; + +// Threshold to use when -O[34] is specified (and there is no +// -inline-threshold). +const int OptAggressiveThreshold = 275; + +static cl::opt<int> DefaultInlineThreshold( + "inline-threshold", cl::Hidden, cl::init(225), cl::ZeroOrMore, + cl::desc("Control the amount of inlining to perform (default = 225)")); + +static cl::opt<int> HintThreshold( + "inlinehint-threshold", cl::Hidden, cl::init(325), + cl::desc("Threshold for inlining functions with inline hint")); + +// We introduce this threshold to help performance of instrumentation based +// PGO before we actually hook up inliner with analysis passes such as BPI and +// BFI. +static cl::opt<int> ColdThreshold( + "inlinecold-threshold", cl::Hidden, cl::init(225), + cl::desc("Threshold for inlining functions with cold attribute")); + namespace { class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> { @@ -122,6 +148,12 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> { /// inlined through this particular callsite. bool isKnownNonNullInCallee(Value *V); + /// Update Threshold based on callsite properties such as callee + /// attributes and callee hotness for PGO builds. The Callee is explicitly + /// passed to support analyzing indirect calls whose target is inferred by + /// analysis. + void updateThreshold(CallSite CS, Function &Callee); + // Custom analysis routines. bool analyzeBlock(BasicBlock *BB, SmallPtrSetImpl<const Value *> &EphValues); @@ -541,6 +573,56 @@ bool CallAnalyzer::isKnownNonNullInCallee(Value *V) { return false; } +void CallAnalyzer::updateThreshold(CallSite CS, Function &Callee) { + // If -inline-threshold is not given, listen to the optsize attribute when it + // would decrease the threshold. + Function *Caller = CS.getCaller(); + + // FIXME: Use Function::optForSize() + bool OptSize = Caller->hasFnAttribute(Attribute::OptimizeForSize); + + if (!(DefaultInlineThreshold.getNumOccurrences() > 0) && OptSize && + OptSizeThreshold < Threshold) + Threshold = OptSizeThreshold; + + // If profile information is available, use that to adjust threshold of hot + // and cold functions. + // FIXME: The heuristic used below for determining hotness and coldness are + // based on preliminary SPEC tuning and may not be optimal. Replace this with + // a well-tuned heuristic based on *callsite* hotness and not callee hotness. + uint64_t FunctionCount = 0, MaxFunctionCount = 0; + bool HasPGOCounts = false; + if (Callee.getEntryCount() && Callee.getParent()->getMaximumFunctionCount()) { + HasPGOCounts = true; + FunctionCount = Callee.getEntryCount().getValue(); + MaxFunctionCount = Callee.getParent()->getMaximumFunctionCount().getValue(); + } + + // Listen to the inlinehint attribute or profile based hotness information + // when it would increase the threshold and the caller does not need to + // minimize its size. + bool InlineHint = + Callee.hasFnAttribute(Attribute::InlineHint) || + (HasPGOCounts && + FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount)); + if (InlineHint && HintThreshold > Threshold && !Caller->optForMinSize()) + Threshold = HintThreshold; + + // Listen to the cold attribute or profile based coldness information + // when it would decrease the threshold. + bool ColdCallee = + Callee.hasFnAttribute(Attribute::Cold) || + (HasPGOCounts && + FunctionCount <= (uint64_t)(0.01 * (double)MaxFunctionCount)); + // Command line argument for DefaultInlineThreshold will override the default + // ColdThreshold. If we have -inline-threshold but no -inlinecold-threshold, + // do not use the default cold threshold even if it is smaller. + if ((DefaultInlineThreshold.getNumOccurrences() == 0 || + ColdThreshold.getNumOccurrences() > 0) && + ColdCallee && ColdThreshold < Threshold) + Threshold = ColdThreshold; +} + bool CallAnalyzer::visitCmpInst(CmpInst &I) { Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); // First try to handle simplified comparisons. @@ -1079,6 +1161,10 @@ bool CallAnalyzer::analyzeCall(CallSite CS) { // nice to base the bonus values on something more scientific. assert(NumInstructions == 0); assert(NumVectorInstructions == 0); + + // Update the threshold based on callsite properties + updateThreshold(CS, F); + FiftyPercentVectorBonus = 3 * Threshold / 2; TenPercentVectorBonus = 3 * Threshold / 4; const DataLayout &DL = F.getParent()->getDataLayout(); @@ -1335,15 +1421,31 @@ static bool functionsHaveCompatibleAttributes(Function *Caller, AttributeFuncs::areInlineCompatible(*Caller, *Callee); } -InlineCost llvm::getInlineCost(CallSite CS, int Threshold, +InlineCost llvm::getInlineCost(CallSite CS, int DefaultThreshold, TargetTransformInfo &CalleeTTI, AssumptionCacheTracker *ACT) { - return getInlineCost(CS, CS.getCalledFunction(), Threshold, CalleeTTI, ACT); + return getInlineCost(CS, CS.getCalledFunction(), DefaultThreshold, CalleeTTI, + ACT); } -InlineCost llvm::getInlineCost(CallSite CS, Function *Callee, int Threshold, +int llvm::computeThresholdFromOptLevels(unsigned OptLevel, + unsigned SizeOptLevel) { + if (OptLevel > 2) + return OptAggressiveThreshold; + if (SizeOptLevel == 1) // -Os + return OptSizeThreshold; + if (SizeOptLevel == 2) // -Oz + return OptMinSizeThreshold; + return DefaultInlineThreshold; +} + +int llvm::getDefaultInlineThreshold() { return DefaultInlineThreshold; } + +InlineCost llvm::getInlineCost(CallSite CS, Function *Callee, + int DefaultThreshold, TargetTransformInfo &CalleeTTI, AssumptionCacheTracker *ACT) { + // Cannot inline indirect calls. if (!Callee) return llvm::InlineCost::getNever(); @@ -1375,7 +1477,7 @@ InlineCost llvm::getInlineCost(CallSite CS, Function *Callee, int Threshold, DEBUG(llvm::dbgs() << " Analyzing call of " << Callee->getName() << "...\n"); - CallAnalyzer CA(CalleeTTI, ACT, *Callee, Threshold, CS); + CallAnalyzer CA(CalleeTTI, ACT, *Callee, DefaultThreshold, CS); bool ShouldInline = CA.analyzeCall(CS); DEBUG(CA.dump()); |