alpha: Use TARGET_COMPUTE_FRAME_LAYOUT

Message ID 20180709190513.11578-1-rth@twiddle.net
State New
Headers show
Series
  • alpha: Use TARGET_COMPUTE_FRAME_LAYOUT
Related show

Commit Message

Richard Henderson July 9, 2018, 7:05 p.m.
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.

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(-)

Comments

Richard Biener July 10, 2018, 7:05 a.m. | #1
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
>
Richard Henderson July 10, 2018, 12:50 p.m. | #2
On 07/10/2018 12:05 AM, Richard Biener wrote:
> 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.

I do use both popcount_hwi and ctz_hwi.  Enough to swing the preference?


r~
Richard Biener July 10, 2018, 12:52 p.m. | #3
On Tue, Jul 10, 2018 at 2:50 PM Richard Henderson <rth@twiddle.net> wrote:
>
> On 07/10/2018 12:05 AM, Richard Biener wrote:
> > 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.
>
> I do use both popcount_hwi and ctz_hwi.  Enough to swing the preference?

Yes.  Getting rid of HWI in APIs is difficult, and s/HWI/uint64_t/ loses
in my eye...

Richard.

>
> r~

Patch

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)