On Tue, Feb 23, 2021 at 8:48 AM Richard Biener <rguent...@suse.de> wrote:
>
> On Mon, 22 Feb 2021, Uros Bizjak wrote:
>
> > The intention of HONOR_REG_ALLOC_ORDER is to ensure that IRA allocates
> > registers in the order given by REG_ALLOC_ORDER.  However in
> > ira_better_spill_reload_regno_p, there is still a place where the
> > calculation depends on the presence of REG_ALLOC_ORDER, ignoring
> > HONOR_REG_ALLOC_ORDER macro altogether.  The patch uses the correct macro
> > at this place.
> >
> > On the other hand, assign_hard_reg function respects HONOR_REG_ALLOC_ORDER,
> > but expects this macro to return 1 to avoid internal cost calculations.
> > As the macro is defined to 0 by default, it is expected that targets 
> > redefine
> > HONOR_REG_ALLOC_ORDER to return nonzero value, even if REG_ALLOC_ORDER
> > is defined.  This approach is prone to errors, so the patch defines
> > HONOR_REG_ALLOC_ORDER to 1 by default if REG_ALLOC_ORDER is defined.
> >
> > 2021-02-22  Uroš Bizjak  <ubiz...@gmail.com>
> >
> > gcc/
> >     * defaults.h (HONOR_REG_ALLOC_ORDER): If not defined,
> >     define to 1 if REG_ALLOC_ORDER is defined.
> >     * doc/tm.texi.in (HONOR_REG_ALLOC_ORDER):
> >     Describe new default definition.
> >     * doc/tm.texi: Regenerate.
> >     * ira-color.c (ira_better_spill_reload_regno_p):
> >     Use HONOR_REG_ALLOC_ORDER instead of REG_ALLOC_ORDER
> >     to determine better spill reload regno.
> >
> > Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
> >
> > OK for gcc-12 when it opens?
>
> OK in case Vlad doesn't have a better suggestion or further comments.
>
> Do you have an idea for how many targets the changed default is an
> actual change?

Practically every target defines REG_ALLOC_ORDER, namely:

$ grep -R "define REG_ALLOC_ORDER" *
alpha/vms.h:#define REG_ALLOC_ORDER
alpha/alpha.h:#define REG_ALLOC_ORDER
arc/arc.h:#define REG_ALLOC_ORDER
arm/arm.h:#define REG_ALLOC_ORDER
avr/avr.h:#define REG_ALLOC_ORDER
bfin/bfin.h:#define REG_ALLOC_ORDER
c6x/c6x.h:#define REG_ALLOC_ORDER
cris/cris.h:#define REG_ALLOC_ORDER
csky/csky.h:#define REG_ALLOC_ORDER
epiphany/epiphany.h:#define REG_ALLOC_ORDER
frv/frv.h:#define REG_ALLOC_ORDER
h8300/h8300.h:#define REG_ALLOC_ORDER
i386/i386.h:#define REG_ALLOC_ORDER
ia64/ia64.h:#define REG_ALLOC_ORDER
iq2000/iq2000.h:#define REG_ALLOC_ORDER
m32c/m32c.h:#define REG_ALLOC_ORDER
m32r/m32r.h:#define REG_ALLOC_ORDER
m32r/m32r.h:#define REG_ALLOC_ORDER
m68k/m68k.h:#define REG_ALLOC_ORDER
mcore/mcore.h:#define REG_ALLOC_ORDER
mips/mips.h:#define REG_ALLOC_ORDER
mmix/mmix.h:#define REG_ALLOC_ORDER
mn10300/mn10300.h:#define REG_ALLOC_ORDER
msp430/msp430.h:#define REG_ALLOC_ORDER
nds32/nds32.h:#define REG_ALLOC_ORDER
nios2/nios2.h:#define REG_ALLOC_ORDER
or1k/or1k.h:#define REG_ALLOC_ORDER
pa/pa32-regs.h:#define REG_ALLOC_ORDER
pa/pa64-regs.h:#define REG_ALLOC_ORDER
pru/pru.h:#define REG_ALLOC_ORDER
riscv/riscv.h:#define REG_ALLOC_ORDER
rl78/rl78.h:#define REG_ALLOC_ORDER
rs6000/rs6000.h:#define REG_ALLOC_ORDER
rx/rx.h:#define REG_ALLOC_ORDER
s390/s390.h:#define REG_ALLOC_ORDER
sh/sh.h:#define REG_ALLOC_ORDER
sparc/sparc.h:#define REG_ALLOC_ORDER
stormy16/stormy16.h:#define REG_ALLOC_ORDER
tilegx/tilegx.h:#define REG_ALLOC_ORDER
tilepro/tilepro.h:#define REG_ALLOC_ORDER
v850/v850.h:#define REG_ALLOC_ORDER
visium/visium.h:#define REG_ALLOC_ORDER
xtensa/xtensa.h:#define REG_ALLOC_ORDER

while HONOR_REG_ALLOC_ORDER is defined by a few:

$ grep -R "define HONOR_REG_ALLOC_ORDER" *
arc/arc.h:#define HONOR_REG_ALLOC_ORDER 1
arm/arm.h:#define HONOR_REG_ALLOC_ORDER optimize_function_for_size_p (cfun)
nds32/nds32.h:#define HONOR_REG_ALLOC_ORDER optimize_size
nios2/nios2.h:#define HONOR_REG_ALLOC_ORDER (TARGET_HAS_CDX)

So, setting new HONOR_REG_ALLOC_ORDER default would have a noticeable
impact, mainly in the existing assing_hard_reg heuristics (please note
that patched condition in ira_better_spill_reload_regno with the new
default is a no-op for targets that don't define
HONOR_REG_ALLOC_ORDER, and a correction for targets that do).

Based on the comment in assign_hard_reg, the heuristic assumes that:

  /* We don't care about giving callee saved registers to allocnos no
     living through calls because call clobbered registers are
     allocated first (it is usual practice to put them first in
     REG_ALLOC_ORDER).  */

and now for targets that define REG_ALLOC_ORDER (and don't define
HONOR_REG_ALLOC_ORDER) the new default *disables*

      if (!HONOR_REG_ALLOC_ORDER)
    {
      if ((saved_nregs = calculate_saved_nregs (hard_regno, mode)) != 0)
      /* We need to save/restore the hard register in
         epilogue/prologue.  Therefore we increase the cost.  */
      {
        rclass = REGNO_REG_CLASS (hard_regno);
        add_cost = ((ira_memory_move_cost[mode][rclass][0]
                 + ira_memory_move_cost[mode][rclass][1])
                * saved_nregs / hard_regno_nregs (hard_regno,
                              mode) - 1);
        cost += add_cost;
        full_cost += add_cost;
      }
    }

Assuming that REG_ALLOC_ORDER targets follow the usual practice and
put call-clobbered registers first (these regs don't have to be
saved/restored), then call-clobbered regs have precedence over
call-saved regs, and no additional cost has to be calculated.
Currently, the logic is incorrect and additional cost is calculated
for targets that define REG_ALLOC_ORDER and don't define
HONOR_REG_ALLOC_ORDER (atm, x86 also fits in this group).

Uros.

Reply via email to