[llvm-commits] [llvm] r44315 - in /llvm/trunk: include/llvm/ParameterAttributes.h lib/Transforms/Scalar/InstructionCombining.cpp lib/VMCore/Function.cpp lib/VMCore/Verifier.cpp test/Transforms/InstCombine/2007-11-25-CompatibleAttributes.ll

Duncan Sands baldrick at free.fr
Sun Nov 25 06:10:57 PST 2007


Author: baldrick
Date: Sun Nov 25 08:10:56 2007
New Revision: 44315

URL: http://llvm.org/viewvc/llvm-project?rev=44315&view=rev
Log:
Fix PR1816.  If a bitcast of a function only exists because of a
trivial difference in function attributes, allow calls to it to
be converted to direct calls.  Based on a patch by Török Edwin.
While there, move the various lists of mutually incompatible
parameters etc out of the verifier and into ParameterAttributes.h.

Added:
    llvm/trunk/test/Transforms/InstCombine/2007-11-25-CompatibleAttributes.ll
Modified:
    llvm/trunk/include/llvm/ParameterAttributes.h
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
    llvm/trunk/lib/VMCore/Function.cpp
    llvm/trunk/lib/VMCore/Verifier.cpp

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

==============================================================================
--- llvm/trunk/include/llvm/ParameterAttributes.h (original)
+++ llvm/trunk/include/llvm/ParameterAttributes.h Sun Nov 25 08:10:56 2007
@@ -43,6 +43,34 @@
   ReadOnly   = 1 << 10  ///< Function only reads from memory
 };
 
+/// These attributes can safely be dropped from a function or a function call:
+/// doing so may reduce the number of optimizations performed, but it will not
+/// change a correct program into an incorrect one.
+/// @brief Attributes that do not change the calling convention.
+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;
+
+/// @brief Attributes that only apply to function return values.
+const uint16_t ReturnOnly = NoReturn | NoUnwind | ReadNone | ReadOnly;
+
+/// @brief Attributes that only apply to integers.
+const uint16_t IntegerTypeOnly = SExt | ZExt;
+
+/// @brief Attributes that only apply to pointers.
+const uint16_t PointerTypeOnly = ByVal | Nest | NoAlias | StructRet;
+
+/// @brief Attributes that are mutually incompatible.
+const uint16_t MutuallyIncompatible[3] = {
+  ByVal | InReg | Nest  | StructRet,
+  ZExt  | SExt,
+  ReadNone | ReadOnly
+};
+
 }
 
 /// This is just a pair of values to associate a set of parameter attributes
@@ -110,6 +138,11 @@
     /// @brief Get a ParamAttrsList instance.
     static ParamAttrsList *get(const ParamAttrsVector &attrVec);
 
+    /// Returns whether each of the specified lists of attributes can be safely
+    /// replaced with the other in a function or a function call.
+    /// @brief Whether one attribute list can safely replace the other.
+    static bool areCompatible(const ParamAttrsList *A, const ParamAttrsList *B);
+
   /// @}
   /// @name Accessors
   /// @{

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sun Nov 25 08:10:56 2007
@@ -7990,11 +7990,12 @@
   const FunctionType *ActualFT =
     cast<FunctionType>(cast<PointerType>(CE->getType())->getElementType());
   
-  // If the parameter attributes don't match up, don't do the xform.  We don't
-  // want to lose an sret attribute or something.
-  if (FT->getParamAttrs() != ActualFT->getParamAttrs())
+  // If the parameter attributes are not compatible, don't do the xform.  We
+  // don't want to lose an sret attribute or something.
+  if (!ParamAttrsList::areCompatible(FT->getParamAttrs(),
+                                     ActualFT->getParamAttrs()))
     return false;
-  
+
   // Check to see if we are changing the return type...
   if (OldRetTy != FT->getReturnType()) {
     if (Callee->isDeclaration() && !Caller->use_empty() && 

Modified: llvm/trunk/lib/VMCore/Function.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Function.cpp?rev=44315&r1=44314&r2=44315&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Function.cpp (original)
+++ llvm/trunk/lib/VMCore/Function.cpp Sun Nov 25 08:10:56 2007
@@ -86,7 +86,6 @@
   return ParamAttr::None;
 }
 
-
 std::string 
 ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
   std::string Result;
@@ -115,6 +114,50 @@
   return Result;
 }
 
