aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2011-10-01 01:39:05 +0000
committerAndrew Trick <atrick@apple.com>2011-10-01 01:39:05 +0000
commitb2ab2fa524f3f90376639037bd81924483cca0af (patch)
treee09aa034342e5ed6e61cd2b7bb363b5808c9fc1b
parent5c655413cf9466c29e38204ab3f19b33fffd7996 (diff)
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
-rw-r--r--include/llvm/Analysis/CodeMetrics.h7
-rw-r--r--include/llvm/Analysis/InlineCost.h9
-rw-r--r--lib/Analysis/InlineCost.cpp32
-rw-r--r--lib/Transforms/IPO/InlineAlways.cpp3
-rw-r--r--lib/Transforms/IPO/InlineSimple.cpp2
-rw-r--r--lib/Transforms/Scalar/LoopUnrollPass.cpp9
6 files changed, 44 insertions, 18 deletions
diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h
index 9433d07a2b..d96dd82b35 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 a0cce515e9..36a16e68df 100644
--- a/include/llvm/Analysis/InlineCost.h
+++ b/include/llvm/Analysis/InlineCost.h
@@ -29,6 +29,7 @@ namespace llvm {
class CallSite;
template<class PtrType, unsigned SmallSize>
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<const Function *, FunctionInfo> 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 7ec7ae525b..e12e322c2a 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<IntToPtrInst>(CI) ||
isa<PtrToIntInst>(CI))
continue;
+ // trunc to a native type is free (assuming the target has compare and
+ // shift-right of the same width).
+ if (isa<TruncInst>(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 50cccd51a0..c0426da2c6 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<TargetData>());
+
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 1ebe7c97e0..84dd4fdd98 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<TargetData>());
Module &M = CG.getModule();
diff --git a/lib/Transforms/Scalar/LoopUnrollPass.cpp b/lib/Transforms/Scalar/LoopUnrollPass.cpp
index cca7ba0bd4..91395b2af6 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 <climits>
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<TargetData>();
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");