forked from OSchip/llvm-project
This change makes two big adjustments.
* Be a lot more accurate about what the effects will be when inlining a call to a function when an argument is an alloca. * Dramatically reduce the penalty for inlining a call in a large function. This heuristic made it almost impossible to inline a function into a large function, no matter how small the callee is. llvm-svn: 12363
This commit is contained in:
parent
797cb2f6c1
commit
2dc85b27e4
|
@ -14,11 +14,20 @@
|
||||||
#include "Inliner.h"
|
#include "Inliner.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
|
#include "llvm/Type.h"
|
||||||
#include "llvm/Support/CallSite.h"
|
#include "llvm/Support/CallSite.h"
|
||||||
#include "llvm/Transforms/IPO.h"
|
#include "llvm/Transforms/IPO.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
struct ArgInfo {
|
||||||
|
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
|
// FunctionInfo - For each function, calculate the size of it in blocks and
|
||||||
// instructions.
|
// instructions.
|
||||||
struct FunctionInfo {
|
struct FunctionInfo {
|
||||||
|
@ -26,11 +35,11 @@ namespace {
|
||||||
// used to estimate the code size cost of inlining it.
|
// used to estimate the code size cost of inlining it.
|
||||||
unsigned NumInsts, NumBlocks;
|
unsigned NumInsts, NumBlocks;
|
||||||
|
|
||||||
// ConstantArgumentWeights - Each formal argument of the function is
|
// ArgumentWeights - Each formal argument of the function is inspected to
|
||||||
// inspected to see if it is used in any contexts where making it a constant
|
// 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
|
// would reduce the code size. If so, we add some value to the argument
|
||||||
// entry here.
|
// entry here.
|
||||||
std::vector<unsigned> ConstantArgumentWeights;
|
std::vector<ArgInfo> ArgumentWeights;
|
||||||
|
|
||||||
FunctionInfo() : NumInsts(0), NumBlocks(0) {}
|
FunctionInfo() : NumInsts(0), NumBlocks(0) {}
|
||||||
};
|
};
|
||||||
|
@ -88,6 +97,33 @@ static unsigned CountCodeReductionForConstant(Value *V) {
|
||||||
return Reduction;
|
return Reduction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
static unsigned CountCodeReductionForAlloca(Value *V) {
|
||||||
|
if (!isa<PointerType>(V->getType())) return 0; // Not a pointer
|
||||||
|
unsigned Reduction = 0;
|
||||||
|
for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
|
||||||
|
Instruction *I = cast<Instruction>(*UI);
|
||||||
|
if (isa<LoadInst>(I) || isa<StoreInst>(I))
|
||||||
|
Reduction += 10;
|
||||||
|
else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
|
||||||
|
// If the GEP has variable indices, we won't be able to do much with it.
|
||||||
|
for (Instruction::op_iterator I = GEP->op_begin()+1, E = GEP->op_end();
|
||||||
|
I != E; ++I)
|
||||||
|
if (!isa<Constant>(*I)) return 0;
|
||||||
|
Reduction += CountCodeReductionForAlloca(GEP)+15;
|
||||||
|
} else {
|
||||||
|
// If there is some other strange instruction, we're not going to be able
|
||||||
|
// to do much if we inline this.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Reduction;
|
||||||
|
}
|
||||||
|
|
||||||
// getInlineCost - The heuristic used to determine if we should inline the
|
// getInlineCost - The heuristic used to determine if we should inline the
|
||||||
// function call or not.
|
// function call or not.
|
||||||
//
|
//
|
||||||
|
@ -131,11 +167,12 @@ int SimpleInliner::getInlineCost(CallSite CS) {
|
||||||
|
|
||||||
// Check out all of the arguments to the function, figuring out how much
|
// Check out all of the arguments to the function, figuring out how much
|
||||||
// code can be eliminated if one of the arguments is a constant.
|
// code can be eliminated if one of the arguments is a constant.
|
||||||
std::vector<unsigned> &ArgWeights = CalleeFI.ConstantArgumentWeights;
|
std::vector<ArgInfo> &ArgWeights = CalleeFI.ArgumentWeights;
|
||||||
|
|
||||||
for (Function::aiterator I = Callee->abegin(), E = Callee->aend();
|
for (Function::aiterator I = Callee->abegin(), E = Callee->aend();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
ArgWeights.push_back(CountCodeReductionForConstant(I));
|
ArgWeights.push_back(ArgInfo(CountCodeReductionForConstant(I),
|
||||||
|
CountCodeReductionForAlloca(I)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,15 +198,16 @@ int SimpleInliner::getInlineCost(CallSite CS) {
|
||||||
// significant future optimization possibilities (like scalar promotion, and
|
// significant future optimization possibilities (like scalar promotion, and
|
||||||
// scalarization), so encourage the inlining of the function.
|
// scalarization), so encourage the inlining of the function.
|
||||||
//
|
//
|
||||||
else if (isa<AllocaInst>(I))
|
else if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
|
||||||
InlineCost -= 60;
|
if (ArgNo < CalleeFI.ArgumentWeights.size())
|
||||||
|
InlineCost -= CalleeFI.ArgumentWeights[ArgNo].AllocaWeight;
|
||||||
|
|
||||||
// If this is a constant being passed into the function, use the argument
|
// If this is a constant being passed into the function, use the argument
|
||||||
// weights calculated for the callee to determine how much will be folded
|
// weights calculated for the callee to determine how much will be folded
|
||||||
// away with this information.
|
// away with this information.
|
||||||
else if (isa<Constant>(I) || isa<GlobalVariable>(I)) {
|
} else if (isa<Constant>(I) || isa<GlobalVariable>(I)) {
|
||||||
if (ArgNo < CalleeFI.ConstantArgumentWeights.size())
|
if (ArgNo < CalleeFI.ArgumentWeights.size())
|
||||||
InlineCost -= CalleeFI.ConstantArgumentWeights[ArgNo];
|
InlineCost -= CalleeFI.ArgumentWeights[ArgNo].ConstantWeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +216,7 @@ int SimpleInliner::getInlineCost(CallSite CS) {
|
||||||
|
|
||||||
// Don't inline into something too big, which would make it bigger. Here, we
|
// Don't inline into something too big, which would make it bigger. Here, we
|
||||||
// count each basic block as a single unit.
|
// count each basic block as a single unit.
|
||||||
InlineCost += Caller->size()*2;
|
InlineCost += Caller->size()/20;
|
||||||
|
|
||||||
|
|
||||||
// Look at the size of the callee. Each basic block counts as 20 units, and
|
// Look at the size of the callee. Each basic block counts as 20 units, and
|
||||||
|
|
Loading…
Reference in New Issue