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\
>