[llvm-commits] [llvm-gcc-4.2] r48440 - in /llvm-gcc-4.2/trunk/gcc: config/rs6000/llvm-rs6000.cpp config/rs6000/rs6000.h llvm-abi.h

Dale Johannesen dalej at apple.com
Sun Mar 16 19:21:44 PDT 2008


Author: johannes
Date: Sun Mar 16 21:21:44 2008
New Revision: 48440

URL: http://llvm.org/viewvc/llvm-project?rev=48440&view=rev
Log:
Adjustments for ppc32 ABI.  Pass single-elt structs
(except long double) as if they were the type of the
element.  Handle complex long long & complex double.


Modified:
    llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp
    llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.h
    llvm-gcc-4.2/trunk/gcc/llvm-abi.h

Modified: llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp?rev=48440&r1=48439&r2=48440&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp Sun Mar 16 21:21:44 2008
@@ -26,6 +26,7 @@
 
 #include "llvm-abi.h"
 #include "llvm-internal.h"
+#include "llvm/DerivedTypes.h"
 #include "llvm/Instructions.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/Module.h"
@@ -389,30 +390,61 @@
   if (Bytes == 0)
     return false;
 
-  // If this is a small fixed size type, investigate it.
+  // Large types always use byval.  If this is a small fixed size type, 
+  // investigate it.
   if (Bytes <= 0 || Bytes > 16)
     return true;
 
   // ppc32 passes aggregates by copying, either in int registers or on the 
-  // stack.  If this is an extremely simple aggregate whose elements would be 
-  // passed the same if passed as scalars, pass them that way in order to 
-  // promote SROA on the caller and callee side.
-  // Note that we can't support passing all structs this way.  For example,
-  // {i16, i16} should be passed in on 32-bit unit, which is not how "i16, i16"
-  // would be passed as stand-alone arguments.  And any floating point element
-  // would be passed in float regs, not int.
+  // stack.
   const StructType *STy = dyn_cast<StructType>(Ty);
   if (!STy || STy->isPacked()) return true;
 
-  for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
-    const Type *EltTy = STy->getElementType(i);
-    // 32 and 64-bit integers are fine, as are pointers.
-    // Shorter ints do not work, nor do floating point or vectors.
-    if (EltTy != Type::Int32Ty && EltTy != Type::Int64Ty &&
-        !isa<PointerType>(EltTy))
-      return true;
+  // A struct containing only a float, double or vector field, possibly with
+  // some zero-length fields as well, must be passed as the field type.
+  // Note this does not apply to long double.
+  // This is required for ABI correctness.  
+  tree tType = isSingleElementStructOrArray(TreeType, true, false);
+  if (tType && int_size_in_bytes(tType)==Bytes && TYPE_MODE(tType)!=TFmode)
+    return false;
+
+  return true;
+}
+
+/* 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
+   for parameter passing. */
+bool 
+llvm_rs6000_should_pass_aggregate_in_mixed_regs(tree TreeType, const Type* Ty,
+                                              std::vector<const Type*>&Elts) {
+  // FIXME there are plenty of ppc64 cases that need this.
+  if (TARGET_64BIT)
+    return false;
+
+  // If this is a small fixed size type, investigate it.
+  HOST_WIDE_INT SrcSize = int_size_in_bytes(TreeType);
+  if (SrcSize <= 0 || SrcSize > 16)
+    return false;
+
+  const StructType *STy = dyn_cast<StructType>(Ty);
+  if (!STy || STy->isPacked()) return false;
+
+  // A struct containing only a float, double or vector field, possibly with
+  // some zero-length fields as well, must be passed as the field type.
+  // Note this does not apply to long double.
+  // Other single-element structs may be passed this way as well, but
+  // only if the type size matches the element's type size (structs that
+  // violate this can be created with __aligned__).
+  tree tType = isSingleElementStructOrArray(TreeType, true, false);
+  if (tType && int_size_in_bytes(tType)==SrcSize && TYPE_MODE(tType)!=TFmode) {
+    Elts.push_back(ConvertType(tType));
+    return true;
   }
+
+  Elts.clear();
   return false;
 }
+
 /* LLVM LOCAL end (ENTIRE FILE!)  */
 

Modified: llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.h?rev=48440&r1=48439&r2=48440&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.h (original)
+++ llvm-gcc-4.2/trunk/gcc/config/rs6000/rs6000.h Sun Mar 16 21:21:44 2008
@@ -3478,7 +3478,15 @@
 
 #define LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(X, TY)      \
   llvm_rs6000_should_pass_aggregate_byval(X, TY)
-#endif
+
+extern bool llvm_rs6000_should_pass_aggregate_in_mixed_regs(tree, const Type*, 
+                                              std::vector<const Type*>&);
+
+// FIXME this is needed for 64-bit
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, E) \
+   llvm_rs6000_should_pass_aggregate_in_mixed_regs((T), (TY), (E))
+
+#endif /* LLVM_ABI_H */
 
 /* LLVM LOCAL end */
 

Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi.h?rev=48440&r1=48439&r2=48440&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Sun Mar 16 21:21:44 2008
@@ -243,10 +243,7 @@
       // Return scalar values normally.
       C.HandleScalarResult(Ty);
     } else if (TYPE_SIZE(type) && TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST &&
-               !aggregate_value_p(type, current_function_decl) &&
-               // FIXME: this is a hack around returning 'complex double' by-val
-               // which returns in r3/r4/r5/r6 on PowerPC.
-               TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type)) <= 8) {
+               !aggregate_value_p(type, current_function_decl)) {
       tree SingleElt = LLVM_SHOULD_RETURN_STRUCT_AS_SCALAR(type);
       if (SingleElt && TYPE_SIZE(SingleElt) && 
           TREE_CODE(TYPE_SIZE(SingleElt)) == INTEGER_CST &&
@@ -267,6 +264,10 @@
           C.HandleAggregateResultAsScalar(Type::Int32Ty);
         else if (Size <= 8)
           C.HandleAggregateResultAsScalar(Type::Int64Ty);
+        else if (Size <= 16)
+          C.HandleAggregateResultAsScalar(IntegerType::get(128));
+        else if (Size <= 32)
+          C.HandleAggregateResultAsScalar(IntegerType::get(256));
         else {
           assert(0 && "Cannot return this aggregate as a scalar!");
           abort();





More information about the llvm-commits mailing list