[llvm-commits] [llvm] r45285 - in /llvm/trunk: include/llvm/ParameterAttributes.h lib/Transforms/IPO/DeadArgumentElimination.cpp test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll

Duncan Sands baldrick at free.fr
Fri Dec 21 11:16:17 PST 2007


Author: baldrick
Date: Fri Dec 21 13:16:16 2007
New Revision: 45285

URL: http://llvm.org/viewvc/llvm-project?rev=45285&view=rev
Log:
Make DAE not wipe out attributes on calls, and not drop
return attributes on the floor.  In the case of a call
to a varargs function where the varargs arguments are
being removed, any call attributes on those arguments
need to be dropped.  I didn't do this because I plan to
make it illegal to have such attributes (see next patch).
With this change, compiling the gcc filter2 eh test at -O0
and then running opt -std-compile-opts on it results in
a correctly working program (compiling at -O1 or higher
results in the test failing due to a problem with how we
output eh info into the IR).

Added:
    llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll
Modified:
    llvm/trunk/include/llvm/ParameterAttributes.h
    llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp

Modified: llvm/trunk/include/llvm/ParameterAttributes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ParameterAttributes.h?rev=45285&r1=45284&r2=45285&view=diff

==============================================================================
--- llvm/trunk/include/llvm/ParameterAttributes.h (original)
+++ llvm/trunk/include/llvm/ParameterAttributes.h Fri Dec 21 13:16:16 2007
@@ -50,8 +50,6 @@
 const uint16_t Informative = NoReturn | NoUnwind | NoAlias |
                              ReadNone | ReadOnly;
 
-/// The following attribute sets are used by the verifier:
-
 /// @brief Attributes that only apply to function parameters.
 const uint16_t ParameterOnly = ByVal | InReg | Nest | StructRet;
 
@@ -64,6 +62,10 @@
 /// @brief Attributes that only apply to pointers.
 const uint16_t PointerTypeOnly = ByVal | Nest | NoAlias | StructRet;
 
+/// @brief Attributes that do not apply to void type function return values.
+const uint16_t VoidTypeIncompatible = IntegerTypeOnly | PointerTypeOnly |
+                                      ParameterOnly;
+
 /// @brief Attributes that are mutually incompatible.
 const uint16_t MutuallyIncompatible[3] = {
   ByVal | InReg | Nest  | StructRet,

Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=45285&r1=45284&r2=45285&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Fri Dec 21 13:16:16 2007
@@ -122,18 +122,18 @@
 bool DAE::DeleteDeadVarargs(Function &Fn) {
   assert(Fn.getFunctionType()->isVarArg() && "Function isn't varargs!");
   if (Fn.isDeclaration() || !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) {
@@ -144,24 +144,24 @@
       }
     }
   }
-  
+
   // 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());
   NF->setCallingConv(Fn.getCallingConv());
   NF->setParamAttrs(Fn.getParamAttrs());
   Fn.getParent()->getFunctionList().insert(&Fn, NF);
   NF->takeName(&Fn);
-  
+
   // 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.
   //
@@ -169,40 +169,40 @@
   while (!Fn.use_empty()) {
     CallSite CS = CallSite::get(Fn.use_back());
     Instruction *Call = CS.getInstruction();
-    
+
     // Pass all the same arguments.
     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.begin(), Args.end(), "", Call);
       cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
-      cast<InvokeInst>(New)->setParamAttrs(NF->getParamAttrs());
+      cast<InvokeInst>(New)->setParamAttrs(CS.getParamAttrs());
     } else {
       New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
       cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
-      cast<CallInst>(New)->setParamAttrs(NF->getParamAttrs());
+      cast<CallInst>(New)->setParamAttrs(CS.getParamAttrs());
       if (cast<CallInst>(Call)->isTailCall())
         cast<CallInst>(New)->setTailCall();
     }
     Args.clear();
-    
+
     if (!Call->use_empty())
       Call->replaceAllUsesWith(New);
-    
+
     New->takeName(Call);
-    
+
     // Finally, remove the old call from the program, reducing the use-count of
     // F.
     Call->eraseFromParent();
   }
-  
+
   // 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.
@@ -213,7 +213,7 @@
     I->replaceAllUsesWith(I2);
     I2->takeName(I);
   }
