[llvm-commits] [llvm] r45973 - in /llvm/trunk: include/llvm/ParameterAttributes.h lib/Transforms/Scalar/InstructionCombining.cpp lib/VMCore/ParameterAttributes.cpp test/Transforms/InstCombine/2008-01-14-DoubleNest.ll test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll

Duncan Sands baldrick at free.fr
Mon Jan 14 11:52:09 PST 2008


Author: baldrick
Date: Mon Jan 14 13:52:09 2008
New Revision: 45973

URL: http://llvm.org/viewvc/llvm-project?rev=45973&view=rev
Log:
I noticed that the trampoline straightening transformation could
drop attributes on varargs call arguments.  Also, it could generate
invalid IR if the transformed call already had the 'nest' attribute
somewhere (this can never happen for code coming from llvm-gcc,
but it's a theoretical possibility).  Fix both problems.

Added:
    llvm/trunk/test/Transforms/InstCombine/2008-01-14-DoubleNest.ll
    llvm/trunk/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll
Modified:
    llvm/trunk/include/llvm/ParameterAttributes.h
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
    llvm/trunk/lib/VMCore/ParameterAttributes.cpp

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

==============================================================================
--- llvm/trunk/include/llvm/ParameterAttributes.h (original)
+++ llvm/trunk/include/llvm/ParameterAttributes.h Mon Jan 14 13:52:09 2008
@@ -53,7 +53,7 @@
 const uint16_t ReturnOnly = NoReturn | NoUnwind | ReadNone | ReadOnly;
 
 /// @brief Parameter attributes that do not apply to vararg call arguments.
-const uint16_t VarArgsIncompatible = Nest | StructRet;
+const uint16_t VarArgsIncompatible = StructRet;
 
 /// @brief Attributes that are mutually incompatible.
 const uint16_t MutuallyIncompatible[3] = {
@@ -171,6 +171,12 @@
       return getParamAttrs(i) & attr;
     }
 
+    /// This returns whether the given attribute is set for at least one
+    /// parameter or for the return value.
+    /// @returns true if the parameter attribute is set somewhere
+    /// @brief Determine if a ParameterAttributes is set somewhere
+    bool hasAttrSomewhere(ParameterAttributes attr) const;
+
     /// The set of ParameterAttributes set in Attributes is converted to a
     /// string of equivalent mnemonics. This is, presumably, for writing out
     /// the mnemonics for the assembly writer. 

Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=45973&r1=45972&r2=45973&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Jan 14 13:52:09 2008
@@ -8385,6 +8385,12 @@
   Value *Callee = CS.getCalledValue();
   const PointerType *PTy = cast<PointerType>(Callee->getType());
   const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+  const ParamAttrsList *Attrs = CS.getParamAttrs();
+
+  // If the call already has the 'nest' attribute somewhere then give up -
+  // otherwise 'nest' would occur twice after splicing in the chain.
+  if (Attrs && Attrs->hasAttrSomewhere(ParamAttr::Nest))
+    return 0;
 
   IntrinsicInst *Tramp =
     cast<IntrinsicInst>(cast<BitCastInst>(Callee)->getOperand(0));
@@ -8414,25 +8420,39 @@
       std::vector<Value*> NewArgs;
       NewArgs.reserve(unsigned(CS.arg_end()-CS.arg_begin())+1);
 
+      ParamAttrsVector NewAttrs;
+      NewAttrs.reserve(Attrs ? Attrs->size() + 1 : 1);
+
       // Insert the nest argument into the call argument list, which may
-      // mean appending it.
+      // mean appending it.  Likewise for attributes.
+
+      // Add any function result attributes.
+      uint16_t Attr = Attrs ? Attrs->getParamAttrs(0) : 0;
+      if (Attr)
+        NewAttrs.push_back (ParamAttrsWithIndex::get(0, Attr));
+
       {
         unsigned Idx = 1;
         CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
         do {
           if (Idx == NestIdx) {
-            // Add the chain argument.
+            // Add the chain argument and attributes.
             Value *NestVal = Tramp->getOperand(3);
             if (NestVal->getType() != NestTy)
               NestVal = new BitCastInst(NestVal, NestTy, "nest", Caller);
             NewArgs.push_back(NestVal);
+            NewAttrs.push_back(ParamAttrsWithIndex::get(NestIdx, NestAttr));
           }
 
           if (I == E)
             break;
 
-          // Add the original argument.
+          // Add the original argument and attributes.
           NewArgs.push_back(*I);
+          Attr = Attrs ? Attrs->getParamAttrs(Idx) : 0;
+          if (Attr)
+            NewAttrs.push_back
+              (ParamAttrsWithIndex::get(Idx + (Idx >= NestIdx), Attr));
 
           ++Idx, ++I;
         } while (1);
@@ -8440,41 +8460,28 @@
 
       // The trampoline may have been bitcast to a bogus type (FTy).
       // Handle this by synthesizing a new function type, equal to FTy
-      // with the chain parameter inserted.  Likewise for attributes.
+      // with the chain parameter inserted.
 
-      const ParamAttrsList *Attrs = CS.getParamAttrs();
       std::vector<const Type*> NewTypes;
-      ParamAttrsVector NewAttrs;
       NewTypes.reserve(FTy->getNumParams()+1);
 
-      // Add any function result attributes.
-      uint16_t Attr = Attrs ? Attrs->getParamAttrs(0) : 0;
-      if (Attr)
-        NewAttrs.push_back (ParamAttrsWithIndex::get(0, Attr));
-
       // Insert the chain's type into the list of parameter types, which may
-      // mean appending it.  Likewise for the chain's attributes.
+      // mean appending it.
       {
         unsigned Idx = 1;
         FunctionType::param_iterator I = FTy->param_begin(),
           E = FTy->param_end();
 
         do {
-          if (Idx == NestIdx) {
-            // Add the chain's type and attributes.
+          if (Idx == NestIdx)
+            // Add the chain's type.
             NewTypes.push_back(NestTy);
-            NewAttrs.push_back(ParamAttrsWithIndex::get(NestIdx, NestAttr));
-          }
 
           if (I == E)
             break;
 
-          // Add the original type and attributes.
+          // Add the original type.
           NewTypes.push_back(*I);
-          Attr = Attrs ? Attrs->getParamAttrs(Idx) : 0;
-          if (Attr)
-            NewAttrs.push_back
-              (ParamAttrsWithIndex::get(Idx + (Idx >= NestIdx), Attr));
 
           ++Idx, ++I;
         } while (1);

Modified: llvm/trunk/lib/VMCore/ParameterAttributes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/ParameterAttributes.cpp?rev=45973&r1=45972&r2=45973&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/ParameterAttributes.cpp (original)
+++ llvm/trunk/lib/VMCore/ParameterAttributes.cpp Mon Jan 14 13:52:09 2008
@@ -36,6 +36,13 @@
   return ParamAttr::None;
 }
 
+bool ParamAttrsList::hasAttrSomewhere(ParameterAttributes attr) const {
+  for (unsigned i = 0, e = attrs.size(); i < e; ++i)
+    if (attrs[i].attrs & attr)
+      return true;
+  return false;
+}
+
 std::string 
 ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
   std::string Result;

Added: llvm/trunk/test/Transforms/InstCombine/2008-01-14-DoubleNest.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-01-14-DoubleNest.ll?rev=45973&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2008-01-14-DoubleNest.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2008-01-14-DoubleNest.ll Mon Jan 14 13:52:09 2008
@@ -0,0 +1,24 @@
+; RUN: llvm-as < %s | opt -instcombine -disable-output
+
+	%struct.FRAME.nest = type { i32, i32 (i32*)* }
+	%struct.__builtin_trampoline = type { [10 x i8] }
+
+declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind 
+
+declare i32 @f(%struct.FRAME.nest* nest , i32*)
+
+define i32 @nest(i32 %n) {
+entry:
+	%FRAME.0 = alloca %struct.FRAME.nest, align 8		; <%struct.FRAME.nest*> [#uses=3]
+	%TRAMP.216 = alloca [10 x i8], align 16		; <[10 x i8]*> [#uses=1]
+	%TRAMP.216.sub = getelementptr [10 x i8]* %TRAMP.216, i32 0, i32 0		; <i8*> [#uses=1]
+	%tmp3 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 0		; <i32*> [#uses=1]
+	store i32 %n, i32* %tmp3, align 8
+	%FRAME.06 = bitcast %struct.FRAME.nest* %FRAME.0 to i8*		; <i8*> [#uses=1]
+	%tramp = call i8* @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest*, i32*)* @f to i8*), i8* %FRAME.06 )		; <i8*> [#uses=1]
+	%tmp7 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 1		; <i32 (i32*)**> [#uses=1]
+	%tmp89 = bitcast i8* %tramp to i32 (i32*)*		; <i32 (i32*)*> [#uses=2]
+	store i32 (i32*)* %tmp89, i32 (i32*)** %tmp7, align 8
+	%tmp2.i = call i32 %tmp89( i32* nest  null )		; <i32> [#uses=1]
+	ret i32 %tmp2.i
+}

Added: llvm/trunk/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll?rev=45973&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2008-01-14-VarArgTrampoline.ll Mon Jan 14 13:52:09 2008
@@ -0,0 +1,24 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep zeroext
+
+	%struct.FRAME.nest = type { i32, i32 (...)* }
+	%struct.__builtin_trampoline = type { [10 x i8] }
+
+declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind 
+
+declare i32 @f(%struct.FRAME.nest* nest , ...)
+
+define i32 @nest(i32 %n) {
+entry:
+	%FRAME.0 = alloca %struct.FRAME.nest, align 8		; <%struct.FRAME.nest*> [#uses=3]
+	%TRAMP.216 = alloca [10 x i8], align 16		; <[10 x i8]*> [#uses=1]
+	%TRAMP.216.sub = getelementptr [10 x i8]* %TRAMP.216, i32 0, i32 0		; <i8*> [#uses=1]
+	%tmp3 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 0		; <i32*> [#uses=1]
+	store i32 %n, i32* %tmp3, align 8
+	%FRAME.06 = bitcast %struct.FRAME.nest* %FRAME.0 to i8*		; <i8*> [#uses=1]
+	%tramp = call i8* @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest*, ...)* @f to i8*), i8* %FRAME.06 )		; <i8*> [#uses=1]
+	%tmp7 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 1		; <i32 (...)**> [#uses=1]
+	%tmp89 = bitcast i8* %tramp to i32 (...)*		; <i32 (...)*> [#uses=2]
+	store i32 (...)* %tmp89, i32 (...)** %tmp7, align 8
+	%tmp2.i = call i32 (...)* %tmp89( i32 zeroext 0 )		; <i32> [#uses=1]
+	ret i32 %tmp2.i
+}





More information about the llvm-commits mailing list