https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117064

            Bug ID: 117064
           Summary: target hook HARD_REGNO_RENAME_OK is too limiting
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: matz at gcc dot gnu.org
  Target Milestone: ---

This came up during fixing PR116650.  Essentially it's possible for regrename
choosing a new register N for a chain (having old register O) where N and O
have
unequal number of hard-regs to represent all modes occuring in the chain.

In the above bug that lead to checking freeness of new candidates only in terms
of the old register.  But even with that fixed the target hook
HARD_REGNO_RENAME_OK has an incomplete interface only taking hardreg numbers.

Right now it's used in regrename.cc:check_new_reg_p like so:

  for (i = nregs - 1; i >= 0; --)
    ...
    || ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i))

I.e. it assumes that old and new reg agree in the number of necessary hardregs.
That simply isn't the case always.  Even if it were it's not quite clear how
the later register numbers should be interpreted inside the target hook.

E.g. assume that regrename decides to rename r16:DF into r2:DF, and also assume
that r0-15 are SImode (hence we need two for DFmode) and r16 onwards are DFmode
regs (only needs one).  Now the question towards the backend certainly needs to
be at least: "can r16 be renamed into r2, in principle?".  So:

  TARGETHOOK (r16, r2)

But asking also "TARGETHOOK (r16, r3)" doesn't make much sense here.
And asking "TARGETHOOK (r17, r3)" is completely wrong.  So, something needs
to give way.  An idea was to add a mode argument to the target hook and only
ask the starting register number:

  TARGETHOOK (DFmode, r16, r2)

(then the target can either do something with the mode or not.  Most targets
currently only inspect the src or target regnumber to not be "special", like
being a callee saved register that wasn't in fact saved.)

Something to keep in mind with that proposal (adding a mode argument) would be
that regrename can rename multi-mode chains.  I.e. a web of connected defs/uses
of a hardreg that have not just a single mode.  The proposal would still work
in light of that when the hooks would be called as part of the loop over
all uses of the chain (instead of within the loop over all nregs):

  for (tmp = this_head->first; tmp; tmp = tmp->next_use)
    ...
    if (!TARGETHOOK (GET_MODE (*tmp->loc), reg, new_reg))
      ... new_reg can't be used ...

Reply via email to