aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-08-12 05:45:09 +0000
committerChris Lattner <sabre@nondot.org>2004-08-12 05:45:09 +0000
commitee45f4cbe409b2e89207f3c554e9121101c9e52e (patch)
treecea602fc956fe853deed08b10792ebf2a90bd64a
parenta1b6ae9d7cf39e4589192eac4ad2288ec29e2de1 (diff)
This patch makes the inliner refuse to inline functions that have alloca
instructions in the body of the function (not the entry block). This fixes test/Programs/SingleSource/Regression/C/2004-08-12-InlinerAndAllocas.c and test/Programs/External/SPEC/CINT2000/176.gcc on zion. This should obviously be pulled into 1.3. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15684 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/IPO/InlineSimple.cpp82
1 files changed, 57 insertions, 25 deletions
diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp
index 791b21356e..1722fe52e0 100644
--- a/lib/Transforms/IPO/InlineSimple.cpp
+++ b/lib/Transforms/IPO/InlineSimple.cpp
@@ -31,6 +31,16 @@ namespace {
// FunctionInfo - For each function, calculate the size of it in blocks and
// instructions.
struct FunctionInfo {
+ // HasAllocas - Keep track of whether or not a function contains an alloca
+ // instruction that is not in the entry block of the function. Inlining
+ // this call could cause us to blow out the stack, because the stack memory
+ // would never be released.
+ //
+ // FIXME: LLVM needs a way of dealloca'ing memory, which would make this
+ // irrelevant!
+ //
+ bool HasAllocas;
+
// NumInsts, NumBlocks - Keep track of how large each function is, which is
// used to estimate the code size cost of inlining it.
unsigned NumInsts, NumBlocks;
@@ -41,7 +51,11 @@ namespace {
// entry here.
std::vector<ArgInfo> ArgumentWeights;
- FunctionInfo() : NumInsts(0), NumBlocks(0) {}
+ FunctionInfo() : HasAllocas(false), NumInsts(0), NumBlocks(0) {}
+
+ /// analyzeFunction - Fill in the current structure with information gleaned
+ /// from the specified function.
+ void analyzeFunction(Function *F);
};
class SimpleInliner : public Inliner {
@@ -123,6 +137,41 @@ static unsigned CountCodeReductionForAlloca(Value *V) {
return Reduction;
}
+/// analyzeFunction - Fill in the current structure with information gleaned
+/// from the specified function.
+void FunctionInfo::analyzeFunction(Function *F) {
+ unsigned NumInsts = 0, NumBlocks = 0;
+
+ // Look at the size of the callee. Each basic block counts as 20 units, and
+ // each instruction counts as 10.
+ for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
+ for (BasicBlock::const_iterator II = BB->begin(), E = BB->end();
+ II != E; ++II) {
+ ++NumInsts;
+
+ // If there is an alloca in the body of the function, we cannot currently
+ // inline the function without the risk of exploding the stack.
+ if (isa<AllocaInst>(II) && BB != F->begin()) {
+ HasAllocas = true;
+ this->NumBlocks = this->NumInsts = 1;
+ return;
+ }
+ }
+
+ ++NumBlocks;
+ }
+
+ this->NumBlocks = NumBlocks;
+ this->NumInsts = NumInsts;
+
+ // 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.
+ for (Function::aiterator I = F->abegin(), E = F->aend(); I != E; ++I)
+ ArgumentWeights.push_back(ArgInfo(CountCodeReductionForConstant(I),
+ CountCodeReductionForAlloca(I)));
+}
+
+
// getInlineCost - The heuristic used to determine if we should inline the
// function call or not.
//
@@ -149,31 +198,14 @@ int SimpleInliner::getInlineCost(CallSite CS) {
// Get information about the callee...
FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];
- // If we haven't calculated this information yet...
- if (CalleeFI.NumBlocks == 0) {
- unsigned NumInsts = 0, NumBlocks = 0;
-
- // Look at the size of the callee. Each basic block counts as 20 units, and
- // each instruction counts as 10.
- for (Function::const_iterator BB = Callee->begin(), E = Callee->end();
- BB != E; ++BB) {
- NumInsts += BB->size();
- NumBlocks++;
- }
-
- CalleeFI.NumBlocks = NumBlocks;
- CalleeFI.NumInsts = NumInsts;
-
- // 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<ArgInfo> &ArgWeights = CalleeFI.ArgumentWeights;
-
- for (Function::aiterator I = Callee->abegin(), E = Callee->aend();
- I != E; ++I)
- ArgWeights.push_back(ArgInfo(CountCodeReductionForConstant(I),
- CountCodeReductionForAlloca(I)));
- }
+ // If we haven't calculated this information yet, do so now.
+ if (CalleeFI.NumBlocks == 0)
+ CalleeFI.analyzeFunction(Callee);
+ // Don't inline calls to functions with allocas that are not in the entry
+ // block of the function.
+ if (CalleeFI.HasAllocas)
+ return 2000000000;
// Add to the inline quality for properties that make the call valuable to
// inline. This includes factors that indicate that the result of inlining