From 11a3d7b7ddd10659b72ed248d878fa0d90ddcb45 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 13 Nov 2004 23:31:34 +0000 Subject: [PATCH] Argument promotion transforms functions to unconditionally load their argument pointers. This is only valid to do if the function already unconditionally loaded an argument or if the pointer passed in is known to be valid. Make sure to do the required checks. This fixed ArgumentPromotion/control-flow.ll and the Burg program. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@17718 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/ArgumentPromotion.cpp | 54 ++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp index 85339bf9a70..927c60a23fb 100644 --- a/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -87,6 +87,7 @@ bool ArgPromotion::runOnSCC(const std::vector &SCC) { // Attempt to promote arguments from all functions in this SCC. for (unsigned i = 0, e = SCC.size(); i != e; ++i) LocalChange |= PromoteArguments(SCC[i]); + if (LocalChange) return true; Changed |= LocalChange; // Remember that we changed something. } while (LocalChange); @@ -145,6 +146,39 @@ bool ArgPromotion::PromoteArguments(CallGraphNode *CGN) { return true; } +/// IsAlwaysValidPointer - Return true if the specified pointer is always legal +/// to load. +static bool IsAlwaysValidPointer(Value *V) { + if (isa(V) || isa(V)) return true; + if (GetElementPtrInst *GEP = dyn_cast(V)) + return IsAlwaysValidPointer(GEP->getOperand(0)); + if (ConstantExpr *CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::GetElementPtr) + return IsAlwaysValidPointer(CE->getOperand(0)); + + return false; +} + +/// AllCalleesPassInValidPointerForArgument - Return true if we can prove that +/// all callees pass in a valid pointer for the specified function argument. +static bool AllCalleesPassInValidPointerForArgument(Argument *Arg) { + Function *Callee = Arg->getParent(); + + unsigned ArgNo = std::distance(Callee->abegin(), Function::aiterator(Arg)); + + // Look at all call sites of the function. At this pointer we know we only + // have direct callees. + for (Value::use_iterator UI = Callee->use_begin(), E = Callee->use_end(); + UI != E; ++UI) { + CallSite CS = CallSite::get(*UI); + assert(CS.getInstruction() && "Should only have direct calls!"); + + if (!IsAlwaysValidPointer(CS.getArgument(ArgNo))) + return false; + } + return true; +} + /// isSafeToPromoteArgument - As you might guess from the name of this method, /// it checks to see if it is both safe and useful to promote the argument. @@ -154,6 +188,8 @@ bool ArgPromotion::PromoteArguments(CallGraphNode *CGN) { bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg) const { // 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; + BasicBlock *EntryBlock = Arg->getParent()->begin(); std::vector Loads; std::vector > GEPIndices; for (Value::use_iterator UI = Arg->use_begin(), E = Arg->use_end(); @@ -161,6 +197,7 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg) const { if (LoadInst *LI = dyn_cast(*UI)) { if (LI->isVolatile()) return false; // Don't hack volatile loads Loads.push_back(LI); + HasLoadInEntryBlock |= LI->getParent() == EntryBlock; } else if (GetElementPtrInst *GEP = dyn_cast(*UI)) { if (GEP->use_empty()) { // Dead GEP's cause trouble later. Just remove them if we run into @@ -183,6 +220,7 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg) const { if (LoadInst *LI = dyn_cast(*UI)) { if (LI->isVolatile()) return false; // Don't hack volatile loads Loads.push_back(LI); + HasLoadInEntryBlock |= LI->getParent() == EntryBlock; } else { return false; } @@ -208,9 +246,19 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg) const { if (Loads.empty()) return true; // No users, this is a dead argument. - // Okay, now we know that the argument is only used by load instructions. Use - // alias analysis to check to see if the pointer is guaranteed to not be - // modified from entry of the function to each of the load instructions. + // If we decide that we want to promote this argument, the value is going to + // be unconditionally loaded in all callees. This is only safe to do if the + // pointer was going to be unconditionally loaded anyway (i.e. there is a load + // of the pointer in the entry block of the function) or if we can prove that + // all pointers passed in are always to legal locations (for example, no null + // pointers are passed in, no pointers to free'd memory, etc). + if (!HasLoadInEntryBlock && !AllCalleesPassInValidPointerForArgument(Arg)) + return false; // Cannot prove that this is safe!! + + // Okay, now we know that the argument is only used by load instructions and + // it is safe to unconditionally load the pointer. Use alias analysis to + // check to see if the pointer is guaranteed to not be modified from entry of + // the function to each of the load instructions. Function &F = *Arg->getParent(); // Because there could be several/many load instructions, remember which