diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 1a67409ad17..e89ad9026d0 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -77,7 +77,12 @@ namespace llvm { /// many instructions will be constant folded if the specified value is /// constant. unsigned CountCodeReductionForConstant(Value *V); - + + /// CountBonusForConstant - Figure out an approximation for how much + /// per-call performance boost we can expect if the specified value is + /// constant. + unsigned CountBonusForConstant(Value *V); + /// 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. diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index b3b93950d47..9963ba44d0b 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -96,9 +96,11 @@ namespace llvm { public: unsigned ConstantWeight; unsigned AllocaWeight; + unsigned ConstantBonus; - ArgInfo(unsigned CWeight, unsigned AWeight) - : ConstantWeight(CWeight), AllocaWeight(AWeight) {} + ArgInfo(unsigned CWeight, unsigned AWeight, unsigned CBonus) + : ConstantWeight(CWeight), AllocaWeight(AWeight), ConstantBonus(CBonus) + {} }; struct FunctionInfo { diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp index afdf474c616..a0e2ec715fd 100644 --- a/lib/Analysis/InlineCost.cpp +++ b/lib/Analysis/InlineCost.cpp @@ -142,6 +142,55 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { 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; + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ + User *U = *UI; + if (CallInst *CI = dyn_cast(U)) { + // Turning an indirect call into a direct call is a BIG win + if (CI->getCalledValue() == V) + Bonus += InlineConstants::IndirectCallBonus; + } + else if (InvokeInst *II = dyn_cast(U)) { + // Turning an indirect call into a direct call is a BIG win + if (II->getCalledValue() == V) + Bonus += InlineConstants::IndirectCallBonus; + } + // 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(*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(Inst)) + continue; + + bool AllOperandsConstant = true; + for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) + if (!isa(Inst.getOperand(i)) && Inst.getOperand(i) != V) { + AllOperandsConstant = false; + break; + } + + if (AllOperandsConstant) + Bonus += CountBonusForConstant(&Inst); + } + } + return Bonus; +} + + // CountCodeReductionForConstant - Figure out an approximation for how many // instructions will be constant folded if the specified value is constant. // @@ -158,14 +207,6 @@ unsigned CodeMetrics::CountCodeReductionForConstant(Value *V) { Instrs += NumBBInsts[TI.getSuccessor(I)]; // We don't know which blocks will be eliminated, so use the average size. Reduction += InlineConstants::InstrCost*Instrs*(NumSucc-1)/NumSucc; - } else if (CallInst *CI = dyn_cast(U)) { - // Turning an indirect call into a direct call is a BIG win - if (CI->getCalledValue() == V) - Reduction += InlineConstants::IndirectCallBonus; - } else if (InvokeInst *II = dyn_cast(U)) { - // Turning an indirect call into a direct call is a BIG win - if (II->getCalledValue() == V) - Reduction += InlineConstants::IndirectCallBonus; } else { // Figure out if this instruction will be removed due to simple constant // propagation. @@ -259,7 +300,8 @@ void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) { ArgumentWeights.reserve(F->arg_size()); for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++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 @@ -383,7 +425,8 @@ InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS, // away with this information. } else if (isa(I)) { if (ArgNo < CalleeFI->ArgumentWeights.size()) - InlineCost -= CalleeFI->ArgumentWeights[ArgNo].ConstantWeight; + InlineCost -= (CalleeFI->ArgumentWeights[ArgNo].ConstantWeight + + CalleeFI->ArgumentWeights[ArgNo].ConstantBonus); } }