i386.c (contains_128bit_aligned_vector_p): New function.
authorJan Hubicka <jh@suse.cz>
Tue, 11 Feb 2003 21:58:09 +0000 (22:58 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Tue, 11 Feb 2003 21:58:09 +0000 (21:58 +0000)
* i386.c (contains_128bit_aligned_vector_p): New function.
(ix86_function_arg_boundary): Properly align vector modes.

From-SVN: r62732

gcc/ChangeLog
gcc/config/i386/i386.c

index 69ef14413a676a5854b4948dd1d1fc1d96115727..f1341b2b57613af8aadc5d1fa8a84bce1834804f 100644 (file)
@@ -1,3 +1,8 @@
+Mon Oct 21 17:07:47 CEST 2002  Jan Hubicka  <jh@suse.cz>
+
+       * i386.c (contains_128bit_aligned_vector_p): New function.
+       (ix86_function_arg_boundary): Properly align vector modes.
+
 2003-02-11  Bob Wilson  <bob.wilson@acm.org>
 
        * config/xtensa/xtensa.md (set_frame_ptr): Change rtl to set reg a7.
index ca9e0aaad1542c47889f17ed34dc5465cb43000e..cad5c60cd659b5b001d7e6308cb8a2129a923e75 100644 (file)
@@ -880,6 +880,7 @@ static bool ix86_function_ok_for_sibcall PARAMS ((tree, tree));
 static tree ix86_handle_cdecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static int ix86_value_regno PARAMS ((enum machine_mode));
+static bool contains_128bit_aligned_vector_p PARAMS ((tree));
 static bool ix86_ms_bitfield_layout_p PARAMS ((tree));
 static tree ix86_handle_struct_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static int extended_reg_mentioned_1 PARAMS ((rtx *, void *));
@@ -2534,6 +2535,64 @@ function_arg_pass_by_reference (cum, mode, type, named)
   return 0;
 }
 
+/* Return true when TYPE should be 128bit aligned for 32bit argument passing
+   ABI  */
+static bool
+contains_128bit_aligned_vector_p (type)
+     tree type;
+{
+  enum machine_mode mode = TYPE_MODE (type);
+  if (SSE_REG_MODE_P (mode)
+      && (!TYPE_USER_ALIGN (type) || TYPE_ALIGN (type) > 128))
+    return true;
+  if (TYPE_ALIGN (type) < 128)
+    return false;
+
+  if (AGGREGATE_TYPE_P (type))
+    {
+      /* Walk the agregates recursivly.  */
+      if (TREE_CODE (type) == RECORD_TYPE
+         || TREE_CODE (type) == UNION_TYPE
+         || TREE_CODE (type) == QUAL_UNION_TYPE)
+       {
+         tree field;
+
+         if (TYPE_BINFO (type) != NULL
+             && TYPE_BINFO_BASETYPES (type) != NULL)
+           {
+             tree bases = TYPE_BINFO_BASETYPES (type);
+             int n_bases = TREE_VEC_LENGTH (bases);
+             int i;
+
+             for (i = 0; i < n_bases; ++i)
+               {
+                 tree binfo = TREE_VEC_ELT (bases, i);
+                 tree type = BINFO_TYPE (binfo);
+
+                 if (contains_128bit_aligned_vector_p (type))
+                   return true;
+               }
+           }
+         /* And now merge the fields of structure.   */
+         for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+           {
+             if (TREE_CODE (field) == FIELD_DECL
+                 && contains_128bit_aligned_vector_p (TREE_TYPE (field)))
+               return true;
+           }
+       }
+      /* Just for use if some languages passes arrays by value.  */
+      else if (TREE_CODE (type) == ARRAY_TYPE)
+       {
+         if (contains_128bit_aligned_vector_p (TREE_TYPE (type)))
+           return true;
+       }
+      else
+       abort ();
+    }
+  return false;
+}
+
 /* Gives the alignment boundary, in bits, of an argument with the specified mode
    and type.   */
 
@@ -2543,14 +2602,34 @@ ix86_function_arg_boundary (mode, type)
      tree type;
 {
   int align;
-  if (!TARGET_64BIT)
-    return PARM_BOUNDARY;
   if (type)
     align = TYPE_ALIGN (type);
   else
     align = GET_MODE_ALIGNMENT (mode);
   if (align < PARM_BOUNDARY)
     align = PARM_BOUNDARY;
+  if (!TARGET_64BIT)
+    {
+      /* i386 ABI defines all arguments to be 4 byte aligned.  We have to
+        make an exception for SSE modes since these require 128bit
+        alignment.  
+
+        The handling here differs from field_alignment.  ICC aligns MMX
+        arguments to 4 byte boundaries, while structure fields are aligned
+        to 8 byte boundaries.  */
+      if (!type)
+       {
+         if (!SSE_REG_MODE_P (mode))
+           align = PARM_BOUNDARY;
+       }
+      else
+       {
+         if (!contains_128bit_aligned_vector_p (type))
+           align = PARM_BOUNDARY;
+       }
+      if (align != PARM_BOUNDARY && !TARGET_SSE)
+       abort();
+    }
   if (align > 128)
     align = 128;
   return align;