On 09/01/14 15:21, Vladimir Makarov wrote:
> Hi, Richard.
> 
>    This week I've been working on THUMB code size issues.  Here is the
> prototype of the patch for spilling into HI_REGS instead of memory.
> The patch decreases number of generated insns and makes the code faster
> as it removes a lot of loads/stores.
> 
>    I am sending the patch for your evaluation and for getting your
> opinion.  If you like the code size results, I could create the real 
> patch next week (the patch here will not work correctly when a user 
> defines fixed registers by himself).
> 
> Thanks in advance, Vlad.
> 

Do you need to take into account HARD_REGNO_NREGS (mode) when doing the
limit check?

R.

> 
> z
> 
> 
> Index: config/arm/arm.c
> ===================================================================
> --- config/arm/arm.c  (revision 206089)
> +++ config/arm/arm.c  (working copy)
> @@ -73,6 +73,8 @@ struct four_ints
>  
>  /* Forward function declarations.  */
>  static bool arm_lra_p (void);
> +static reg_class_t arm_spill_class (reg_class_t, enum machine_mode);
> +static int arm_spill_hard_regno (int, reg_class_t, enum machine_mode);
>  static bool arm_needs_doubleword_align (enum machine_mode, const_tree);
>  static int arm_compute_static_chain_stack_bytes (void);
>  static arm_stack_offsets *arm_get_frame_offsets (void);
> @@ -345,6 +347,12 @@ static const struct attribute_spec arm_a
>  #undef TARGET_LRA_P
>  #define TARGET_LRA_P arm_lra_p
>  
> +#undef TARGET_SPILL_CLASS
> +#define TARGET_SPILL_CLASS arm_spill_class
> +
> +#undef TARGET_SPILL_HARD_REGNO
> +#define TARGET_SPILL_HARD_REGNO arm_spill_hard_regno
> +
>  #undef  TARGET_ATTRIBUTE_TABLE
>  #define TARGET_ATTRIBUTE_TABLE arm_attribute_table
>  
> @@ -5597,6 +5605,28 @@ arm_lra_p (void)
>    return arm_lra_flag;
>  }
>  
> +/* Return class of registers which could be used for pseudo of MODE
> +   and of class RCLASS for spilling instead of memory.  Return NO_REGS
> +   if it is not possible or non-profitable.  */
> +static reg_class_t
> +arm_spill_class (reg_class_t rclass, enum machine_mode mode)
> +{
> +  if (TARGET_THUMB1 && mode == SImode
> +      && (rclass == LO_REGS || rclass == GENERAL_REGS))
> +    return HI_REGS;
> +  return NO_REGS;
> +}
> +
> +/* ???  */
> +static int
> +arm_spill_hard_regno (int n, reg_class_t spill_class, enum machine_mode mode)
> +{
> +  gcc_assert (TARGET_THUMB1 && mode == SImode && spill_class == HI_REGS
> +           && n >= 0);
> +  int hard_regno = FIRST_HI_REGNUM + n;
> +  return hard_regno > 12 ? -1 : hard_regno;
> +}
> +
>  /* Return true if mode/type need doubleword alignment.  */
>  static bool
>  arm_needs_doubleword_align (enum machine_mode mode, const_tree type)
> @@ -29236,6 +29266,7 @@ arm_conditional_register_usage (void)
>        for (regno = FIRST_HI_REGNUM;
>          regno <= LAST_HI_REGNUM; ++regno)
>       fixed_regs[regno] = call_used_regs[regno] = 1;
> +      fixed_regs[12] = call_used_regs[12] = 1;
>      }
>  
>    /* The link register can be clobbered by any branch insn,
> Index: doc/tm.texi
> ===================================================================
> --- doc/tm.texi       (revision 206089)
> +++ doc/tm.texi       (working copy)
> @@ -2918,6 +2918,10 @@ A target hook which returns true if an a
>  This hook defines a class of registers which could be used for spilling  
> pseudos of the given mode and class, or @code{NO_REGS} if only memory  should 
> be used.  Not defining this hook is equivalent to returning  @code{NO_REGS} 
> for all inputs.
>  @end deftypefn
>  
> +@deftypefn {Target Hook} int TARGET_SPILL_HARD_REGNO (int, 
> @var{reg_class_t}, enum @var{machine_mode})
> +This hook defines n-th (0, ...) register which could be used for spilling  
> pseudos of the given mode and spill class, or -1 if there are no  such regs 
> anymore.  The hook shoul be defined with spill_class hook  and should be 
> defined only for classes returned by spill_class.
> +@end deftypefn
> +
>  @deftypefn {Target Hook} {enum machine_mode} TARGET_CSTORE_MODE (enum 
> insn_code @var{icode})
>  This hook defines the machine mode to use for the boolean result of  
> conditional store patterns.  The ICODE argument is the instruction code  for 
> the cstore being performed.  Not definiting this hook is the same  as 
> accepting the mode encoded into operand 0 of the cstore expander  patterns.
>  @end deftypefn
> Index: doc/tm.texi.in
> ===================================================================
> --- doc/tm.texi.in    (revision 206089)
> +++ doc/tm.texi.in    (working copy)
> @@ -2549,6 +2549,8 @@ as below:
>  
>  @hook TARGET_SPILL_CLASS
>  
> +@hook TARGET_SPILL_HARD_REGNO
> +
>  @hook TARGET_CSTORE_MODE
>  
>  @node Old Constraints
> Index: lra-spills.c
> ===================================================================
> --- lra-spills.c      (revision 206089)
> +++ lra-spills.c      (working copy)
> @@ -252,7 +252,7 @@ pseudo_reg_slot_compare (const void *v1p
>  static int
>  assign_spill_hard_regs (int *pseudo_regnos, int n)
>  {
> -  int i, k, p, regno, res, spill_class_size, hard_regno, nr;
> +  int i, k, p, regno, res, hard_regno, nr;
>    enum reg_class rclass, spill_class;
>    enum machine_mode mode;
>    lra_live_range_t r;
> @@ -271,7 +271,7 @@ assign_spill_hard_regs (int *pseudo_regn
>    /* Set up reserved hard regs for every program point.       */
>    reserved_hard_regs = XNEWVEC (HARD_REG_SET, lra_live_max_point);
>    for (p = 0; p < lra_live_max_point; p++)
> -    COPY_HARD_REG_SET (reserved_hard_regs[p], lra_no_alloc_regs);
> +    CLEAR_HARD_REG_SET (reserved_hard_regs[p]);
>    for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++)
>      if (lra_reg_info[i].nrefs != 0
>       && (hard_regno = lra_get_regno_hard_regno (i)) >= 0)
> @@ -307,15 +307,16 @@ assign_spill_hard_regs (int *pseudo_regn
>        for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
>       for (p = r->start; p <= r->finish; p++)
>         IOR_HARD_REG_SET (conflict_hard_regs, reserved_hard_regs[p]);
> -      spill_class_size = ira_class_hard_regs_num[spill_class];
>        mode = lra_reg_info[regno].biggest_mode;
> -      for (k = 0; k < spill_class_size; k++)
> +      for (k = 0;; k++)
>       {
> -       hard_regno = ira_class_hard_regs[spill_class][k];
> +       hard_regno = targetm.spill_hard_regno (k, spill_class, mode);
> +       if (hard_regno < 0)
> +         break;
>         if (! overlaps_hard_reg_set_p (conflict_hard_regs, mode, hard_regno))
>           break;
>       }
> -      if (k >= spill_class_size)
> +      if (hard_regno < 0)
>       {
>          /* There is no available regs -- assign memory later.  */
>         pseudo_regnos[res++] = regno;
> Index: target.def
> ===================================================================
> --- target.def        (revision 206089)
> +++ target.def        (working copy)
> @@ -4399,6 +4399,17 @@ DEFHOOK
>   reg_class_t, (reg_class_t, enum machine_mode),
>   NULL)
>  
> +/* Determine class for spilling pseudos of given mode into registers
> +   instead of memory.  */
> +DEFHOOK
> +(spill_hard_regno,
> + "This hook defines n-th (0, ...) register which could be used for spilling\
> +  pseudos of the given mode and spill class, or -1 if there are no\
> +  such regs anymore.  The hook shoul be defined with spill_class hook\
> +  and should be defined only for classes returned by spill_class.",
> + int, (int, reg_class_t, enum machine_mode),
> + NULL)
> +
>  DEFHOOK
>  (cstore_mode,
>   "This hook defines the machine mode to use for the boolean result of\
> 


Reply via email to