This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] alpha: Use TARGET_COMPUTE_FRAME_LAYOUT
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: Richard Henderson <rth at twiddle dot net>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 10 Jul 2018 09:05:32 +0200
- Subject: Re: [PATCH] alpha: Use TARGET_COMPUTE_FRAME_LAYOUT
- References: <20180709190513.11578-1-rth@twiddle.net>
On Mon, Jul 9, 2018 at 9:05 PM Richard Henderson <rth@twiddle.net> wrote:
>
> At the same time, merge several related frame computing functions.
> Recall that HWI is now always 64-bit, so merge IMASK and FMASK,
> which allows merging of several loops within prologue and epilogue.
Btw, if you're not using these with existing HWI APIs it is now prefered
to use [u]int64_t where appropriate.
Richard.
> Full regression testing will take some time, but a quick browse
> suggests no change in generated code.
>
>
> r~
>
>
> * config/alpha/alpha.c (direct_return): Move down after
> struct machine_function definition; use saved frame_size;
> return bool.
> (struct machine_function): Add sa_mask, sa_size, frame_size.
> (alpha_sa_mask, alpha_sa_size, compute_frame_size): Merge into ...
> (alpha_compute_frame_layout): ... new function.
> (TARGET_COMPUTE_FRAME_LAYOUT): New.
> (alpha_initial_elimination_offset): Use saved sa_size.
> (alpha_vms_initial_elimination_offset): Likewise.
> (alpha_vms_can_eliminate): Remove alpha_sa_size call.
> (alpha_expand_prologue): Use saved frame data. Merge integer
> and fp register save loops.
> (alpha_expand_epilogue): Likewise.
> (alpha_start_function): Use saved frame data.
> * config/alpha/alpha-protos.h (direct_return): Update.
> (alpha_sa_size): Remove.
> ---
> gcc/config/alpha/alpha-protos.h | 3 +-
> gcc/config/alpha/alpha.c | 293 ++++++++++++--------------------
> 2 files changed, 109 insertions(+), 187 deletions(-)
>
> diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
> index d171f4eb414..099ce0e0c42 100644
> --- a/gcc/config/alpha/alpha-protos.h
> +++ b/gcc/config/alpha/alpha-protos.h
> @@ -21,9 +21,8 @@ extern int alpha_next_sequence_number;
>
> extern void literal_section (void);
> extern int zap_mask (HOST_WIDE_INT);
> -extern int direct_return (void);
> +extern bool direct_return (void);
>
> -extern int alpha_sa_size (void);
> extern HOST_WIDE_INT alpha_initial_elimination_offset (unsigned int,
> unsigned int);
> extern void alpha_expand_prologue (void);
> diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
> index 9adfe159381..218306d3a07 100644
> --- a/gcc/config/alpha/alpha.c
> +++ b/gcc/config/alpha/alpha.c
> @@ -728,19 +728,6 @@ alpha_vector_mode_supported_p (machine_mode mode)
> return mode == V8QImode || mode == V4HImode || mode == V2SImode;
> }
>
> -/* Return 1 if this function can directly return via $26. */
> -
> -int
> -direct_return (void)
> -{
> - return (TARGET_ABI_OSF
> - && reload_completed
> - && alpha_sa_size () == 0
> - && get_frame_size () == 0
> - && crtl->outgoing_args_size == 0
> - && crtl->args.pretend_args_size == 0);
> -}
> -
> /* Return the TLS model to use for SYMBOL. */
>
> static enum tls_model
> @@ -4837,6 +4824,10 @@ struct GTY(()) alpha_links;
>
> struct GTY(()) machine_function
> {
> + unsigned HOST_WIDE_INT sa_mask;
> + HOST_WIDE_INT sa_size;
> + HOST_WIDE_INT frame_size;
> +
> /* For flag_reorder_blocks_and_partition. */
> rtx gp_save_rtx;
>
> @@ -7236,83 +7227,59 @@ static int vms_save_fp_regno;
> /* Register number used to reference objects off our PV. */
> static int vms_base_regno;
>
> -/* Compute register masks for saved registers. */
> -
> +/* Compute register masks for saved registers, register save area size,
> + and total frame size. */
> static void
> -alpha_sa_mask (unsigned long *imaskP, unsigned long *fmaskP)
> +alpha_compute_frame_layout (void)
> {
> - unsigned long imask = 0;
> - unsigned long fmask = 0;
> - unsigned int i;
> + unsigned HOST_WIDE_INT sa_mask = 0;
> + HOST_WIDE_INT frame_size;
> + int sa_size;
>
> /* When outputting a thunk, we don't have valid register life info,
> but assemble_start_function wants to output .frame and .mask
> directives. */
> - if (cfun->is_thunk)
> + if (!cfun->is_thunk)
> {
> - *imaskP = 0;
> - *fmaskP = 0;
> - return;
> - }
> + if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
> + sa_mask |= HOST_WIDE_INT_1U << HARD_FRAME_POINTER_REGNUM;
>
> - if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
> - imask |= (1UL << HARD_FRAME_POINTER_REGNUM);
> + /* One for every register we have to save. */
> + for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; i++)
> + if (! fixed_regs[i] && ! call_used_regs[i]
> + && df_regs_ever_live_p (i) && i != REG_RA)
> + sa_mask |= HOST_WIDE_INT_1U << i;
>
> - /* One for every register we have to save. */
> - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
> - if (! fixed_regs[i] && ! call_used_regs[i]
> - && df_regs_ever_live_p (i) && i != REG_RA)
> - {
> - if (i < 32)
> - imask |= (1UL << i);
> - else
> - fmask |= (1UL << (i - 32));
> - }
> -
> - /* We need to restore these for the handler. */
> - if (crtl->calls_eh_return)
> - {
> - for (i = 0; ; ++i)
> + /* We need to restore these for the handler. */
> + if (crtl->calls_eh_return)
> {
> - unsigned regno = EH_RETURN_DATA_REGNO (i);
> - if (regno == INVALID_REGNUM)
> - break;
> - imask |= 1UL << regno;
> + for (unsigned i = 0; ; ++i)
> + {
> + unsigned regno = EH_RETURN_DATA_REGNO (i);
> + if (regno == INVALID_REGNUM)
> + break;
> + sa_mask |= HOST_WIDE_INT_1U << regno;
> + }
> }
> +
> + /* If any register spilled, then spill the return address also. */
> + /* ??? This is required by the Digital stack unwind specification
> + and isn't needed if we're doing Dwarf2 unwinding. */
> + if (sa_mask || alpha_ra_ever_killed ())
> + sa_mask |= HOST_WIDE_INT_1U << REG_RA;
> }
>
> - /* If any register spilled, then spill the return address also. */
> - /* ??? This is required by the Digital stack unwind specification
> - and isn't needed if we're doing Dwarf2 unwinding. */
> - if (imask || fmask || alpha_ra_ever_killed ())
> - imask |= (1UL << REG_RA);
> -
> - *imaskP = imask;
> - *fmaskP = fmask;
> -}
> -
> -int
> -alpha_sa_size (void)
> -{
> - unsigned long mask[2];
> - int sa_size = 0;
> - int i, j;
> -
> - alpha_sa_mask (&mask[0], &mask[1]);
> -
> - for (j = 0; j < 2; ++j)
> - for (i = 0; i < 32; ++i)
> - if ((mask[j] >> i) & 1)
> - sa_size++;
> + sa_size = popcount_hwi(sa_mask);
> + frame_size = get_frame_size ();
>
> if (TARGET_ABI_OPEN_VMS)
> {
> /* Start with a stack procedure if we make any calls (REG_RA used), or
> need a frame pointer, with a register procedure if we otherwise need
> at least a slot, and with a null procedure in other cases. */
> - if ((mask[0] >> REG_RA) & 1 || frame_pointer_needed)
> + if ((sa_mask >> REG_RA) & 1 || frame_pointer_needed)
> alpha_procedure_type = PT_STACK;
> - else if (get_frame_size() != 0)
> + else if (frame_size != 0)
> alpha_procedure_type = PT_REGISTER;
> else
> alpha_procedure_type = PT_NULL;
> @@ -7336,12 +7303,15 @@ alpha_sa_size (void)
>
> /* If we want to copy PV into FP, we need to find some register
> in which to save FP. */
> -
> vms_save_fp_regno = -1;
> if (vms_base_regno == HARD_FRAME_POINTER_REGNUM)
> - for (i = 0; i < 32; i++)
> - if (! fixed_regs[i] && call_used_regs[i] && ! df_regs_ever_live_p (i))
> - vms_save_fp_regno = i;
> + for (unsigned i = 0; i < 32; i++)
> + if (! fixed_regs[i] && call_used_regs[i]
> + && ! df_regs_ever_live_p (i))
> + {
> + vms_save_fp_regno = i;
> + break;
> + }
>
> /* A VMS condition handler requires a stack procedure in our
> implementation. (not required by the calling standard). */
> @@ -7366,8 +7336,34 @@ alpha_sa_size (void)
> if (sa_size & 1)
> sa_size++;
> }
> + sa_size *= 8;
>
> - return sa_size * 8;
> + if (TARGET_ABI_OPEN_VMS)
> + frame_size = ALPHA_ROUND (sa_size
> + + (alpha_procedure_type == PT_STACK ? 8 : 0)
> + + frame_size
> + + crtl->args.pretend_args_size);
> + else
> + frame_size = (ALPHA_ROUND (crtl->outgoing_args_size)
> + + sa_size
> + + ALPHA_ROUND (frame_size + crtl->args.pretend_args_size));
> +
> + cfun->machine->sa_mask = sa_mask;
> + cfun->machine->sa_size = sa_size;
> + cfun->machine->frame_size = frame_size;
> +}
> +
> +#undef TARGET_COMPUTE_FRAME_LAYOUT
> +#define TARGET_COMPUTE_FRAME_LAYOUT alpha_compute_frame_layout
> +
> +/* Return 1 if this function can directly return via $26. */
> +
> +bool
> +direct_return (void)
> +{
> + return (TARGET_ABI_OSF
> + && reload_completed
> + && cfun->machine->frame_size == 0);
> }
>
> /* Define the offset between two registers, one to be eliminated,
> @@ -7379,7 +7375,7 @@ alpha_initial_elimination_offset (unsigned int from,
> {
> HOST_WIDE_INT ret;
>
> - ret = alpha_sa_size ();
> + ret = cfun->machine->sa_size;
> ret += ALPHA_ROUND (crtl->outgoing_args_size);
>
> switch (from)
> @@ -7407,9 +7403,6 @@ alpha_initial_elimination_offset (unsigned int from,
> static bool
> alpha_vms_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
> {
> - /* We need the alpha_procedure_type to decide. Evaluate it now. */
> - alpha_sa_size ();
> -
> switch (alpha_procedure_type)
> {
> case PT_NULL:
> @@ -7439,7 +7432,7 @@ alpha_vms_initial_elimination_offset (unsigned int from, unsigned int to)
> on the proper computations and will need the register save area size
> in most cases. */
>
> - HOST_WIDE_INT sa_size = alpha_sa_size ();
> + HOST_WIDE_INT sa_size = cfun->machine->sa_size;
>
> /* PT_NULL procedures have no frame of their own and we only allow
> elimination to the stack pointer. This is the argument pointer and we
> @@ -7671,24 +7664,6 @@ emit_frame_store (unsigned int regno, rtx base_reg,
> emit_frame_store_1 (reg, base_reg, frame_bias, base_ofs, reg);
> }
>
> -/* Compute the frame size. SIZE is the size of the "naked" frame
> - and SA_SIZE is the size of the register save area. */
> -
> -static HOST_WIDE_INT
> -compute_frame_size (HOST_WIDE_INT size, HOST_WIDE_INT sa_size)
> -{
> - if (TARGET_ABI_OPEN_VMS)
> - return ALPHA_ROUND (sa_size
> - + (alpha_procedure_type == PT_STACK ? 8 : 0)
> - + size
> - + crtl->args.pretend_args_size);
> - else
> - return ALPHA_ROUND (crtl->outgoing_args_size)
> - + sa_size
> - + ALPHA_ROUND (size
> - + crtl->args.pretend_args_size);
> -}
> -
> /* Write function prologue. */
>
> /* On vms we have two kinds of functions:
> @@ -7710,22 +7685,17 @@ void
> alpha_expand_prologue (void)
> {
> /* Registers to save. */
> - unsigned long imask = 0;
> - unsigned long fmask = 0;
> + unsigned HOST_WIDE_INT sa_mask = cfun->machine->sa_mask;
> /* Stack space needed for pushing registers clobbered by us. */
> - HOST_WIDE_INT sa_size, sa_bias;
> + HOST_WIDE_INT sa_size = cfun->machine->sa_size;
> /* Complete stack size needed. */
> - HOST_WIDE_INT frame_size;
> + HOST_WIDE_INT frame_size = cfun->machine->frame_size;
> /* Probed stack size; it additionally includes the size of
> the "reserve region" if any. */
> - HOST_WIDE_INT probed_size;
> + HOST_WIDE_INT probed_size, sa_bias;
> /* Offset from base reg to register save area. */
> HOST_WIDE_INT reg_offset;
> rtx sa_reg;
> - int i;
> -
> - sa_size = alpha_sa_size ();
> - frame_size = compute_frame_size (get_frame_size (), sa_size);
>
> if (flag_stack_usage_info)
> current_function_static_stack_size = frame_size;
> @@ -7735,8 +7705,6 @@ alpha_expand_prologue (void)
> else
> reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
>
> - alpha_sa_mask (&imask, &fmask);
> -
> /* Emit an insn to reload GP, if needed. */
> if (TARGET_ABI_OSF)
> {
> @@ -7875,29 +7843,15 @@ alpha_expand_prologue (void)
> if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK)
> emit_frame_store (REG_PV, stack_pointer_rtx, 0, 0);
>
> - /* Save register RA next. */
> - if (imask & (1UL << REG_RA))
> + /* Save register RA next, followed by any other registers
> + that need to be saved. */
> + for (unsigned i = REG_RA; sa_mask != 0; i = ctz_hwi(sa_mask))
> {
> - emit_frame_store (REG_RA, sa_reg, sa_bias, reg_offset);
> - imask &= ~(1UL << REG_RA);
> + emit_frame_store (i, sa_reg, sa_bias, reg_offset);
> reg_offset += 8;
> + sa_mask &= ~(HOST_WIDE_INT_1U << i);
> }
>
> - /* Now save any other registers required to be saved. */
> - for (i = 0; i < 31; i++)
> - if (imask & (1UL << i))
> - {
> - emit_frame_store (i, sa_reg, sa_bias, reg_offset);
> - reg_offset += 8;
> - }
> -
> - for (i = 0; i < 31; i++)
> - if (fmask & (1UL << i))
> - {
> - emit_frame_store (i+32, sa_reg, sa_bias, reg_offset);
> - reg_offset += 8;
> - }
> -
> if (TARGET_ABI_OPEN_VMS)
> {
> /* Register frame procedures save the fp. */
> @@ -7984,14 +7938,11 @@ void
> alpha_start_function (FILE *file, const char *fnname,
> tree decl ATTRIBUTE_UNUSED)
> {
> - unsigned long imask = 0;
> - unsigned long fmask = 0;
> - /* Stack space needed for pushing registers clobbered by us. */
> - HOST_WIDE_INT sa_size;
> + unsigned long imask, fmask;
> /* Complete stack size needed. */
> - unsigned HOST_WIDE_INT frame_size;
> + HOST_WIDE_INT frame_size = cfun->machine->frame_size;
> /* The maximum debuggable frame size. */
> - unsigned HOST_WIDE_INT max_frame_size = 1UL << 31;
> + const HOST_WIDE_INT max_frame_size = HOST_WIDE_INT_1 << 31;
> /* Offset from base reg to register save area. */
> HOST_WIDE_INT reg_offset;
> char *entry_label = (char *) alloca (strlen (fnname) + 6);
> @@ -8003,15 +7954,14 @@ alpha_start_function (FILE *file, const char *fnname,
> #endif
>
> alpha_fnname = fnname;
> - sa_size = alpha_sa_size ();
> - frame_size = compute_frame_size (get_frame_size (), sa_size);
>
> if (TARGET_ABI_OPEN_VMS)
> reg_offset = 8 + 8 * cfun->machine->uses_condition_handler;
> else
> reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
>
> - alpha_sa_mask (&imask, &fmask);
> + imask = cfun->machine->sa_mask & 0xffffffffu;
> + fmask = cfun->machine->sa_mask >> 32;
>
> /* Issue function start and label. */
> if (TARGET_ABI_OPEN_VMS || !flag_inhibit_size_directive)
> @@ -8078,7 +8028,7 @@ alpha_start_function (FILE *file, const char *fnname,
> fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,"
> HOST_WIDE_INT_PRINT_DEC "\n",
> vms_unwind_regno,
> - frame_size >= (1UL << 31) ? 0 : frame_size,
> + frame_size >= max_frame_size ? 0 : frame_size,
> reg_offset);
> else if (!flag_inhibit_size_directive)
> fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,%d\n",
> @@ -8158,12 +8108,11 @@ void
> alpha_expand_epilogue (void)
> {
> /* Registers to save. */
> - unsigned long imask = 0;
> - unsigned long fmask = 0;
> + unsigned HOST_WIDE_INT sa_mask = cfun->machine->sa_mask;
> /* Stack space needed for pushing registers clobbered by us. */
> - HOST_WIDE_INT sa_size;
> + HOST_WIDE_INT sa_size = cfun->machine->sa_size;
> /* Complete stack size needed. */
> - HOST_WIDE_INT frame_size;
> + HOST_WIDE_INT frame_size = cfun->machine->frame_size;
> /* Offset from base reg to register save area. */
> HOST_WIDE_INT reg_offset;
> int fp_is_frame_pointer, fp_offset;
> @@ -8171,10 +8120,6 @@ alpha_expand_epilogue (void)
> rtx sp_adj1, sp_adj2, mem, reg, insn;
> rtx eh_ofs;
> rtx cfa_restores = NULL_RTX;
> - int i;
> -
> - sa_size = alpha_sa_size ();
> - frame_size = compute_frame_size (get_frame_size (), sa_size);
>
> if (TARGET_ABI_OPEN_VMS)
> {
> @@ -8186,8 +8131,6 @@ alpha_expand_epilogue (void)
> else
> reg_offset = ALPHA_ROUND (crtl->outgoing_args_size);
>
> - alpha_sa_mask (&imask, &fmask);
> -
> fp_is_frame_pointer
> = (TARGET_ABI_OPEN_VMS
> ? alpha_procedure_type == PT_STACK
> @@ -8226,43 +8169,23 @@ alpha_expand_epilogue (void)
> }
>
> /* Restore registers in order, excepting a true frame pointer. */
> -
> - mem = gen_frame_mem (DImode, plus_constant (Pmode, sa_reg, reg_offset));
> - reg = gen_rtx_REG (DImode, REG_RA);
> - emit_move_insn (reg, mem);
> - cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
> -
> - reg_offset += 8;
> - imask &= ~(1UL << REG_RA);
> -
> - for (i = 0; i < 31; ++i)
> - if (imask & (1UL << i))
> - {
> - if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
> - fp_offset = reg_offset;
> - else
> - {
> - mem = gen_frame_mem (DImode,
> - plus_constant (Pmode, sa_reg,
> - reg_offset));
> - reg = gen_rtx_REG (DImode, i);
> - emit_move_insn (reg, mem);
> - cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
> - cfa_restores);
> - }
> - reg_offset += 8;
> - }
> -
> - for (i = 0; i < 31; ++i)
> - if (fmask & (1UL << i))
> - {
> - mem = gen_frame_mem (DFmode, plus_constant (Pmode, sa_reg,
> - reg_offset));
> - reg = gen_rtx_REG (DFmode, i+32);
> - emit_move_insn (reg, mem);
> - cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
> - reg_offset += 8;
> - }
> + for (unsigned i = REG_RA; sa_mask != 0; i = ctz_hwi(sa_mask))
> + {
> + if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer)
> + fp_offset = reg_offset;
> + else
> + {
> + mem = gen_frame_mem (DImode,
> + plus_constant (Pmode, sa_reg,
> + reg_offset));
> + reg = gen_rtx_REG (DImode, i);
> + emit_move_insn (reg, mem);
> + cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
> + cfa_restores);
> + }
> + reg_offset += 8;
> + sa_mask &= ~(HOST_WIDE_INT_1U << i);
> + }
> }
>
> if (frame_size || eh_ofs)
> --
> 2.17.1
>