Reapply 124275 since the Dragonegg failure was unreproducible.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124641 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Christopher 2011-02-01 01:16:32 +00:00
parent 4d98ee5234
commit 8e2da0ce9d
2 changed files with 87 additions and 84 deletions

View File

@ -96,10 +96,9 @@ namespace llvm {
public: public:
unsigned ConstantWeight; unsigned ConstantWeight;
unsigned AllocaWeight; unsigned AllocaWeight;
unsigned ConstantBonus;
ArgInfo(unsigned CWeight, unsigned AWeight, unsigned CBonus) ArgInfo(unsigned CWeight, unsigned AWeight)
: ConstantWeight(CWeight), AllocaWeight(AWeight), ConstantBonus(CBonus) : ConstantWeight(CWeight), AllocaWeight(AWeight)
{} {}
}; };
@ -125,6 +124,7 @@ namespace llvm {
// the ValueMap will update itself when this happens. // the ValueMap will update itself when this happens.
ValueMap<const Function *, FunctionInfo> CachedFunctionInfo; ValueMap<const Function *, FunctionInfo> CachedFunctionInfo;
unsigned CountBonusForConstant(Value *V);
public: public:
/// getInlineCost - The heuristic used to determine if we should inline the /// getInlineCost - The heuristic used to determine if we should inline the

View File

@ -142,64 +142,6 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) {
NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB; NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB;
} }
// CountBonusForConstant - Figure out an approximation for how much per-call
// performance boost we can expect if the specified value is constant.
unsigned CodeMetrics::CountBonusForConstant(Value *V) {
unsigned Bonus = 0;
bool indirectCallBonus = false;
for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
User *U = *UI;
if (CallInst *CI = dyn_cast<CallInst>(U)) {
// Turning an indirect call into a direct call is a BIG win
if (CI->getCalledValue() == V)
indirectCallBonus = true;
}
else if (InvokeInst *II = dyn_cast<InvokeInst>(U)) {
// Turning an indirect call into a direct call is a BIG win
if (II->getCalledValue() == V)
indirectCallBonus = true;
}
// FIXME: Eliminating conditional branches and switches should
// also yield a per-call performance boost.
else {
// Figure out the bonuses that wll accrue due to simple constant
// propagation.
Instruction &Inst = cast<Instruction>(*U);
// We can't constant propagate instructions which have effects or
// read memory.
//
// FIXME: It would be nice to capture the fact that a load from a
// pointer-to-constant-global is actually a *really* good thing to zap.
// Unfortunately, we don't know the pointer that may get propagated here,
// so we can't make this decision.
if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() ||
isa<AllocaInst>(Inst))
continue;
bool AllOperandsConstant = true;
for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i)
if (!isa<Constant>(Inst.getOperand(i)) && Inst.getOperand(i) != V) {
AllOperandsConstant = false;
break;
}
if (AllOperandsConstant)
Bonus += CountBonusForConstant(&Inst);
}
}
// FIXME: The only reason we're applying the bonus once is while it's great
// to devirtualize calls the magnitude of the bonus x number of call sites
// can lead to a huge code explosion when we prefer to inline 1000 instruction
// functions that have 10 call sites. This should be made a function of the
// estimated inline penalty/benefit + the indirect call bonus.
if (indirectCallBonus) Bonus += InlineConstants::IndirectCallBonus;
return Bonus;
}
// CountCodeReductionForConstant - Figure out an approximation for how many // CountCodeReductionForConstant - Figure out an approximation for how many
// instructions will be constant folded if the specified value is constant. // instructions will be constant folded if the specified value is constant.
// //
@ -309,17 +251,14 @@ void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
ArgumentWeights.reserve(F->arg_size()); ArgumentWeights.reserve(F->arg_size());
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
ArgumentWeights.push_back(ArgInfo(Metrics.CountCodeReductionForConstant(I), ArgumentWeights.push_back(ArgInfo(Metrics.CountCodeReductionForConstant(I),
Metrics.CountCodeReductionForAlloca(I), Metrics.CountCodeReductionForAlloca(I)));
Metrics.CountBonusForConstant(I)));
} }
/// NeverInline - returns true if the function should never be inlined into /// NeverInline - returns true if the function should never be inlined into
/// any caller /// any caller
bool InlineCostAnalyzer::FunctionInfo::NeverInline() bool InlineCostAnalyzer::FunctionInfo::NeverInline() {
{
return (Metrics.callsSetJmp || Metrics.isRecursive || return (Metrics.callsSetJmp || Metrics.isRecursive ||
Metrics.containsIndirectBr); Metrics.containsIndirectBr);
} }
// getSpecializationBonus - The heuristic used to determine the per-call // getSpecializationBonus - The heuristic used to determine the per-call
// performance boost for using a specialization of Callee with argument // performance boost for using a specialization of Callee with argument
@ -343,8 +282,14 @@ int InlineCostAnalyzer::getSpecializationBonus(Function *Callee,
if (CalleeFI->Metrics.NumBlocks == 0) if (CalleeFI->Metrics.NumBlocks == 0)
CalleeFI->analyzeFunction(Callee); CalleeFI->analyzeFunction(Callee);
for (unsigned i = 0, s = SpecializedArgNos.size(); i < s; ++i ) unsigned ArgNo = 0;
Bonus += CalleeFI->ArgumentWeights[SpecializedArgNos[i]].ConstantBonus; unsigned i = 0;
for (Function::arg_iterator I = Callee->arg_begin(), E = Callee->arg_end();
I != E; ++I, ++ArgNo)
if (ArgNo == SpecializedArgNos[i]) {
++i;
Bonus += CountBonusForConstant(I);
}
// Calls usually take a long time, so they make the specialization gain // Calls usually take a long time, so they make the specialization gain
// smaller. // smaller.
@ -353,6 +298,62 @@ int InlineCostAnalyzer::getSpecializationBonus(Function *Callee,
return Bonus; return Bonus;
} }
// CountBonusForConstant - Figure out an approximation for how much per-call
// performance boost we can expect if the specified value is constant.
unsigned InlineCostAnalyzer::CountBonusForConstant(Value *V) {
unsigned Bonus = 0;
bool indirectCallBonus = false;
for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
User *U = *UI;
if (CallInst *CI = dyn_cast<CallInst>(U)) {
// Turning an indirect call into a direct call is a BIG win
if (CI->getCalledValue() == V)
indirectCallBonus = true;
}
else if (InvokeInst *II = dyn_cast<InvokeInst>(U)) {
// Turning an indirect call into a direct call is a BIG win
if (II->getCalledValue() == V)
indirectCallBonus = true;
}
// FIXME: Eliminating conditional branches and switches should
// also yield a per-call performance boost.
else {
// Figure out the bonuses that wll accrue due to simple constant
// propagation.
Instruction &Inst = cast<Instruction>(*U);
// We can't constant propagate instructions which have effects or
// read memory.
//
// FIXME: It would be nice to capture the fact that a load from a
// pointer-to-constant-global is actually a *really* good thing to zap.
// Unfortunately, we don't know the pointer that may get propagated here,
// so we can't make this decision.
if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() ||
isa<AllocaInst>(Inst))
continue;
bool AllOperandsConstant = true;
for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i)
if (!isa<Constant>(Inst.getOperand(i)) && Inst.getOperand(i) != V) {
AllOperandsConstant = false;
break;
}
if (AllOperandsConstant)
Bonus += CountBonusForConstant(&Inst);
}
}
// FIXME: The only reason we're applying the bonus once is while it's great
// to devirtualize calls the magnitude of the bonus x number of call sites
// can lead to a huge code explosion when we prefer to inline 1000 instruction
// functions that have 10 call sites. This should be made a function of the
// estimated inline penalty/benefit + the indirect call bonus.
if (indirectCallBonus) Bonus += InlineConstants::IndirectCallBonus;
return Bonus;
}
// 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.
@ -427,31 +428,33 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
// passed into the function. // passed into the function.
// //
unsigned ArgNo = 0; unsigned ArgNo = 0;
for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); CallSite::arg_iterator I = CS.arg_begin();
I != E; ++I, ++ArgNo) { for (Function::arg_iterator FI = Callee->arg_begin(), FE = Callee->arg_end();
// Each argument passed in has a cost at both the caller and the callee FI != FE; ++I, ++FI, ++ArgNo) {
// sides. Measurements show that each argument costs about the same as an
// instruction.
InlineCost -= InlineConstants::InstrCost;
// If an alloca is passed in, inlining this function is likely to allow // If an alloca is passed in, inlining this function is likely to allow
// 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.
// //
if (isa<AllocaInst>(I)) { if (isa<AllocaInst>(I))
if (ArgNo < CalleeFI->ArgumentWeights.size()) InlineCost -= CalleeFI->ArgumentWeights[ArgNo].AllocaWeight;
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)) { else if (isa<Constant>(I)) {
if (ArgNo < CalleeFI->ArgumentWeights.size()) InlineCost -= CalleeFI->ArgumentWeights[ArgNo].ConstantWeight;
InlineCost -= (CalleeFI->ArgumentWeights[ArgNo].ConstantWeight +
CalleeFI->ArgumentWeights[ArgNo].ConstantBonus); // Compute any constant bonus due to inlining we want to give here.
InlineCost -= CountBonusForConstant(FI);
} }
} }
// Each argument passed in has a cost at both the caller and the callee
// sides. Measurements show that each argument costs about the same as an
// instruction.
InlineCost -= (CS.arg_size() * InlineConstants::InstrCost);
// If there is only one call of the function, and it has internal linkage, // If there is only one call of the function, and it has internal linkage,
// make it almost guaranteed to be inlined. // make it almost guaranteed to be inlined.
// //