> Am 10.10.2024 um 16:56 schrieb Michael Matz <m...@suse.de>:
>
> (this came up for m68k vs. LRA, but is a generic problem)
>
> Regrename wants to use new registers for certain def-use chains.
> For validity of replacements it needs to check that the selected
> candidates are unused up to then. That's done in check_new_reg_p.
> But if it so happens that the new register needs more hardregs
> than the old register (which happens if the target allows inter-bank
> moves and the mode is something like a DFmode that needs to be placed
> into a SImode reg-pair), then check_new_reg_p only checks the
> first of those registers for free-ness.
>
> This is caused by that function looking up the number of necessary
> hardregs only in terms of the old hardreg number. It of course needs
> to do that in terms of the new candidate regnumber. The symptom is that
> regrename sometimes clobbers the higher numbered registers of such a
> regrename target pair. This patch fixes that problem.
>
> (In the particular case of the bug report it was LRA that left over a
> inter-bank move instruction that triggers regrename, ultimately causing
> the mis-compile. Reload didn't do that, but in general we of course
> can't rely on such moves not happening if the target allows them.)
>
> This also shows a general confusion in that function and the target hook
> interface here:
>
> for (i = nregs - 1; i >= 0; --)
> ...
> || ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i))
>
> it uses nregs in a way that requires it to be the same between old and
> new register. The problem is that the target hook only gets register
> numbers, when it instead should get a mode and register numbers and
> would be called only for the first but not for subsequent registers.
> I've looked at a number of definitions of that target hook and I think
> that this is currently harmless in the sense that it would merely rule
> out some potential reg-renames that would in fact be okay to do. So I'm
> not changing the target hook interface here and hence that problem
> remains unfixed.
Can you please open a bugreport tracking this?
The patch is OK.
Thanks,
Richard
> PR rtl-optimization/116650
> * regrename.cc (check_new_reg_p): Calculate nregs in terms of
> the new candidate register.
> ---
>
> Regstrapped on x86-64-linux, okay for trunk?
>
>
> Ciao,
> Michael.
>
> ---
> gcc/regrename.cc | 25 +++++++++++++++++++------
> 1 file changed, 19 insertions(+), 6 deletions(-)
>
> diff --git a/gcc/regrename.cc b/gcc/regrename.cc
> index 054e601740b..22668d7bf57 100644
> --- a/gcc/regrename.cc
> +++ b/gcc/regrename.cc
> @@ -324,10 +324,27 @@ static bool
> check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
> class du_head *this_head, HARD_REG_SET this_unavailable)
> {
> - int nregs = this_head->nregs;
> + int nregs = 1;
> int i;
> struct du_chain *tmp;
>
> + /* See whether new_reg accepts all modes that occur in
> + definition and uses and record the number of regs it would take. */
> + for (tmp = this_head->first; tmp; tmp = tmp->next_use)
> + {
> + int n;
> + /* Completely ignore DEBUG_INSNs, otherwise we can get
> + -fcompare-debug failures. */
> + if (DEBUG_INSN_P (tmp->insn))
> + continue;
> +
> + if (!targetm.hard_regno_mode_ok (new_reg, GET_MODE (*tmp->loc)))
> + return false;
> + n = hard_regno_nregs (new_reg, GET_MODE (*tmp->loc));
> + if (n > nregs)
> + nregs = n;
> + }
> +
> for (i = nregs - 1; i >= 0; --i)
> if (TEST_HARD_REG_BIT (this_unavailable, new_reg + i)
> || fixed_regs[new_reg + i]
> @@ -348,14 +365,10 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
> definition and uses. */
> for (tmp = this_head->first; tmp; tmp = tmp->next_use)
> {
> - /* Completely ignore DEBUG_INSNs, otherwise we can get
> - -fcompare-debug failures. */
> if (DEBUG_INSN_P (tmp->insn))
> continue;
>
> - if (!targetm.hard_regno_mode_ok (new_reg, GET_MODE (*tmp->loc))
> - || call_clobbered_in_chain_p (this_head, GET_MODE (*tmp->loc),
> - new_reg))
> + if (call_clobbered_in_chain_p (this_head, GET_MODE (*tmp->loc),
> new_reg))
> return false;
> }
>
> --
> 2.39.1