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

Chris Lattner sabre at nondot.org
Mon Sep 18 00:02:45 PDT 2006



Changes in directory llvm/lib/Transforms/IPO:

DeadArgumentElimination.cpp updated: 1.28 -> 1.29
---
Log message:

Implement a trivial optzn: of vastart is never called in a function that takes
... args, remove the '...'.

This is Transforms/DeadArgElim/dead_vaargs.ll


---
Diffs of the changes:  (+113 -2)

 DeadArgumentElimination.cpp |  115 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 113 insertions(+), 2 deletions(-)


Index: llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
diff -u llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.28 llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.29
--- llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.28	Sun Aug 27 17:42:52 2006
+++ llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp	Mon Sep 18 02:02:31 2006
@@ -23,6 +23,7 @@
 #include "llvm/Constant.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
 #include "llvm/Module.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/CallSite.h"
@@ -85,6 +86,7 @@
     Liveness getArgumentLiveness(const Argument &A);
     bool isMaybeLiveArgumentNowLive(Argument *Arg);
 
+    bool DeleteDeadVarargs(Function &Fn);
     void SurveyFunction(Function &Fn);
 
     void MarkArgumentLive(Argument *Arg);
@@ -111,6 +113,109 @@
 ModulePass *llvm::createDeadArgEliminationPass() { return new DAE(); }
 ModulePass *llvm::createDeadArgHackingPass() { return new DAH(); }
 
+/// DeleteDeadVarargs - If this is an function that takes a ... list, and if
+/// llvm.vastart is never called, the varargs list is dead for the function.
+bool DAE::DeleteDeadVarargs(Function &Fn) {
+  assert(Fn.getFunctionType()->isVarArg() && "Function isn't varargs!");
+  if (Fn.isExternal() || !Fn.hasInternalLinkage()) return false;
+  
+  // Ensure that the function is only directly called.
+  for (Value::use_iterator I = Fn.use_begin(), E = Fn.use_end(); I != E; ++I) {
+    // If this use is anything other than a call site, give up.
+    CallSite CS = CallSite::get(*I);
+    Instruction *TheCall = CS.getInstruction();
+    if (!TheCall) return false;   // Not a direct call site?
+   
+    // The addr of this function is passed to the call.
+    if (I.getOperandNo() != 0) return false;
+  }
+  
+  // Okay, we know we can transform this function if safe.  Scan its body
+  // looking for calls to llvm.vastart.
+  for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) {
+    for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
+      if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
+        if (II->getIntrinsicID() == Intrinsic::vastart)
+          return false;
+      }
+    }
+  }
+  
+  // If we get here, there are no calls to llvm.vastart in the function body,
+  // remove the "..." and adjust all the calls.
+  
+  // Start by computing a new prototype for the function, which is the same as
+  // the old function, but has fewer arguments.
+  const FunctionType *FTy = Fn.getFunctionType();
+  std::vector<const Type*> Params(FTy->param_begin(), FTy->param_end());
+  FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false);
+  unsigned NumArgs = Params.size();
+  
+  // Create the new function body and insert it into the module...
+  Function *NF = new Function(NFTy, Fn.getLinkage(), Fn.getName());
+  NF->setCallingConv(Fn.getCallingConv());
+  Fn.getParent()->getFunctionList().insert(&Fn, NF);
+  
+  // Loop over all of the callers of the function, transforming the call sites
+  // to pass in a smaller number of arguments into the new function.
+  //
+  std::vector<Value*> Args;
+  while (!Fn.use_empty()) {
+    CallSite CS = CallSite::get(Fn.use_back());
+    Instruction *Call = CS.getInstruction();
+    
+    // Loop over the operands, dropping extraneous ones at the end of the list.
+    Args.assign(CS.arg_begin(), CS.arg_begin()+NumArgs);
+    
+    Instruction *New;
+    if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
+      New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
+                           Args, "", Call);
+      cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
+    } else {
+      New = new CallInst(NF, Args, "", Call);
+      cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
+      if (cast<CallInst>(Call)->isTailCall())
+        cast<CallInst>(New)->setTailCall();
+    }
+    Args.clear();
+    
+    if (!Call->use_empty())
+      Call->replaceAllUsesWith(Constant::getNullValue(Call->getType()));
+    
+    if (Call->hasName()) {
+      std::string Name = Call->getName();
+      Call->setName("");
+      New->setName(Name);
+    }
+    
+    // Finally, remove the old call from the program, reducing the use-count of
+    // F.
+    Call->getParent()->getInstList().erase(Call);
+  }
+  
+  // Since we have now created the new function, splice the body of the old
+  // function right into the new function, leaving the old rotting hulk of the
+  // function empty.
+  NF->getBasicBlockList().splice(NF->begin(), Fn.getBasicBlockList());
+  
+  // Loop over the argument list, transfering uses of the old arguments over to
+  // the new arguments, also transfering over the names as well.  While we're at
+  // it, remove the dead arguments from the DeadArguments list.
+  //
+  for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(),
+       I2 = NF->arg_begin(); I != E; ++I, ++I2) {
+    // Move the name and users over to the new version.
+    I->replaceAllUsesWith(I2);
+    I2->setName(I->getName());
+  }
+  
+  // Finally, nuke the old function.
+  Fn.eraseFromParent();
+  return true;
+}
+
+
 static inline bool CallPassesValueThoughVararg(Instruction *Call,
                                                const Value *Arg) {
   CallSite CS = CallSite::get(Call);
@@ -507,8 +612,14 @@
   // determine that dead arguments passed into recursive functions are dead).
   //
   DEBUG(std::cerr << "DAE - Determining liveness\n");
-  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
-    SurveyFunction(*I);
+  for (Module::iterator I = M.begin(), E = M.end(); I != E; ) {
+    Function &F = *I++;
+    if (F.getFunctionType()->isVarArg())
+      if (DeleteDeadVarargs(F))
+        continue;
+      
+    SurveyFunction(F);
+  }
 
   // Loop over the instructions to inspect, propagating liveness among arguments
   // and return values which are MaybeLive.






More information about the llvm-commits mailing list