[llvm-commits] CVS: llvm/lib/Transforms/IPO/ArgumentPromotion.cpp

Chris Lattner lattner at cs.uiuc.edu
Sat Nov 13 15:31:46 PST 2004



Changes in directory llvm/lib/Transforms/IPO:

ArgumentPromotion.cpp updated: 1.13 -> 1.14
---
Log message:

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.


---
Diffs of the changes:  (+51 -3)

Index: llvm/lib/Transforms/IPO/ArgumentPromotion.cpp
diff -u llvm/lib/Transforms/IPO/ArgumentPromotion.cpp:1.13 llvm/lib/Transforms/IPO/ArgumentPromotion.cpp:1.14
--- llvm/lib/Transforms/IPO/ArgumentPromotion.cpp:1.13	Sun Sep 19 23:43:34 2004
+++ llvm/lib/Transforms/IPO/ArgumentPromotion.cpp	Sat Nov 13 17:31:34 2004
@@ -87,6 +87,7 @@
     // 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 @@
   return true;
 }
 
+/// IsAlwaysValidPointer - Return true if the specified pointer is always legal
+/// to load.
+static bool IsAlwaysValidPointer(Value *V) {
+  if (isa<AllocaInst>(V) || isa<GlobalVariable>(V)) return true;
+  if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(V))
+    return IsAlwaysValidPointer(GEP->getOperand(0));
+  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(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::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<LoadInst*> Loads;
   std::vector<std::vector<ConstantInt*> > GEPIndices;
   for (Value::use_iterator UI = Arg->use_begin(), E = Arg->use_end();
@@ -161,6 +197,7 @@
     if (LoadInst *LI = dyn_cast<LoadInst>(*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<GetElementPtrInst>(*UI)) {
       if (GEP->use_empty()) {
         // Dead GEP's cause trouble later.  Just remove them if we run into
@@ -183,6 +220,7 @@
         if (LoadInst *LI = dyn_cast<LoadInst>(*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 @@
 
   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






More information about the llvm-commits mailing list