+/// onlyInformative - Returns whether only informative attributes are set.
+static inline bool onlyInformative(uint16_t attrs) {
+  return !(attrs & ~ParamAttr::Informative);
+}
+
+bool
+ParamAttrsList::areCompatible(const ParamAttrsList *A, const ParamAttrsList *B){
+  if (A == B)
+    return true;
+  unsigned ASize = A ? A->size() : 0;
+  unsigned BSize = B ? B->size() : 0;
+  unsigned AIndex = 0;
+  unsigned BIndex = 0;
+
+  while (AIndex < ASize && BIndex < BSize) {
+    uint16_t AIdx = A->getParamIndex(AIndex);
+    uint16_t BIdx = B->getParamIndex(BIndex);
+    uint16_t AAttrs = A->getParamAttrsAtIndex(AIndex);
+    uint16_t BAttrs = B->getParamAttrsAtIndex(AIndex);
+
+    if (AIdx < BIdx) {
+      if (!onlyInformative(AAttrs))
+        return false;
+      ++AIndex;
+    } else if (BIdx < AIdx) {
+      if (!onlyInformative(BAttrs))
+        return false;
+      ++BIndex;
+    } else {
+      if (!onlyInformative(AAttrs ^ BAttrs))
+        return false;
+      ++AIndex;
+      ++BIndex;
+    }
+  }
+  for (; AIndex < ASize; ++AIndex)
+    if (!onlyInformative(A->getParamAttrsAtIndex(AIndex)))
+      return false;
+  for (; BIndex < BSize; ++BIndex)
+    if (!onlyInformative(B->getParamAttrsAtIndex(AIndex)))
+      return false;
+  return true;
+}
+
 void 
 ParamAttrsList::Profile(FoldingSetNodeID &ID) const {
   for (unsigned i = 0; i < attrs.size(); ++i) {

Modified: llvm/trunk/lib/VMCore/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=44315&r1=44314&r2=44315&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Verifier.cpp (original)
+++ llvm/trunk/lib/VMCore/Verifier.cpp Sun Nov 25 08:10:56 2007
@@ -393,30 +393,6 @@
   Assert1(!FT->isStructReturn() || FT->getReturnType() == Type::VoidTy,
           "Invalid struct-return function!", &F);
 
-  const uint16_t ReturnIncompatible =
-    ParamAttr::ByVal | ParamAttr::InReg |
-    ParamAttr::Nest  | ParamAttr::StructRet;
-
-  const uint16_t ParameterIncompatible =
-    ParamAttr::NoReturn | ParamAttr::NoUnwind |
-    ParamAttr::ReadNone | ParamAttr::ReadOnly;
-
-  const uint16_t MutuallyIncompatible[3] = {
-    ParamAttr::ByVal | ParamAttr::InReg |
-    ParamAttr::Nest  | ParamAttr::StructRet,
-
-    ParamAttr::ZExt | ParamAttr::SExt,
-
-    ParamAttr::ReadNone | ParamAttr::ReadOnly
-  };
-
-  const uint16_t IntegerTypeOnly =
-    ParamAttr::SExt | ParamAttr::ZExt;
-
-  const uint16_t PointerTypeOnly =
-    ParamAttr::ByVal   | ParamAttr::Nest |
-    ParamAttr::NoAlias | ParamAttr::StructRet;
-
   bool SawSRet = false;
 
   if (const ParamAttrsList *Attrs = FT->getParamAttrs()) {
@@ -426,28 +402,29 @@
       uint16_t Attr = Attrs->getParamAttrs(Idx);
 
       if (!Idx) {
-        uint16_t RetI = Attr & ReturnIncompatible;
+        uint16_t RetI = Attr & ParamAttr::ParameterOnly;
         Assert1(!RetI, "Attribute " + Attrs->getParamAttrsText(RetI) +
                 "should not apply to functions!", &F);
       } else {
-        uint16_t ParmI = Attr & ParameterIncompatible;
+        uint16_t ParmI = Attr & ParamAttr::ReturnOnly;
         Assert1(!ParmI, "Attribute " + Attrs->getParamAttrsText(ParmI) +
                 "should only be applied to function!", &F);
 
       }
 
-      for (unsigned i = 0; i < array_lengthof(MutuallyIncompatible); ++i) {
-        uint16_t MutI = Attr & MutuallyIncompatible[i];
+      for (unsigned i = 0;
+           i < array_lengthof(ParamAttr::MutuallyIncompatible); ++i) {
+        uint16_t MutI = Attr & ParamAttr::MutuallyIncompatible[i];
         Assert1(!(MutI & (MutI - 1)), "Attributes " +
                 Attrs->getParamAttrsText(MutI) + "are incompatible!", &F);
       }
 
-      uint16_t IType = Attr & IntegerTypeOnly;
+      uint16_t IType = Attr & ParamAttr::IntegerTypeOnly;
       Assert1(!IType || FT->getParamType(Idx-1)->isInteger(),
               "Attribute " + Attrs->getParamAttrsText(IType) +
               "should only apply to Integer type!", &F);
 
-      uint16_t PType = Attr & PointerTypeOnly;
+      uint16_t PType = Attr & ParamAttr::PointerTypeOnly;
       Assert1(!PType || isa<PointerType>(FT->getParamType(Idx-1)),
               "Attribute " + Attrs->getParamAttrsText(PType) +
               "should only apply to Pointer type!", &F);

Added: llvm/trunk/test/Transforms/InstCombine/2007-11-25-CompatibleAttributes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2007-11-25-CompatibleAttributes.ll?rev=44315&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2007-11-25-CompatibleAttributes.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/2007-11-25-CompatibleAttributes.ll Sun Nov 25 08:10:56 2007
@@ -0,0 +1,12 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep bitcast
+; PR1716
+
+ at .str = internal constant [4 x i8] c"%d\0A\00"		; <[4 x i8]*> [#uses=1]
+
+define i32 @main(i32 %argc, i8** %argv) {
+entry:
+	%tmp32 = tail call i32 (i8* noalias , ...) nounwind * bitcast (i32 (i8*, ...) nounwind * @printf to i32 (i8* noalias , ...) nounwind *)( i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0) noalias , i32 0 ) nounwind 		; <i32> [#uses=0]
+	ret i32 undef
+}
+
+declare i32 @printf(i8*, ...) nounwind 





More information about the llvm-commits mailing list