This patch implements 16-byte alignment for __int128 types.  In
particular:
  - the stack is aligned to 16 bytes.
  - objects of type __int128 will have 16-byte alignment.
  - __int128 fields in structure have 16-byte alignment.
  - __int128 function arguments: if they are in registers they will
    always start with a even register.  if they are in memory they will
    have 16-byte alignment.
  - stack slots will have 16-byte alignment.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c4a449e..dd93134 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
 2014-01-25  Walter Lee  <w...@tilera.com>
 
+       * config/tilegx/tilegx.c (tilegx_function_arg): Start 16-byte
+       arguments on even registers.
+       (tilegx_gimplify_va_arg_expr): Align 16-byte var args to
+       STACK_BOUNDARY.
+       * config/tilegx/tilegx.h (STACK_BOUNDARY): Change to 16 bytes.
+       (BIGGEST_ALIGNMENT): Ditto.
+       (BIGGEST_FIELD_ALIGNMENT): Ditto.
+
+2014-01-25  Walter Lee  <w...@tilera.com>
+
        * config/tilegx/tilegx.c (tilegx_gen_bundles): Delete barrier
        insns after bundles have been formed.
        * config/tilegx/tilegx.md (tile_network_barrier): Update
diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c
index 7694e31..f3c68e3 100644
--- a/gcc/config/tilegx/tilegx.c
+++ b/gcc/config/tilegx/tilegx.c
@@ -220,10 +220,18 @@ tilegx_function_arg (cumulative_args_t cum_v,
   CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v);
   int byte_size = ((mode == BLKmode)
                   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
+  bool doubleword_aligned_p;
 
   if (cum >= TILEGX_NUM_ARG_REGS)
     return NULL_RTX;
 
+  /* See whether the argument has doubleword alignment.  */
+  doubleword_aligned_p =
+    tilegx_function_arg_boundary (mode, type) > BITS_PER_WORD;
+
+  if (doubleword_aligned_p)
+    cum += cum & 1;
+
   /* The ABI does not allow parameters to be passed partially in reg
      and partially in stack.  */
   if ((cum + (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
@@ -245,6 +253,14 @@ tilegx_function_arg_advance (cumulative_args_t cum_v,
   int byte_size = ((mode == BLKmode)
                   ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
   int word_size = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+  bool doubleword_aligned_p;
+
+  /* See whether the argument has doubleword alignment.  */
+  doubleword_aligned_p =
+    tilegx_function_arg_boundary (mode, type) > BITS_PER_WORD;
+
+  if (doubleword_aligned_p)
+    *cum += *cum & 1;
 
   /* If the current argument does not fit in the pretend_args space,
      skip over it.  */
@@ -417,7 +433,7 @@ tilegx_setup_incoming_varargs (cumulative_args_t cum,
 
    generates code equivalent to:
   
-    paddedsize = (sizeof(TYPE) + 3) & -4;
+    paddedsize = (sizeof(TYPE) + 7) & -8;
     if (  (VALIST.__args + paddedsize > VALIST.__skip)
        & (VALIST.__args <= VALIST.__skip))
       addr = VALIST.__skip + STACK_POINTER_OFFSET;
@@ -457,9 +473,23 @@ tilegx_gimplify_va_arg_expr (tree valist, tree type, 
gimple_seq *pre_p,
   size = int_size_in_bytes (type);
   rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
 
-  /* Assert alignment assumption.  */
-  gcc_assert (STACK_BOUNDARY == PARM_BOUNDARY);
+  /* If the alignment of the type is greater than the default for a
+     parameter, align to the STACK_BOUNDARY. */
+  if (TYPE_ALIGN (type) > PARM_BOUNDARY)
+    {
+      /* Assert the only case we generate code for: when
+        stack boundary = 2 * parm boundary. */
+      gcc_assert (STACK_BOUNDARY == PARM_BOUNDARY * 2);
+
+      tmp = build2 (BIT_AND_EXPR, sizetype,
+                   fold_convert (sizetype, unshare_expr (args)),
+                   size_int (PARM_BOUNDARY / 8));
+      tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node,
+                   unshare_expr (args), tmp);
 
+      gimplify_assign (unshare_expr (args), tmp, pre_p);
+    }
+ 
   /* Build conditional expression to calculate addr. The expression
      will be gimplified later.  */
   tmp = fold_build_pointer_plus_hwi (unshare_expr (args), rsize);
diff --git a/gcc/config/tilegx/tilegx.h b/gcc/config/tilegx/tilegx.h
index 68f466c..9eab51e 100644
--- a/gcc/config/tilegx/tilegx.h
+++ b/gcc/config/tilegx/tilegx.h
@@ -59,9 +59,9 @@
 
 #define UNITS_PER_WORD 8
 #define PARM_BOUNDARY BITS_PER_WORD
-#define STACK_BOUNDARY 64
+#define STACK_BOUNDARY 128
 #define FUNCTION_BOUNDARY 64
-#define BIGGEST_ALIGNMENT 64
+#define BIGGEST_ALIGNMENT 128
 #define STRICT_ALIGNMENT 1
 
 #define INT_TYPE_SIZE         32
@@ -74,7 +74,7 @@
 
 #define PCC_BITFIELD_TYPE_MATTERS 1
 #define FASTEST_ALIGNMENT 64
-#define BIGGEST_FIELD_ALIGNMENT 64
+#define BIGGEST_FIELD_ALIGNMENT 128
 #define WIDEST_HARDWARE_FP_SIZE 64
 
 /* Unaligned moves trap and are very slow.  */

Reply via email to