[llvm-commits] [llvm-gcc-4.2] r50492 - in /llvm-gcc-4.2/branches/Apple/Tak/gcc: config/i386/llvm-i386-target.h config/i386/llvm-i386.cpp llvm-abi.h llvm-convert.cpp llvm-types.cpp

Bill Wendling isanbard at gmail.com
Wed Apr 30 12:50:27 PDT 2008


Author: void
Date: Wed Apr 30 14:50:27 2008
New Revision: 50492

URL: http://llvm.org/viewvc/llvm-project?rev=50492&view=rev
Log:
Porting r50491 to Tak.

Modified:
    llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h
    llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp
    llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h
    llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp
    llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp

Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h?rev=50492&r1=50491&r2=50492&view=diff

==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h Wed Apr 30 14:50:27 2008
@@ -164,10 +164,20 @@
 llvm_x86_32_should_pass_aggregate_in_mixed_regs(tree, const Type *Ty,
                                                 std::vector<const Type*>&);
 
-#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, E)            \
-  (TARGET_64BIT ?                                                     \
-   llvm_x86_64_should_pass_aggregate_in_mixed_regs((T), (TY), (E)) :  \
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, E)           \
+  (TARGET_64BIT ?                                                    \
+   llvm_x86_64_should_pass_aggregate_in_mixed_regs((T), (TY), (E)) : \
    llvm_x86_32_should_pass_aggregate_in_mixed_regs((T), (TY), (E)))
+
+extern
+bool llvm_x86_64_aggregate_partially_passed_in_regs(std::vector<const Type*>&,
+                                                    std::vector<const Type*>&);
+
+#define LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(E, SE)         \
+  (TARGET_64BIT ?                                              \
+   llvm_x86_64_aggregate_partially_passed_in_regs((E), (SE)) : \
+   false)
+
 #endif /* LLVM_ABI_H */
 
 /* LLVM LOCAL end (ENTIRE FILE!)  */

Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp?rev=50492&r1=50491&r2=50492&view=diff

==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp Wed Apr 30 14:50:27 2008
@@ -744,6 +744,82 @@
   return llvm_x86_64_should_pass_aggregate_in_memory(TreeType, Mode);
 }
 
