From b833e5ac3fc9230947cbdfd50c7d8782a0c17d60 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Sat, 2 Sep 2006 21:19:44 +0000 Subject: [PATCH] Make ArgumentPromotion handle recursive functions that pass pointers in their recursive calls. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30057 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/ArgumentPromotion.cpp | 44 ++++++++++++++----- .../Transforms/ArgumentPromotion/recursion.ll | 16 +++++++ 2 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 test/Transforms/ArgumentPromotion/recursion.ll diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp index 5183d43bc7c..fb9090327d1 100644 --- a/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -186,6 +186,8 @@ static bool AllCalleesPassInValidPointerForArgument(Argument *Arg) { /// elements of the aggregate in order to avoid exploding the number of /// arguments passed in. bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg) const { + AliasAnalysis &AA = getAnalysis(); + // We can only promote this argument if all of the uses are loads, or are GEP // instructions (with constant indices) that are subsequently loaded. bool HasLoadInEntryBlock = false; @@ -240,6 +242,25 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg) const { } GEPIndices.push_back(Operands); } + } else if (CallInst* CI = dyn_cast(*UI)) { + // Is this a recursive call? + if (CI->getCalledFunction() != Arg->getParent()) + return false; + + // Find out what position argument we're dealing with. + unsigned Position = 0; + Function::arg_iterator ArgPos = Arg->getParent()->arg_begin(); + while (Arg != ArgPos) { + assert(ArgPos != Arg->getParent()->arg_end() && + "Arg not in parent's arg list?"); + Position++; + ArgPos++; + } + + // We only know that the call is safe if it's passing the argument in + // the same position that it came in at. + if (UI.getOperandNo() != Position+1) + return false; } else { return false; // Not a load or a GEP. } @@ -264,8 +285,7 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg) const { // Because there could be several/many load instructions, remember which // blocks we know to be transparent to the load. std::set TranspBlocks; - - AliasAnalysis &AA = getAnalysis(); + TargetData &TD = getAnalysis(); for (unsigned i = 0, e = Loads.size(); i != e; ++i) { @@ -360,15 +380,17 @@ Function *ArgPromotion::DoPromotion(Function *F, for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ++UI) { Instruction *User = cast(*UI); - assert(isa(User) || isa(User)); - std::vector Indices(User->op_begin()+1, User->op_end()); - ArgIndices.insert(Indices); - LoadInst *OrigLoad; - if (LoadInst *L = dyn_cast(User)) - OrigLoad = L; - else - OrigLoad = cast(User->use_back()); - OriginalLoads[Indices] = OrigLoad; + if (!isa(User)) { + assert(isa(User) || isa(User)); + std::vector Indices(User->op_begin()+1, User->op_end()); + ArgIndices.insert(Indices); + LoadInst *OrigLoad; + if (LoadInst *L = dyn_cast(User)) + OrigLoad = L; + else + OrigLoad = cast(User->use_back()); + OriginalLoads[Indices] = OrigLoad; + } } // Add a parameter to the function for each element passed in. diff --git a/test/Transforms/ArgumentPromotion/recursion.ll b/test/Transforms/ArgumentPromotion/recursion.ll new file mode 100644 index 00000000000..a005b9ce04b --- /dev/null +++ b/test/Transforms/ArgumentPromotion/recursion.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as < %s | opt -argpromotion | llvm-dis | grep x.val +; ModuleID = 'recursive2.bc' + +implementation ; Functions: + +internal int %foo(int* %x) { +entry: + %tmp.foo = load int* %x + ret int %tmp.foo +} + +int %bar(int* %x) { +entry: + %tmp3 = call int %foo( int* %x) ; [#uses=1] + ret int %tmp3 +} \ No newline at end of file -- 2.34.1