From b2ab2fa524f3f90376639037bd81924483cca0af Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Sat, 1 Oct 2011 01:39:05 +0000 Subject: [PATCH] Inlining and unrolling heuristics should be aware of free truncs. We want heuristics to be based on accurate data, but more importantly we don't want llvm to behave randomly. A benign trunc inserted by an upstream pass should not cause a wild swings in optimization level. See PR11034. It's a general problem with threshold-based heuristics, but we can make it less bad. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140919 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/CodeMetrics.h | 7 ++++-- include/llvm/Analysis/InlineCost.h | 9 ++++++- lib/Analysis/InlineCost.cpp | 32 +++++++++++++++--------- lib/Transforms/IPO/InlineAlways.cpp | 3 +++ lib/Transforms/IPO/InlineSimple.cpp | 2 ++ lib/Transforms/Scalar/LoopUnrollPass.cpp | 9 ++++--- 6 files changed, 44 insertions(+), 18 deletions(-) diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 9433d07a2b5..d96dd82b359 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -18,6 +18,9 @@ #include "llvm/ADT/DenseMap.h" namespace llvm { + + class TargetData; + // CodeMetrics - Calculate size and a few similar metrics for a set of // basic blocks. struct CodeMetrics { @@ -68,11 +71,11 @@ namespace llvm { /// analyzeBasicBlock - Add information about the specified basic block /// to the current structure. - void analyzeBasicBlock(const BasicBlock *BB); + void analyzeBasicBlock(const BasicBlock *BB, const TargetData *TD = 0); /// analyzeFunction - Add information about the specified function /// to the current structure. - void analyzeFunction(Function *F); + void analyzeFunction(Function *F, const TargetData *TD = 0); /// CountCodeReductionForConstant - Figure out an approximation for how /// many instructions will be constant folded if the specified value is diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index a0cce515e9e..36a16e68df0 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -29,6 +29,7 @@ namespace llvm { class CallSite; template class SmallPtrSet; + class TargetData; namespace InlineConstants { // Various magic constants used to adjust heuristics. @@ -113,7 +114,7 @@ namespace llvm { /// analyzeFunction - Add information about the specified function /// to the current structure. - void analyzeFunction(Function *F); + void analyzeFunction(Function *F, const TargetData *TD); /// NeverInline - Returns true if the function should never be /// inlined into any caller. @@ -124,11 +125,17 @@ namespace llvm { // the ValueMap will update itself when this happens. ValueMap CachedFunctionInfo; + // TargetData if available, or null. + const TargetData *TD; + int CountBonusForConstant(Value *V, Constant *C = NULL); int ConstantFunctionBonus(CallSite CS, Constant *C); int getInlineSize(CallSite CS, Function *Callee); int getInlineBonuses(CallSite CS, Function *Callee); public: + InlineCostAnalyzer(): TD(0) {} + + void setTargetData(const TargetData *TData) { TD = TData; } /// getInlineCost - The heuristic used to determine if we should inline the /// function call or not. diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp index 7ec7ae525b2..e12e322c2a9 100644 --- a/lib/Analysis/InlineCost.cpp +++ b/lib/Analysis/InlineCost.cpp @@ -15,6 +15,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/CallingConv.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallPtrSet.h" using namespace llvm; @@ -52,7 +53,8 @@ bool llvm::callIsSmall(const Function *F) { /// analyzeBasicBlock - Fill in the current structure with information gleaned /// from the specified block. -void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { +void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB, + const TargetData *TD) { ++NumBlocks; unsigned NumInstsBeforeThisBB = NumInsts; for (BasicBlock::const_iterator II = BB->begin(), E = BB->end(); @@ -105,6 +107,11 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { if (CI->isLosslessCast() || isa(CI) || isa(CI)) continue; + // trunc to a native type is free (assuming the target has compare and + // shift-right of the same width). + if (isa(CI) && TD && + TD->isLegalInteger(TD->getTypeSizeInBits(CI->getType()))) + continue; // Result of a cmp instruction is often extended (to be used by other // cmp instructions, logical or return instructions). These are usually // nop on most sane targets. @@ -217,7 +224,7 @@ unsigned CodeMetrics::CountCodeReductionForAlloca(Value *V) { /// analyzeFunction - Fill in the current structure with information gleaned /// from the specified function. -void CodeMetrics::analyzeFunction(Function *F) { +void CodeMetrics::analyzeFunction(Function *F, const TargetData *TD) { // If this function contains a call to setjmp or _setjmp, never inline // it. This is a hack because we depend on the user marking their local // variables as volatile if they are live across a setjmp call, and they @@ -227,13 +234,14 @@ void CodeMetrics::analyzeFunction(Function *F) { // Look at the size of the callee. for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) - analyzeBasicBlock(&*BB); + analyzeBasicBlock(&*BB, TD); } /// analyzeFunction - Fill in the current structure with information gleaned /// from the specified function. -void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) { - Metrics.analyzeFunction(F); +void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F, + const TargetData *TD) { + Metrics.analyzeFunction(F, TD); // A function with exactly one return has it removed during the inlining // process (see InlineFunction), so don't count it. @@ -275,7 +283,7 @@ int InlineCostAnalyzer::getSpecializationBonus(Function *Callee, // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); + CalleeFI->analyzeFunction(Callee, TD); unsigned ArgNo = 0; unsigned i = 0; @@ -365,7 +373,7 @@ int InlineCostAnalyzer::getInlineSize(CallSite CS, Function *Callee) { // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); + CalleeFI->analyzeFunction(Callee, TD); // 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 @@ -418,7 +426,7 @@ int InlineCostAnalyzer::getInlineBonuses(CallSite CS, Function *Callee) { // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); + CalleeFI->analyzeFunction(Callee, TD); bool isDirectCall = CS.getCalledFunction() == Callee; Instruction *TheCall = CS.getInstruction(); @@ -486,7 +494,7 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); + CalleeFI->analyzeFunction(Callee, TD); // If we should never inline this, return a huge cost. if (CalleeFI->NeverInline()) @@ -505,7 +513,7 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, // If we haven't calculated this information yet, do so now. if (CallerFI.Metrics.NumBlocks == 0) { - CallerFI.analyzeFunction(Caller); + CallerFI.analyzeFunction(Caller, TD); // Recompute the CalleeFI pointer, getting Caller could have invalidated // it. @@ -544,7 +552,7 @@ InlineCost InlineCostAnalyzer::getSpecializationCost(Function *Callee, // If we haven't calculated this information yet, do so now. if (CalleeFI->Metrics.NumBlocks == 0) - CalleeFI->analyzeFunction(Callee); + CalleeFI->analyzeFunction(Callee, TD); int Cost = 0; @@ -570,7 +578,7 @@ float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) { // If we haven't calculated this information yet, do so now. if (CalleeFI.Metrics.NumBlocks == 0) - CalleeFI.analyzeFunction(Callee); + CalleeFI.analyzeFunction(Callee, TD); float Factor = 1.0f; // Single BB functions are often written to be inlined. diff --git a/lib/Transforms/IPO/InlineAlways.cpp b/lib/Transforms/IPO/InlineAlways.cpp index 50cccd51a06..c0426da2c68 100644 --- a/lib/Transforms/IPO/InlineAlways.cpp +++ b/lib/Transforms/IPO/InlineAlways.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/InlinerPass.h" +#include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallPtrSet.h" using namespace llvm; @@ -74,6 +75,8 @@ Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); } // doInitialization - Initializes the vector of functions that have not // been annotated with the "always inline" attribute. bool AlwaysInliner::doInitialization(CallGraph &CG) { + CA.setTargetData(getAnalysisIfAvailable()); + Module &M = CG.getModule(); for (Module::iterator I = M.begin(), E = M.end(); diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp index 1ebe7c97e0b..84dd4fdd988 100644 --- a/lib/Transforms/IPO/InlineSimple.cpp +++ b/lib/Transforms/IPO/InlineSimple.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/InlinerPass.h" +#include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallPtrSet.h" using namespace llvm; @@ -75,6 +76,7 @@ Pass *llvm::createFunctionInliningPass(int Threshold) { // doInitialization - Initializes the vector of functions that have been // annotated with the noinline attribute. bool SimpleInliner::doInitialization(CallGraph &CG) { + CA.setTargetData(getAnalysisIfAvailable()); Module &M = CG.getModule(); diff --git a/lib/Transforms/Scalar/LoopUnrollPass.cpp b/lib/Transforms/Scalar/LoopUnrollPass.cpp index cca7ba0bd4e..91395b2af6a 100644 --- a/lib/Transforms/Scalar/LoopUnrollPass.cpp +++ b/lib/Transforms/Scalar/LoopUnrollPass.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/UnrollLoop.h" +#include "llvm/Target/TargetData.h" #include using namespace llvm; @@ -107,11 +108,12 @@ Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial) { } /// ApproximateLoopSize - Approximate the size of the loop. -static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls) { +static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls, + const TargetData *TD) { CodeMetrics Metrics; for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); I != E; ++I) - Metrics.analyzeBasicBlock(*I); + Metrics.analyzeBasicBlock(*I, TD); NumCalls = Metrics.NumInlineCandidates; unsigned LoopSize = Metrics.NumInsts; @@ -174,8 +176,9 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) { // Enforce the threshold. if (Threshold != NoThreshold) { + const TargetData *TD = getAnalysisIfAvailable(); unsigned NumInlineCandidates; - unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates); + unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates, TD); DEBUG(dbgs() << " Loop Size = " << LoopSize << "\n"); if (NumInlineCandidates != 0) { DEBUG(dbgs() << " Not unrolling loop with inlinable calls.\n");