+/* count_num_registers_uses - Return the number of GPRs and XMMs parameter
+   register used so far. */
+static void count_num_registers_uses(std::vector<const Type*> &ScalarElts,
+                                     unsigned &NumGPRs, unsigned &NumXMMs) {
+  NumGPRs = 0;
+  NumXMMs = 0;
+  for (unsigned i = 0, e = ScalarElts.size(); i != e; ++i) {
+    const Type *Ty = ScalarElts[i];
+    if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) {
+      if (!TARGET_MACHO)
+        continue;
+      if (VTy->getNumElements() == 1)
+        // v1i64 is passed in GPRs on Darwin.
+        ++NumGPRs;
+      else
+        // All other vector scalar values are passed in XMM registers.
+        ++NumXMMs;
+    } else if (Ty->isInteger() || isa<PointerType>(Ty)) {
+      ++NumGPRs;
+    } else {
+      // Floating point scalar argument.
+      assert(Ty->isFloatingPoint() && Ty->isPrimitiveType() &&
+             "Expecting a floating point primitive type!");
+      if (Ty->getTypeID() == Type::FloatTyID
+          || Ty->getTypeID() == Type::DoubleTyID)
+        ++NumXMMs;
+    }
+  }
+}
+
+/* Target hook for llvm-abi.h. This is called when an aggregate is being passed
+   in registers. If there are only enough available parameter registers to pass
+   part of the aggregate, return true. That means the aggregate should instead
+   be passed in memory. */
+bool
+llvm_x86_64_aggregate_partially_passed_in_regs(std::vector<const Type*> &Elts,
+                                         std::vector<const Type*> &ScalarElts) {
+  // Counting number of GPRs and XMMs used so far. According to AMD64 ABI
+  // document: "If there are no registers available for any eightbyte of an
+  // argument, the whole  argument is passed on the stack." X86-64 uses 6
+  // integer 
+  // For example, if two GPRs are required but only one is available, then
+  // both parts will be in memory.
+  // FIXME: This is a temporary solution. To be removed when llvm has first
+  // class aggregate values.
+  unsigned NumGPRs = 0;
+  unsigned NumXMMs = 0;
+  count_num_registers_uses(ScalarElts, NumGPRs, NumXMMs);
+
+  unsigned NumGPRsNeeded = 0;
+  unsigned NumXMMsNeeded = 0;
+  count_num_registers_uses(Elts, NumGPRsNeeded, NumXMMsNeeded);
+
+  bool GPRsSatisfied = true;
+  if (NumGPRsNeeded) {
+    if (NumGPRs < 6) {
+      if ((NumGPRs + NumGPRsNeeded) > 6)
+        // Only partially satisfied.
+        return true;
+    } else
+      GPRsSatisfied = false;
+  }
+
+  bool XMMsSatisfied = true;
+  if (NumXMMsNeeded) {
+    if (NumXMMs < 8) {
+      if ((NumXMMs + NumXMMsNeeded) > 8)
+        // Only partially satisfied.
+        return true;
+    } else
+      XMMsSatisfied = false;
+  }
+
+  return !GPRsSatisfied || !XMMsSatisfied;
+}
+
 /* Target hook for llvm-abi.h. It returns true if an aggregate of the
    specified type should be passed in a number of registers of mixed types.
    It also returns a vector of types that correspond to the registers used
@@ -792,17 +868,19 @@
               Ty = STy->getElementType(0);
           if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) {
             if (VTy->getNumElements() == 2) {
-              if (VTy->getElementType()->isInteger())
+              if (VTy->getElementType()->isInteger()) {
                 Elts.push_back(VectorType::get(Type::Int64Ty, 2));
-              else
+              } else {
                 Elts.push_back(VectorType::get(Type::DoubleTy, 2));
+              }
               Bytes -= 8;
             } else {
               assert(VTy->getNumElements() == 4);
-              if (VTy->getElementType()->isInteger())
+              if (VTy->getElementType()->isInteger()) {
                 Elts.push_back(VectorType::get(Type::Int32Ty, 4));
-              else
+              } else {
                 Elts.push_back(VectorType::get(Type::FloatTy, 4));
+              }
               Bytes -= 4;
             }
           } else if (llvm_x86_is_all_integer_types(Ty)) {
@@ -850,6 +928,7 @@
     default: assert(0 && "Unexpected register class!");
     }
   }
+
   return true;
 }
 

Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h?rev=50492&r1=50491&r2=50492&view=diff

==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h Wed Apr 30 14:50:27 2008
@@ -247,6 +247,16 @@
     false
 #endif
 
+// LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS - Only called if
+// LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS returns true. This returns true if
+// there are only enough unused argument passing registers to pass a part of
+// the aggregate. Note, this routine should return false if none of the needed
+// registers are available.
+#ifndef LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS
+#define LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(E, SE) \
+    false
+#endif
+
 // LLVM_BYVAL_ALIGNMENT - Returns the alignment of the type in bytes, if known,
 // in the context of its use as a function parameter.
 // Note that the alignment in the TYPE node is usually the alignment appropriate
@@ -387,23 +397,37 @@
   /// argument and invokes methods on the client that indicate how its pieces
   /// should be handled.  This handles things like decimating structures into
   /// their fields.
-  void HandleArgument(tree type, ParameterAttributes *Attributes = NULL) {
+  void HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
+                      ParameterAttributes *Attributes = NULL) {
     const Type *Ty = ConvertType(type);
     // Figure out if this field is zero bits wide, e.g. {} or [0 x int].  Do
     // not include variable sized fields here.
     std::vector<const Type*> Elts;
     if (isPassedByInvisibleReference(type)) { // variable size -> by-ref.
-      C.HandleByInvisibleReferenceArgument(PointerType::getUnqual(Ty), type);
+      const Type *PtrTy = PointerType::getUnqual(Ty);
+      C.HandleByInvisibleReferenceArgument(PtrTy, type);
+      ScalarElts.push_back(PtrTy);
     } else if (Ty->getTypeID()==Type::VectorTyID) {
       if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
-        PassInIntegerRegisters(type, Ty);
+        PassInIntegerRegisters(type, Ty, ScalarElts);
       } else {
         C.HandleScalarArgument(Ty, type);
+        ScalarElts.push_back(Ty);
       }
     } else if (Ty->isFirstClassType()) {
       C.HandleScalarArgument(Ty, type);
+      ScalarElts.push_back(Ty);
     } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty, Elts)) {
-      PassInMixedRegisters(type, Ty, Elts);
+      if (!LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Elts, ScalarElts))
+        PassInMixedRegisters(type, Ty, Elts, ScalarElts);
+      else {
+        C.HandleByValArgument(Ty, type);
+        if (Attributes) {
+          *Attributes |= ParamAttr::ByVal;
+          *Attributes |= 
+            ParamAttr::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
+        }
+      }
     } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty)) {
       C.HandleByValArgument(Ty, type);
       if (Attributes) {
@@ -412,7 +436,7 @@
           ParamAttr::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
       }
     } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type)) {
-      PassInIntegerRegisters(type, Ty);
+      PassInIntegerRegisters(type, Ty, ScalarElts);
     } else if (isZeroSizedStructOrUnion(type)) {
       // Zero sized struct or union, just drop it!
       ;
@@ -423,24 +447,24 @@
           assert(FNo != ~0U && "Case not handled yet!");
           
           C.EnterField(FNo, Ty);
-          HandleArgument(getDeclaredType(Field));
+          HandleArgument(getDeclaredType(Field), ScalarElts);
           C.ExitField();
         }
     } else if (TREE_CODE(type) == COMPLEX_TYPE) {
       C.EnterField(0, Ty);
-      HandleArgument(TREE_TYPE(type));
+      HandleArgument(TREE_TYPE(type), ScalarElts);
       C.ExitField();
       C.EnterField(1, Ty);
-      HandleArgument(TREE_TYPE(type));
+      HandleArgument(TREE_TYPE(type), ScalarElts);
       C.ExitField();
     } else if ((TREE_CODE(type) == UNION_TYPE) ||
                (TREE_CODE(type) == QUAL_UNION_TYPE)) {
-      HandleUnion(type);
+      HandleUnion(type, ScalarElts);
     } else if (TREE_CODE(type) == ARRAY_TYPE) {
       const ArrayType *ATy = cast<ArrayType>(Ty);
       for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
         C.EnterField(i, Ty);
-        HandleArgument(TREE_TYPE(type));
+        HandleArgument(TREE_TYPE(type), ScalarElts);
         C.ExitField();
       }
     } else {
@@ -451,7 +475,7 @@
 
   /// HandleUnion - Handle a UNION_TYPE or QUAL_UNION_TYPE tree.
   ///
-  void HandleUnion(tree type) {
+  void HandleUnion(tree type, std::vector<const Type*> &ScalarElts) {
     if (TYPE_TRANSPARENT_UNION(type)) {
       tree Field = TYPE_FIELDS(type);
       assert(Field && "Transparent union must have some elements!");
@@ -460,7 +484,7 @@
         assert(Field && "Transparent union must have some elements!");
       }
       
-      HandleArgument(TREE_TYPE(Field));
+      HandleArgument(TREE_TYPE(Field), ScalarElts);
     } else {
       // Unions pass the largest element.
       unsigned MaxSize = 0;
@@ -487,14 +511,15 @@
       }
       
       if (MaxElt)
-        HandleArgument(TREE_TYPE(MaxElt));
+        HandleArgument(TREE_TYPE(MaxElt), ScalarElts);
     }
   }
     
   /// PassInIntegerRegisters - Given an aggregate value that should be passed in
   /// integer registers, convert it to a structure containing ints and pass all
   /// of the struct elements in.
-  void PassInIntegerRegisters(tree type, const Type *Ty) {
+  void PassInIntegerRegisters(tree type, const Type *Ty,
+                              std::vector<const Type*> &ScalarElts) {
     unsigned Size = TREE_INT_CST_LOW(TYPE_SIZE(type))/8;
 
     // FIXME: We should preserve all aggregate value alignment information.
@@ -543,6 +568,7 @@
       for (unsigned j = 0; j < ArraySize; ++j) {
         C.EnterField(j, ATy);
         C.HandleScalarArgument(ArrayElementType, 0);
+        ScalarElts.push_back(ArrayElementType);
         C.ExitField();
       }
       C.ExitField();
@@ -551,6 +577,7 @@
     for (unsigned e = Elts.size(); i != e; ++i) {
       C.EnterField(i, STy);
       C.HandleScalarArgument(Elts[i], 0);
+      ScalarElts.push_back(Elts[i]);
       C.ExitField();
     }
   }
@@ -559,11 +586,13 @@
   /// mixed integer, floating point, and vector registers, convert it to a
   /// structure containing the specified struct elements in.
   void PassInMixedRegisters(tree type, const Type *Ty,
-                            std::vector<const Type*> &Elts) {
+                            std::vector<const Type*> &Elts,
+                            std::vector<const Type*> &ScalarElts) {
     const StructType *STy = StructType::get(Elts, false);
     for (unsigned i = 0, e = Elts.size(); i != e; ++i) {
       C.EnterField(i, STy);
       C.HandleScalarArgument(Elts[i], 0);
+      ScalarElts.push_back(Elts[i]);
       C.ExitField();
     }
   }

Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp?rev=50492&r1=50491&r2=50492&view=diff

==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp Wed Apr 30 14:50:27 2008
@@ -498,7 +498,7 @@
       AI->setName(NameStack.back());
       ++AI;
     }
-        
+
     void HandleByValArgument(const llvm::Type *LLVMTy, tree type) {
       // Should not get here.
       abort();
@@ -521,6 +521,22 @@
   };
 }
 
+// isPassedByVal - Return true if an aggregate of the specified type will be
+// passed in memory byval.
+static bool isPassedByVal(tree type, const Type *Ty,
+                          std::vector<const Type*> &ScalarArgs) {
+  if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty))
+    return true;
+
+  std::vector<const Type*> Args;
+  if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty, Args) &&
+      LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Args, ScalarArgs))
+    // We want to pass the whole aggregate in registers but only some of the
+    // registers are available.
+    return true;
+  return false;
+}
+
 void TreeToLLVM::StartFunctionBody() {
   const char *Name = "";
   // Get the name of the function.
@@ -668,6 +684,8 @@
   // Prepend the static chain (if any) to the list of arguments.
   tree Args = static_chain ? static_chain : DECL_ARGUMENTS(FnDecl);
 
+  // Scalar arguments processed so far.
+  std::vector<const Type*> ScalarArgs;
   while (Args) {
     const char *Name = "unnamed_arg";
     if (DECL_NAME(Args)) Name = IDENTIFIER_POINTER(DECL_NAME(Args));
@@ -676,7 +694,7 @@
     bool isInvRef = isPassedByInvisibleReference(TREE_TYPE(Args));
     if (isInvRef ||
         (!ArgTy->isFirstClassType() &&
-         LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(TREE_TYPE(Args), ArgTy))) {
+         isPassedByVal(TREE_TYPE(Args), ArgTy, ScalarArgs))) {
       // If the value is passed by 'invisible reference' or 'byval reference',
       // the l-value for the argument IS the argument itself.
       AI->setName(Name);
@@ -710,7 +728,7 @@
       
       Client.setName(Name);
       Client.setLocation(Tmp);
-      ABIConverter.HandleArgument(TREE_TYPE(Args));
+      ABIConverter.HandleArgument(TREE_TYPE(Args), ScalarArgs);
       Client.clear();
     }
 
@@ -2469,7 +2487,7 @@
 
       // Perform any implicit type conversions.
       if (CallOperands.size() < FTy->getNumParams()) {
-        const Type *CalledTy = FTy->getParamType(CallOperands.size());
+        const Type *CalledTy= FTy->getParamType(CallOperands.size());
         if (Loc->getType() != CalledTy) {
           assert(type && "Inconsistent parameter types?");
           bool isSigned = !TYPE_UNSIGNED(type);
@@ -2581,6 +2599,7 @@
     CallOperands.push_back(Emit(TREE_OPERAND(exp, 2), 0));
 
   // Loop over the arguments, expanding them and adding them to the op list.
+  std::vector<const Type*> ScalarArgs;
   for (tree arg = TREE_OPERAND(exp, 1); arg; arg = TREE_CHAIN(arg)) {
     const Type *ArgTy = ConvertType(TREE_TYPE(TREE_VALUE(arg)));
 
@@ -2596,7 +2615,8 @@
     }
 
     ParameterAttributes Attributes = ParamAttr::None;
-    ABIConverter.HandleArgument(TREE_TYPE(TREE_VALUE(arg)), &Attributes);
+    ABIConverter.HandleArgument(TREE_TYPE(TREE_VALUE(arg)), ScalarArgs,
+                                &Attributes);
     if (Attributes != ParamAttr::None)
       PAL = PAL.addAttr(CallOperands.size(), Attributes);
 

Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp?rev=50492&r1=50491&r2=50492&view=diff

==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp Wed Apr 30 14:50:27 2008
@@ -1068,9 +1068,10 @@
     Attrs.push_back(ParamAttrsWithIndex::get(ArgTys.size(),
                                     ParamAttr::StructRet | ParamAttr::NoAlias));
 
+  std::vector<const Type*> ScalarArgs;
   if (static_chain) {
     // Pass the static chain as the first parameter.
-    ABIConverter.HandleArgument(TREE_TYPE(static_chain));
+    ABIConverter.HandleArgument(TREE_TYPE(static_chain), ScalarArgs);
     // Mark it as the chain argument.
     Attrs.push_back(ParamAttrsWithIndex::get(ArgTys.size(),
                                              ParamAttr::Nest));
@@ -1082,7 +1083,7 @@
     // Determine if there are any attributes for this param.
     ParameterAttributes Attributes = ParamAttr::None;
 
-    ABIConverter.HandleArgument(ArgTy, &Attributes);
+    ABIConverter.HandleArgument(ArgTy, ScalarArgs, &Attributes);
 
     // Compute zext/sext attributes.
     Attributes |= HandleArgumentExtension(ArgTy);
@@ -1165,9 +1166,10 @@
     Attrs.push_back(ParamAttrsWithIndex::get(ArgTypes.size(),
                                     ParamAttr::StructRet | ParamAttr::NoAlias));
 
+  std::vector<const Type*> ScalarArgs;
   if (static_chain) {
     // Pass the static chain as the first parameter.
-    ABIConverter.HandleArgument(TREE_TYPE(static_chain));
+    ABIConverter.HandleArgument(TREE_TYPE(static_chain), ScalarArgs);
     // Mark it as the chain argument.
     Attrs.push_back(ParamAttrsWithIndex::get(ArgTypes.size(),
                                              ParamAttr::Nest));
@@ -1207,7 +1209,7 @@
     // Determine if there are any attributes for this param.
     ParameterAttributes Attributes = ParamAttr::None;
     
-    ABIConverter.HandleArgument(ArgTy, &Attributes);
+    ABIConverter.HandleArgument(ArgTy, ScalarArgs, &Attributes);
 
     // Compute zext/sext attributes.
     Attributes |= HandleArgumentExtension(ArgTy);





More information about the llvm-commits mailing list