public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* retry zero-call-used-regs from zeroed regs
@ 2021-05-12  1:22 Alexandre Oliva
  2021-05-12  9:04 ` Richard Biener
  0 siblings, 1 reply; 2+ messages in thread
From: Alexandre Oliva @ 2021-05-12  1:22 UTC (permalink / raw)
  To: gcc-patches


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?


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>

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: retry zero-call-used-regs from zeroed regs
  2021-05-12  1:22 retry zero-call-used-regs from zeroed regs Alexandre Oliva
@ 2021-05-12  9:04 ` Richard Biener
  0 siblings, 0 replies; 2+ messages in thread
From: Richard Biener @ 2021-05-12  9:04 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: GCC Patches

On Wed, May 12, 2021 at 3:44 AM Alexandre Oliva <oliva@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>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-05-12  9:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-12  1:22 retry zero-call-used-regs from zeroed regs Alexandre Oliva
2021-05-12  9:04 ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).