From 2dc85b27e4de4e414faab987022f194c98160051 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 13 Mar 2004 23:15:45 +0000 Subject: [PATCH] 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 --- llvm/lib/Transforms/IPO/InlineSimple.cpp | 60 +++++++++++++++++++----- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Transforms/IPO/InlineSimple.cpp b/llvm/lib/Transforms/IPO/InlineSimple.cpp index eec2ebd694ae..d28fcbf85d54 100644 --- a/llvm/lib/Transforms/IPO/InlineSimple.cpp +++ b/llvm/lib/Transforms/IPO/InlineSimple.cpp @@ -14,11 +14,20 @@ #include "Inliner.h" #include "llvm/Instructions.h" #include "llvm/Function.h" +#include "llvm/Type.h" #include "llvm/Support/CallSite.h" #include "llvm/Transforms/IPO.h" using namespace llvm; 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 // instructions. struct FunctionInfo { @@ -26,11 +35,11 @@ namespace { // used to estimate the code size cost of inlining it. unsigned NumInsts, NumBlocks; - // ConstantArgumentWeights - Each formal argument of the function is - // inspected to see if it is used in any contexts where making it a constant + // ArgumentWeights - Each formal argument of the function is inspected to + // 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 // entry here. - std::vector ConstantArgumentWeights; + std::vector ArgumentWeights; FunctionInfo() : NumInsts(0), NumBlocks(0) {} }; @@ -88,6 +97,33 @@ static unsigned CountCodeReductionForConstant(Value *V) { 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(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(*UI); + if (isa(I) || isa(I)) + Reduction += 10; + else if (GetElementPtrInst *GEP = dyn_cast(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(*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 // 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 // code can be eliminated if one of the arguments is a constant. - std::vector &ArgWeights = CalleeFI.ConstantArgumentWeights; + std::vector &ArgWeights = CalleeFI.ArgumentWeights; for (Function::aiterator I = Callee->abegin(), E = Callee->aend(); 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 // scalarization), so encourage the inlining of the function. // - else if (isa(I)) - InlineCost -= 60; + else if (AllocaInst *AI = dyn_cast(I)) { + if (ArgNo < CalleeFI.ArgumentWeights.size()) + InlineCost -= CalleeFI.ArgumentWeights[ArgNo].AllocaWeight; // 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 // away with this information. - else if (isa(I) || isa(I)) { - if (ArgNo < CalleeFI.ConstantArgumentWeights.size()) - InlineCost -= CalleeFI.ConstantArgumentWeights[ArgNo]; + } else if (isa(I) || isa(I)) { + if (ArgNo < CalleeFI.ArgumentWeights.size()) + 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 // 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