Unreviewed patch: [PR 16815] RFA: Fix a BLOCK_REG_PADDING check
Richard Sandiford
rsandifo@redhat.com
Thu Sep 30 12:26:00 GMT 2004
Pinging the patch below, originally posted here:
http://gcc.gnu.org/ml/gcc-patches/2004-09/msg01735.html
Richard Sandiford <rsandifo@redhat.com> writes:
> This patch fixes PR target/16815, which complains about very inefficient
> handling of floating-point arguments in big-endian n32 and n64 MIPS code.
> It also fixes gcc.dg/mips-movcc-3.c for mips-sgi-irix6.5.
>
> Although this patch does fix a testsuite failure, there's no wrong code
> as such, so I suppose it might not qualify as a true bugfix. However,
> the current output is a significant code quality regression from gcc 3.3
> and earlier, so I hope the patch is still acceptable for stage 3.
>
> The problem is that, in big-endian n32 and n64 code, float arguments
> are always being forced onto the stack. For example:
>
> float
> sub (float f, float g)
> {
> return f + g;
> }
>
> gives the horrendous:
>
> addiu $sp,$sp,-32
> swc1 $f12,0($sp)
> swc1 $f13,16($sp)
> lwc1 $f1,0($sp)
> lwc1 $f0,16($sp)
> addiu $sp,$sp,32
> j $31
> add.s $f0,$f1,$f0
>
> when compiled with "-mabi=n32 -EB -O2". The problem lies in the
> BLOCK_REG_PADDING check in function.c:assign_parm_setup_block_p():
>
> -------------------------------------------------------------------------
> /* A subroutine of assign_parms. Return true if the current parameter
> should be stored as a BLKmode in the current frame. */
>
> static bool
> assign_parm_setup_block_p (struct assign_parm_data_one *data)
> {
> if (data->nominal_mode == BLKmode)
> return true;
> if (GET_CODE (data->entry_parm) == PARALLEL)
> return true;
>
> #ifdef BLOCK_REG_PADDING
> if (data->locate.where_pad == (BYTES_BIG_ENDIAN ? upward : downward)
> && GET_MODE_SIZE (data->promoted_mode) < UNITS_PER_WORD)
> return true;
> #endif
>
> return false;
> }
> -------------------------------------------------------------------------
>
> This check is looking for register arguments that are padded at the
> least significant end. At the moment, such arguments do need to be
> handled by assign_parm_setup_block, but the check is too general in
> two respects:
>
> (1) It doesn't check whether the argument is actually passed in a
> register. An argument that is:
>
> (a) passed on the stack;
> (b) less than a word in size; and
> (c) padded at the least significant end
>
> will be caught by the check and thus will never be assigned a
> pseudo register. This seems unnecessary, since the padding of any
> such argument is controlled entirely by FUNCTION_ARG_PADDING and
> will be handled in the same way as it would have been on a
> non-B_R_P target.
>
> (2) It doesn't depend on the value of BLOCK_REG_PADDING. (Note that
> where_pad is the padding provided by FUNCTION_ARG_PADDING, not
> BLOCK_REG_PADDING.)
>
> This is the crux of the problem. With big-endian n32 and n64,
> float arguments are passed naturally in registers but are
> left-justified when passed on the stack. Thus FUNCTION_ARG_PADDING
> says "upward" but BLOCK_REG_PADDING says "downward".
>
> Now this combination _is_ handled correctly by
> assign_parm_setup_block, but it simply does a normal store of the
> register into the stack slot. This stack slot then becomes the
> PARM_DECL's DECL_RTL. Since no special handling is required,
> it would be much better to use a pseudo register for the PARM_DECL
> where appropriate.
>
> The patch below fixes both (1) and (2).
>
> FWIW, I wondered about simply shifting the affected registers right so
> that they are padded in the way gcc expects, but it wasn't always a win.
> It would sometimes lead to spill code like:
>
> dsrl reg,reg,56
> sb reg,stack
>
> instead of simply:
>
> sd reg,stack
>
> It also felt less like stage 3 work.
>
> Two other targets use BLOCK_REG_PADDING: powerpc and hppa. Both powerpc
> definitions are:
>
> #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
> (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
>
> so changing the where_pad check to use BLOCK_REG_PADDING is a no-op
> in this case. The pa.h version is more problematic:
>
> #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
> (TARGET_64BIT ? upward : downward)
>
> This seems to be a simplification of function_arg_padding that relies
> on the fact that BLOCK_REG_PADDING is only used for aggregates. At the
> moment, that's true, but since non-aggregate subword values are padded
> downward if TARGET_64BIT, it seems a little dangerous to rely on that.
> (FWIW, BLOCK_REG_PADDING is defined in terms of block moves, but it
> doesn't say what kind of arguments will and will not use a block move.)
>
> So there seemed to be two choices:
>
> (a) In assign_parm_setup_block_p, check BLOCK_REG_PADDING as well as,
> not instead of, where_pad. Only return true if both specify
> padding at the least significant end.
>
> This fixes the MIPS problem without changing the gcc.c-torture
> or gcc.dg assembly output for either powerpc64-linux-gnu or
> hppa64-linux-gnu. But it doesn't feel right conceptually.
> It also fails to to handle the pathological (hopefully non-existent)
> case of an argument that is padded at the least significant end in
> registers and at the most significant end on the stack.
>
> (b) Make hppa's definition use function_arg_padding, just like the
> powerpc and MIPS versions do.
>
> I went for (b) here. I compared the gcc.c-torture and gcc.dg output
> of powerpc64-linux-gnu and hppa64-linux-gnu before and after the patch
> (including subdirectories like gcc.dg/compat). There were no changes.
> The patch has also been bootstrapped & regression tested on mips-sgi-irix6.5,
> where it fixes the mips-movcc-3.c test and introduced no new failures.
> OK to install?
>
> Richard
>
>
> PR target/16815
> * function.c (assign_parm_setup_block_p): Tighten BLOCK_REG_PADDING
> check.
> * config/pa/pa.h (BLOCK_REG_PADDING): Define in terms of
> function_arg_padding.
>
> Index: function.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/function.c,v
> retrieving revision 1.575
> diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.575 function.c
> *** function.c 10 Sep 2004 00:50:24 -0000 1.575
> --- function.c 17 Sep 2004 06:04:03 -0000
> *************** assign_parm_setup_block_p (struct assign
> *** 2513,2520 ****
> return true;
>
> #ifdef BLOCK_REG_PADDING
> ! if (data->locate.where_pad == (BYTES_BIG_ENDIAN ? upward : downward)
> ! && GET_MODE_SIZE (data->promoted_mode) < UNITS_PER_WORD)
> return true;
> #endif
>
> --- 2513,2524 ----
> return true;
>
> #ifdef BLOCK_REG_PADDING
> ! /* Only assign_parm_setup_block knows how to deal with register arguments
> ! that are padded at the least significant end. */
> ! if (REG_P (data->entry_parm)
> ! && GET_MODE_SIZE (data->promoted_mode) < UNITS_PER_WORD
> ! && (BLOCK_REG_PADDING (data->passed_mode, data->passed_type, 1)
> ! == (BYTES_BIG_ENDIAN ? upward : downward)))
> return true;
> #endif
>
> Index: config/pa/pa.h
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/config/pa/pa.h,v
> retrieving revision 1.234
> diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.234 pa.h
> *** config/pa/pa.h 8 Sep 2004 18:45:16 -0000 1.234
> --- config/pa/pa.h 17 Sep 2004 06:04:05 -0000
> *************** #define FUNCTION_ARG_PADDING(MODE, TYPE)
> *** 918,924 ****
> We use a DImode register in the parallel for 5 to 7 byte structures
> so that there is only one element. This allows the object to be
> correctly padded. */
> ! #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) (TARGET_64BIT ? upward : downward)
>
> /* Do not expect to understand this without reading it several times. I'm
> tempted to try and simply it, but I worry about breaking something. */
> --- 918,925 ----
> We use a DImode register in the parallel for 5 to 7 byte structures
> so that there is only one element. This allows the object to be
> correctly padded. */
> ! #define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
> ! function_arg_padding ((MODE), (TYPE))
>
> /* Do not expect to understand this without reading it several times. I'm
> tempted to try and simply it, but I worry about breaking something. */
More information about the Gcc-patches
mailing list