Patchwork [RS6000] little-endian va_arg

login
register
mail settings
Submitter Alan Modra
Date June 7, 2013, 10:04 a.m.
Message ID <20130607100401.GN6878@bubble.grove.modra.org>
Download mbox | patch
Permalink /patch/249636/
State New
Headers show

Comments

Alan Modra - June 7, 2013, 10:04 a.m.
tree-stdarg.c:check_all_va_list_escapes looks at va_arg accesses
to determine cfun->va_list_gpr_size.  The value set is the offset of
the highest access in the va_list area, plus the size of that access.
For big-endian rs6000 this always results in a multiple of the gpr
register size, but that isn't true for little-endian.  We currently
round down the size, resulting in gcc.c-torture/execute/20071213-1.c
failure on powerpc64le at -O3.

Bootstrapped and regression tested powerpc64-linux.  OK to apply?

	* config/rs6000/rs6000.c (setup_incoming_varargs): Round up
	va_list_gpr_size.
David Edelsohn - June 7, 2013, 12:05 p.m.
On Fri, Jun 7, 2013 at 6:04 AM, Alan Modra <amodra@gmail.com> wrote:
> tree-stdarg.c:check_all_va_list_escapes looks at va_arg accesses
> to determine cfun->va_list_gpr_size.  The value set is the offset of
> the highest access in the va_list area, plus the size of that access.
> For big-endian rs6000 this always results in a multiple of the gpr
> register size, but that isn't true for little-endian.  We currently
> round down the size, resulting in gcc.c-torture/execute/20071213-1.c
> failure on powerpc64le at -O3.
>
> Bootstrapped and regression tested powerpc64-linux.  OK to apply?
>
>         * config/rs6000/rs6000.c (setup_incoming_varargs): Round up
>         va_list_gpr_size.
>
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c  (revision 199781)
> +++ gcc/config/rs6000/rs6000.c  (working copy)
> @@ -9371,19 +9371,20 @@
>        && cfun->va_list_gpr_size)
>      {
>        int nregs = GP_ARG_NUM_REG - first_reg_offset;
> +      int n_gpr;

Declare n_gpr on the same line.

>
>        if (va_list_gpr_counter_field)
>         {
>           /* V4 va_list_gpr_size counts number of registers needed.  */
> -         if (nregs > cfun->va_list_gpr_size)
> -           nregs = cfun->va_list_gpr_size;
> +         n_gpr = cfun->va_list_gpr_size;
>         }

Remove the braces.

>        else
>         {
>           /* char * va_list instead counts number of bytes needed.  */
> -         if (nregs > cfun->va_list_gpr_size / reg_size)
> -           nregs = cfun->va_list_gpr_size / reg_size;
> +         n_gpr = (cfun->va_list_gpr_size + reg_size - 1) / reg_size;
>         }

Remove the braces.  Blank line.

> +      if (nregs > n_gpr)
> +       nregs = n_gpr;
>
>        mem = gen_rtx_MEM (BLKmode,
>                          plus_constant (Pmode, save_area,

Okay with those changes.

Thanks, David

Patch

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 199781)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -9371,19 +9371,20 @@ 
       && cfun->va_list_gpr_size)
     {
       int nregs = GP_ARG_NUM_REG - first_reg_offset;
+      int n_gpr;
 
       if (va_list_gpr_counter_field)
 	{
 	  /* V4 va_list_gpr_size counts number of registers needed.  */
-	  if (nregs > cfun->va_list_gpr_size)
-	    nregs = cfun->va_list_gpr_size;
+	  n_gpr = cfun->va_list_gpr_size;
 	}
       else
 	{
 	  /* char * va_list instead counts number of bytes needed.  */
-	  if (nregs > cfun->va_list_gpr_size / reg_size)
-	    nregs = cfun->va_list_gpr_size / reg_size;
+	  n_gpr = (cfun->va_list_gpr_size + reg_size - 1) / reg_size;
 	}
+      if (nregs > n_gpr)
+	nregs = n_gpr;
 
       mem = gen_rtx_MEM (BLKmode,
 			 plus_constant (Pmode, save_area,