-  
+
   // Finally, nuke the old function.
   Fn.eraseFromParent();
   return true;
@@ -496,6 +496,20 @@
   ParamAttrsVector ParamAttrsVec;
   const ParamAttrsList *PAL = F->getParamAttrs();
 
+  // The existing function return attributes.
+  uint16_t RAttrs = PAL ? PAL->getParamAttrs(0) : 0;
+
+  // Make the function return void if the return value is dead.
+  const Type *RetTy = FTy->getReturnType();
+  if (DeadRetVal.count(F)) {
+    RetTy = Type::VoidTy;
+    RAttrs &= ~ParamAttr::VoidTypeIncompatible;
+    DeadRetVal.erase(F);
+  }
+
+  if (RAttrs)
+    ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs));
+
   // Construct the new parameter list from non-dead arguments. Also construct
   // a new set of parameter attributes to correspond.
   unsigned index = 1;
@@ -503,26 +517,13 @@
        ++I, ++index)
     if (!DeadArguments.count(I)) {
       Params.push_back(I->getType());
-      if (PAL) {
-        uint16_t Attrs = PAL->getParamAttrs(index);
-        if (Attrs != ParamAttr::None)
-          ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(),
-                                  Attrs));
-      }
+      uint16_t Attrs = PAL ? PAL->getParamAttrs(index) : 0;
+      if (Attrs)
+        ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), Attrs));
     }
 
   // Reconstruct the ParamAttrsList based on the vector we constructed.
-  if (ParamAttrsVec.empty())
-    PAL = 0;
-  else
-    PAL = ParamAttrsList::get(ParamAttrsVec);
-
-  // Make the function return void if the return value is dead.
-  const Type *RetTy = FTy->getReturnType();
-  if (DeadRetVal.count(F)) {
-    RetTy = Type::VoidTy;
-    DeadRetVal.erase(F);
-  }
+  PAL = ParamAttrsList::get(ParamAttrsVec);
 
   // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
   // have zero fixed arguments.
@@ -550,13 +551,31 @@
   while (!F->use_empty()) {
     CallSite CS = CallSite::get(F->use_back());
     Instruction *Call = CS.getInstruction();
+    ParamAttrsVec.clear();
+    PAL = CS.getParamAttrs();
+
+    // The call return attributes.
+    uint16_t RAttrs = PAL ? PAL->getParamAttrs(0) : 0;
+    // Adjust in case the function was changed to return void.
+    if (NF->getReturnType() == Type::VoidTy)
+      RAttrs &= ~ParamAttr::VoidTypeIncompatible;
+    if (RAttrs)
+      ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs));
 
     // Loop over the operands, deleting dead ones...
     CallSite::arg_iterator AI = CS.arg_begin();
+    index = 1;
     for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
-         I != E; ++I, ++AI)
-      if (!DeadArguments.count(I))      // Remove operands for dead arguments
+         I != E; ++I, ++AI, ++index)
+      if (!DeadArguments.count(I)) {    // Remove operands for dead arguments
         Args.push_back(*AI);
+        uint16_t Attrs = PAL ? PAL->getParamAttrs(index) : 0;
+        if (Attrs)
+          ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
+      }
+
+    // Reconstruct the ParamAttrsList based on the vector we constructed.
+    PAL = ParamAttrsList::get(ParamAttrsVec);
 
     if (ExtraArgHack)
       Args.push_back(UndefValue::get(Type::Int32Ty));

Added: llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll?rev=45285&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll (added)
+++ llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll Fri Dec 21 13:16:16 2007
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | opt -deadargelim | llvm-dis | grep nounwind | count 2
+; RUN: llvm-as < %s | opt -deadargelim | llvm-dis | grep signext | count 2
+; RUN: llvm-as < %s | opt -deadargelim | llvm-dis | not grep inreg
+; RUN: llvm-as < %s | opt -deadargelim | llvm-dis | not grep zeroext
+
+ at g = global i8 0
+
+define internal i8 @foo(i8* inreg %p, i8 signext %y, ... ) zeroext nounwind {
+	store i8 %y, i8* @g
+	ret i8 0
+}
+
+define i32 @bar() {
+	%A = call i8(i8*, i8, ...)* @foo(i8* inreg null, i8 signext 1, i8 2) zeroext nounwind
+	ret i32 0
+}





More information about the llvm-commits mailing list