On Wed, May 12, 2021 at 3:44 AM Alexandre Oliva <ol...@adacore.com> wrote:
>
>
> default_zero_call_used_regs currently requires all potentially zeroed
> registers to offer a move opcode that accepts zero as an operand.
>
> This is not the case e.g. for ARM's r12/ip in Thumb mode, and it was
> not the case of FP registers on AArch64 as of GCC 10.
>
> This patch introduces a fallback strategy to zero out registers,
> copying from registers that have already been zeroed.  Adjacent
> sources to make up wider modes are also supported.
>
> This does not guarantee that there will be some zeroed-out register to
> use as the source, but it expands the cases in which the default
> implementation works out of the box.
>
> This patch was regstrapped on x86_64-linux-gnu, where it is not supposed
> to make any difference.  It was also tested with an older to which the
> feature was backported, with flag_zero_call_used_regs defaulting to ALL
> and to USED on x86_64-linux-gnu (bootstrap), arm-eabi, aarch64-elf, and
> a few other targets that didn't hit problems before or after the patch.
> ARM and AArch64 failed to build target libs in that tree without this
> patch, and succeeded with it.  AArch64 wouldn't have required the patch
> in mainline, because of improvements to movti.  Ok to install?

OK.

Thanks,
Richard.

>
> for  gcc/ChangeLog
>
>         * targhooks.c (default_zero_call_used_regs): Retry using
>         successfully-zeroed registers as sources.
> ---
>  gcc/targhooks.c |   93 
> +++++++++++++++++++++++++++++++++++++++++++++++++++----
>  1 file changed, 86 insertions(+), 7 deletions(-)
>
> diff --git a/gcc/targhooks.c b/gcc/targhooks.c
> index 2e0fdb797e093..1947ef26fd644 100644
> --- a/gcc/targhooks.c
> +++ b/gcc/targhooks.c
> @@ -1001,6 +1001,13 @@ default_zero_call_used_regs (HARD_REG_SET 
> need_zeroed_hardregs)
>  {
>    gcc_assert (!hard_reg_set_empty_p (need_zeroed_hardregs));
>
> +  HARD_REG_SET failed;
> +  CLEAR_HARD_REG_SET (failed);
> +  bool progress = false;
> +
> +  /* First, try to zero each register in need_zeroed_hardregs by
> +     loading a zero into it, taking note of any failures in
> +     FAILED.  */
>    for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
>      if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
>        {
> @@ -1010,16 +1017,88 @@ default_zero_call_used_regs (HARD_REG_SET 
> need_zeroed_hardregs)
>         rtx_insn *insn = emit_move_insn (regno_reg_rtx[regno], zero);
>         if (!valid_insn_p (insn))
>           {
> -           static bool issued_error;
> -           if (!issued_error)
> -             {
> -               issued_error = true;
> -               sorry ("%qs not supported on this target",
> -                       "-fzero-call-used-regs");
> -             }
> +           SET_HARD_REG_BIT (failed, regno);
>             delete_insns_since (last_insn);
>           }
> +       else
> +         progress = true;
>        }
> +
> +  /* Now retry with copies from zeroed registers, as long as we've
> +     made some PROGRESS, and registers remain to be zeroed in
> +     FAILED.  */
> +  while (progress && !hard_reg_set_empty_p (failed))
> +    {
> +      HARD_REG_SET retrying = failed;
> +
> +      CLEAR_HARD_REG_SET (failed);
> +      progress = false;
> +
> +      for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
> +       if (TEST_HARD_REG_BIT (retrying, regno))
> +         {
> +           machine_mode mode = GET_MODE (regno_reg_rtx[regno]);
> +           bool success = false;
> +           /* Look for a source.  */
> +           for (unsigned int src = 0; src < FIRST_PSEUDO_REGISTER; src++)
> +             {
> +               /* If SRC hasn't been zeroed (yet?), skip it.  */
> +               if (! TEST_HARD_REG_BIT (need_zeroed_hardregs, src))
> +                 continue;
> +               if (TEST_HARD_REG_BIT (retrying, src))
> +                 continue;
> +
> +               /* Check that SRC can hold MODE, and that any other
> +                  registers needed to hold MODE in SRC have also been
> +                  zeroed.  */
> +               if (!targetm.hard_regno_mode_ok (src, mode))
> +                 continue;
> +               unsigned n = targetm.hard_regno_nregs (src, mode);
> +               bool ok = true;
> +               for (unsigned i = 1; ok && i < n; i++)
> +                 ok = (TEST_HARD_REG_BIT (need_zeroed_hardregs, src + i)
> +                       && !TEST_HARD_REG_BIT (retrying, src + i));
> +               if (!ok)
> +                 continue;
> +
> +               /* SRC is usable, try to copy from it.  */
> +               rtx_insn *last_insn = get_last_insn ();
> +               rtx zsrc = gen_rtx_REG (mode, src);
> +               rtx_insn *insn = emit_move_insn (regno_reg_rtx[regno], zsrc);
> +               if (!valid_insn_p (insn))
> +                 /* It didn't work, remove any inserts.  We'll look
> +                    for another SRC.  */
> +                 delete_insns_since (last_insn);
> +               else
> +                 {
> +                   /* We're done for REGNO.  */
> +                   success = true;
> +                   break;
> +                 }
> +             }
> +
> +           /* If nothing worked for REGNO this round, marked it to be
> +              retried if we get another round.  */
> +           if (!success)
> +             SET_HARD_REG_BIT (failed, regno);
> +           else
> +             /* Take note so as to enable another round if needed.  */
> +             progress = true;
> +         }
> +    }
> +
> +  /* If any register remained, report it.  */
> +  if (!progress)
> +    {
> +      static bool issued_error;
> +      if (!issued_error)
> +       {
> +         issued_error = true;
> +         sorry ("%qs not supported on this target",
> +                "-fzero-call-used-regs");
> +       }
> +    }
> +
>    return need_zeroed_hardregs;
>  }
>
>
> --
> Alexandre Oliva, happy hacker                https://FSFLA.org/blogs/lxo/
>    Free Software Activist                       GNU Toolchain Engineer
> Disinformation flourishes because many people care deeply about injustice
> but very few check the facts.  Ask me about <https://stallmansupport.org>

Reply via email to