public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
@ 2022-10-21  7:31 Alexandre Oliva
  2022-10-21 14:26 ` Qing Zhao
  0 siblings, 1 reply; 13+ messages in thread
From: Alexandre Oliva @ 2022-10-21  7:31 UTC (permalink / raw)
  To: gcc-patches; +Cc: Qing Zhao

Introduce 'leafy' to auto-select between 'used' and 'all' for leaf and
nonleaf functions, respectively.

Regstrapped on x86_64-linux-gnu.  Ok to install?


for  gcc/ChangeLog

	* doc/extend.texi (zero-call-used-regs): Document leafy and
	variants thereof.
	* flag-types.h (zero_regs_flags): Add LEAFY_MODE, as well as
	LEAFY and variants.
	* function.cc (gen_call_ued_regs_seq): Set only_used for leaf
	functions in leafy mode.
	* opts.cc (zero_call_used_regs_opts): Add leafy and variants.

for  gcc/testsuite/ChangeLog

	* c-c++-common/zero-scratch-regs-leafy-1.c: New.
	* c-c++-common/zero-scratch-regs-leafy-2.c: New.
	* gcc.target/i386/zero-scratch-regs-leafy-1.c: New.
	* gcc.target/i386/zero-scratch-regs-leafy-2.c: New.
---
 gcc/doc/extend.texi                                |   22 ++++++++++++++++++--
 gcc/flag-types.h                                   |    5 +++++
 gcc/function.cc                                    |    3 +++
 gcc/opts.cc                                        |    4 ++++
 .../c-c++-common/zero-scratch-regs-leafy-1.c       |   15 ++++++++++++++
 .../c-c++-common/zero-scratch-regs-leafy-2.c       |   21 +++++++++++++++++++
 .../gcc.target/i386/zero-scratch-regs-leafy-1.c    |   12 +++++++++++
 .../gcc.target/i386/zero-scratch-regs-leafy-2.c    |   16 +++++++++++++++
 8 files changed, 96 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
 create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 04af0584d82cc..bf11956c467fb 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -4391,10 +4391,28 @@ zeros all call-used registers that pass arguments.
 @item all-gpr-arg
 zeros all call-used general purpose registers that pass
 arguments.
+
+@item leafy
+Same as @samp{used} in a leaf function, and same as @samp{all} in a
+nonleaf function.
+
+@item leafy-gpr
+Same as @samp{used-gpr} in a leaf function, and same as @samp{all-gpr}
+in a nonleaf function.
+
+@item leafy-arg
+Same as @samp{used-arg} in a leaf function, and same as @samp{all-arg}
+in a nonleaf function.
+
+@item leafy-gpr-arg
+Same as @samp{used-gpr-arg} in a leaf function, and same as
+@samp{all-gpr-arg} in a nonleaf function.
+
 @end table
 
-Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{all-arg},
-and @samp{all-gpr-arg} are mainly used for ROP mitigation.
+Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{leafy-arg},
+@samp{leafy-gpr-arg}, @samp{all-arg}, and @samp{all-gpr-arg} are mainly
+used for ROP mitigation.
 
 The default for the attribute is controlled by @option{-fzero-call-used-regs}.
 @end table
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index d2e751060ffce..b90c85167dcd4 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -338,6 +338,7 @@ namespace zero_regs_flags {
   const unsigned int ONLY_GPR = 1UL << 2;
   const unsigned int ONLY_ARG = 1UL << 3;
   const unsigned int ENABLED = 1UL << 4;
+  const unsigned int LEAFY_MODE = 1UL << 5;
   const unsigned int USED_GPR_ARG = ENABLED | ONLY_USED | ONLY_GPR | ONLY_ARG;
   const unsigned int USED_GPR = ENABLED | ONLY_USED | ONLY_GPR;
   const unsigned int USED_ARG = ENABLED | ONLY_USED | ONLY_ARG;
@@ -346,6 +347,10 @@ namespace zero_regs_flags {
   const unsigned int ALL_GPR = ENABLED | ONLY_GPR;
   const unsigned int ALL_ARG = ENABLED | ONLY_ARG;
   const unsigned int ALL = ENABLED;
+  const unsigned int LEAFY_GPR_ARG = ENABLED | LEAFY_MODE | ONLY_GPR | ONLY_ARG;
+  const unsigned int LEAFY_GPR = ENABLED | LEAFY_MODE | ONLY_GPR;
+  const unsigned int LEAFY_ARG = ENABLED | LEAFY_MODE | ONLY_ARG;
+  const unsigned int LEAFY = ENABLED | LEAFY_MODE;
 }
 
 /* Settings of flag_incremental_link.  */
diff --git a/gcc/function.cc b/gcc/function.cc
index 6474a663b30b8..16582e698041a 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -5879,6 +5879,9 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
   only_used = zero_regs_type & ONLY_USED;
   only_arg = zero_regs_type & ONLY_ARG;
 
+  if ((zero_regs_type & LEAFY_MODE) && leaf_function_p ())
+    only_used = true;
+
   /* For each of the hard registers, we should zero it if:
 	    1. it is a call-used register;
 	and 2. it is not a fixed register;
diff --git a/gcc/opts.cc b/gcc/opts.cc
index ae079fcd20eea..39f6a1b278dc6 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -2099,6 +2099,10 @@ const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
   ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
   ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
   ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
+  ZERO_CALL_USED_REGS_OPT (leafy-gpr-arg, zero_regs_flags::LEAFY_GPR_ARG),
+  ZERO_CALL_USED_REGS_OPT (leafy-gpr, zero_regs_flags::LEAFY_GPR),
+  ZERO_CALL_USED_REGS_OPT (leafy-arg, zero_regs_flags::LEAFY_ARG),
+  ZERO_CALL_USED_REGS_OPT (leafy, zero_regs_flags::LEAFY),
 #undef ZERO_CALL_USED_REGS_OPT
   {NULL, 0U}
 };
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
new file mode 100644
index 0000000000000..c1a0c31ba1c37
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fzero-call-used-regs=leafy" } */
+
+volatile int result = 0;
+int 
+__attribute__((noipa))
+foo (int x)
+{
+  return x;
+}
+int main()
+{
+  result = foo (2);
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
new file mode 100644
index 0000000000000..d450620c1fcfe
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <assert.h>
+int result = 0;
+
+int 
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("leafy")))
+foo1 (int x)
+{
+  return (x + 1);
+}
+
+int 
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("leafy")))
+foo2 (int x)
+{
+  return foo1 (x + 2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
new file mode 100644
index 0000000000000..2277710c771b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fzero-call-used-regs=leafy -fno-stack-protector -fno-PIC" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
new file mode 100644
index 0000000000000..24b85c3dbb766
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fzero-call-used-regs=leafy-gpr -fno-stack-protector -fno-PIC" } */
+
+extern int bar (int);
+
+void
+foo (void)
+{
+  int x = bar (0);
+  if (x)
+    bar (1);
+}
+
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%ecx, %ecx" } } */

-- 
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] 13+ messages in thread

* Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
  2022-10-21  7:31 [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs Alexandre Oliva
@ 2022-10-21 14:26 ` Qing Zhao
  2022-10-25  2:48   ` Alexandre Oliva
  0 siblings, 1 reply; 13+ messages in thread
From: Qing Zhao @ 2022-10-21 14:26 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

Hi, Alexandre,

Could you please explain a little bit on the motivation of this patch first?

thanks.

Qing

> On Oct 21, 2022, at 3:31 AM, Alexandre Oliva <oliva@adacore.com> wrote:
> 
> Introduce 'leafy' to auto-select between 'used' and 'all' for leaf and
> nonleaf functions, respectively.
> 
> Regstrapped on x86_64-linux-gnu.  Ok to install?
> 
> 
> for  gcc/ChangeLog
> 
> 	* doc/extend.texi (zero-call-used-regs): Document leafy and
> 	variants thereof.
> 	* flag-types.h (zero_regs_flags): Add LEAFY_MODE, as well as
> 	LEAFY and variants.
> 	* function.cc (gen_call_ued_regs_seq): Set only_used for leaf
> 	functions in leafy mode.
> 	* opts.cc (zero_call_used_regs_opts): Add leafy and variants.
> 
> for  gcc/testsuite/ChangeLog
> 
> 	* c-c++-common/zero-scratch-regs-leafy-1.c: New.
> 	* c-c++-common/zero-scratch-regs-leafy-2.c: New.
> 	* gcc.target/i386/zero-scratch-regs-leafy-1.c: New.
> 	* gcc.target/i386/zero-scratch-regs-leafy-2.c: New.
> ---
> gcc/doc/extend.texi                                |   22 ++++++++++++++++++--
> gcc/flag-types.h                                   |    5 +++++
> gcc/function.cc                                    |    3 +++
> gcc/opts.cc                                        |    4 ++++
> .../c-c++-common/zero-scratch-regs-leafy-1.c       |   15 ++++++++++++++
> .../c-c++-common/zero-scratch-regs-leafy-2.c       |   21 +++++++++++++++++++
> .../gcc.target/i386/zero-scratch-regs-leafy-1.c    |   12 +++++++++++
> .../gcc.target/i386/zero-scratch-regs-leafy-2.c    |   16 +++++++++++++++
> 8 files changed, 96 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> 
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 04af0584d82cc..bf11956c467fb 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -4391,10 +4391,28 @@ zeros all call-used registers that pass arguments.
> @item all-gpr-arg
> zeros all call-used general purpose registers that pass
> arguments.
> +
> +@item leafy
> +Same as @samp{used} in a leaf function, and same as @samp{all} in a
> +nonleaf function.
> +
> +@item leafy-gpr
> +Same as @samp{used-gpr} in a leaf function, and same as @samp{all-gpr}
> +in a nonleaf function.
> +
> +@item leafy-arg
> +Same as @samp{used-arg} in a leaf function, and same as @samp{all-arg}
> +in a nonleaf function.
> +
> +@item leafy-gpr-arg
> +Same as @samp{used-gpr-arg} in a leaf function, and same as
> +@samp{all-gpr-arg} in a nonleaf function.
> +
> @end table
> 
> -Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{all-arg},
> -and @samp{all-gpr-arg} are mainly used for ROP mitigation.
> +Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{leafy-arg},
> +@samp{leafy-gpr-arg}, @samp{all-arg}, and @samp{all-gpr-arg} are mainly
> +used for ROP mitigation.
> 
> The default for the attribute is controlled by @option{-fzero-call-used-regs}.
> @end table
> diff --git a/gcc/flag-types.h b/gcc/flag-types.h
> index d2e751060ffce..b90c85167dcd4 100644
> --- a/gcc/flag-types.h
> +++ b/gcc/flag-types.h
> @@ -338,6 +338,7 @@ namespace zero_regs_flags {
>   const unsigned int ONLY_GPR = 1UL << 2;
>   const unsigned int ONLY_ARG = 1UL << 3;
>   const unsigned int ENABLED = 1UL << 4;
> +  const unsigned int LEAFY_MODE = 1UL << 5;
>   const unsigned int USED_GPR_ARG = ENABLED | ONLY_USED | ONLY_GPR | ONLY_ARG;
>   const unsigned int USED_GPR = ENABLED | ONLY_USED | ONLY_GPR;
>   const unsigned int USED_ARG = ENABLED | ONLY_USED | ONLY_ARG;
> @@ -346,6 +347,10 @@ namespace zero_regs_flags {
>   const unsigned int ALL_GPR = ENABLED | ONLY_GPR;
>   const unsigned int ALL_ARG = ENABLED | ONLY_ARG;
>   const unsigned int ALL = ENABLED;
> +  const unsigned int LEAFY_GPR_ARG = ENABLED | LEAFY_MODE | ONLY_GPR | ONLY_ARG;
> +  const unsigned int LEAFY_GPR = ENABLED | LEAFY_MODE | ONLY_GPR;
> +  const unsigned int LEAFY_ARG = ENABLED | LEAFY_MODE | ONLY_ARG;
> +  const unsigned int LEAFY = ENABLED | LEAFY_MODE;
> }
> 
> /* Settings of flag_incremental_link.  */
> diff --git a/gcc/function.cc b/gcc/function.cc
> index 6474a663b30b8..16582e698041a 100644
> --- a/gcc/function.cc
> +++ b/gcc/function.cc
> @@ -5879,6 +5879,9 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
>   only_used = zero_regs_type & ONLY_USED;
>   only_arg = zero_regs_type & ONLY_ARG;
> 
> +  if ((zero_regs_type & LEAFY_MODE) && leaf_function_p ())
> +    only_used = true;
> +
>   /* For each of the hard registers, we should zero it if:
> 	    1. it is a call-used register;
> 	and 2. it is not a fixed register;
> diff --git a/gcc/opts.cc b/gcc/opts.cc
> index ae079fcd20eea..39f6a1b278dc6 100644
> --- a/gcc/opts.cc
> +++ b/gcc/opts.cc
> @@ -2099,6 +2099,10 @@ const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
>   ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
>   ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
>   ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
> +  ZERO_CALL_USED_REGS_OPT (leafy-gpr-arg, zero_regs_flags::LEAFY_GPR_ARG),
> +  ZERO_CALL_USED_REGS_OPT (leafy-gpr, zero_regs_flags::LEAFY_GPR),
> +  ZERO_CALL_USED_REGS_OPT (leafy-arg, zero_regs_flags::LEAFY_ARG),
> +  ZERO_CALL_USED_REGS_OPT (leafy, zero_regs_flags::LEAFY),
> #undef ZERO_CALL_USED_REGS_OPT
>   {NULL, 0U}
> };
> diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> new file mode 100644
> index 0000000000000..c1a0c31ba1c37
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> @@ -0,0 +1,15 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -fzero-call-used-regs=leafy" } */
> +
> +volatile int result = 0;
> +int 
> +__attribute__((noipa))
> +foo (int x)
> +{
> +  return x;
> +}
> +int main()
> +{
> +  result = foo (2);
> +  return 0;
> +}
> diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> new file mode 100644
> index 0000000000000..d450620c1fcfe
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> @@ -0,0 +1,21 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include <assert.h>
> +int result = 0;
> +
> +int 
> +__attribute__((noipa))
> +__attribute__ ((zero_call_used_regs("leafy")))
> +foo1 (int x)
> +{
> +  return (x + 1);
> +}
> +
> +int 
> +__attribute__((noipa))
> +__attribute__ ((zero_call_used_regs("leafy")))
> +foo2 (int x)
> +{
> +  return foo1 (x + 2);
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> new file mode 100644
> index 0000000000000..2277710c771b7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fzero-call-used-regs=leafy -fno-stack-protector -fno-PIC" } */
> +
> +void
> +foo (void)
> +{
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> new file mode 100644
> index 0000000000000..24b85c3dbb766
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fzero-call-used-regs=leafy-gpr -fno-stack-protector -fno-PIC" } */
> +
> +extern int bar (int);
> +
> +void
> +foo (void)
> +{
> +  int x = bar (0);
> +  if (x)
> +    bar (1);
> +}
> +
> +/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]+%ecx, %ecx" } } */
> 
> -- 
> 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] 13+ messages in thread

* Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
  2022-10-21 14:26 ` Qing Zhao
@ 2022-10-25  2:48   ` Alexandre Oliva
  2022-10-25 15:22     ` Qing Zhao
  0 siblings, 1 reply; 13+ messages in thread
From: Alexandre Oliva @ 2022-10-25  2:48 UTC (permalink / raw)
  To: Qing Zhao; +Cc: gcc-patches

Hello, Qing,

It was a pleasure to meet you at the Cauldron.


On Oct 21, 2022, Qing Zhao <qing.zhao@oracle.com> wrote:

> Hi, Alexandre,
> Could you please explain a little bit on the motivation of this patch first?

It was a suggestion I got after the Cauldron presentation.
It made sense to me, and was easy enough to implement.

'all' for leaf functions is likely wasteful.  If no other functions are
called, one can determine exactly which registers might carry
information out and thus need zeroing, and 'used' is thus likely enough,
depending on the purpose of register scrubbing.  (In some scenarios, it
might make sense to want scrubbing of all registers, even unused ones
that carry incoming values)

Though some functions are coded as leaf functions, others may become
leaf functions because of inlining or other optimizations.  It's hard
for users to predict, so it makes sense to have a mode that tells the
compiler to figure it out.


There's room for a follow-up improvement, to save on a little more
potentially-wasteful anti-leaking scrubbing even in non-leaf functions:
for this purpose, they need not scrub registers that they don't use
themselves, if all potential callees are known to have scrubbed them.

I have not (yet?) implemented this variant; I haven't even found a name
I'm happy with for it.  (seal?  plug?  cork?  another leak antonym?)

I'm not entirely happy with leafy either, FWIW.  Bikeshedding anyone? :-)

https://gcc.gnu.org/pipermail/gcc-patches/2022-October/604083.html

-- 
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] 13+ messages in thread

* Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
  2022-10-25  2:48   ` Alexandre Oliva
@ 2022-10-25 15:22     ` Qing Zhao
  2022-10-26 21:29       ` Alexandre Oliva
  0 siblings, 1 reply; 13+ messages in thread
From: Qing Zhao @ 2022-10-25 15:22 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

Hi, Alexandre,

> On Oct 24, 2022, at 10:48 PM, Alexandre Oliva <oliva@adacore.com> wrote:
> 
> Hello, Qing,
> 
> It was a pleasure to meet you at the Cauldron.

Me too!
> 
> 
> On Oct 21, 2022, Qing Zhao <qing.zhao@oracle.com> wrote:
> 
>> Hi, Alexandre,
>> Could you please explain a little bit on the motivation of this patch first?
> 
> It was a suggestion I got after the Cauldron presentation.
> It made sense to me, and was easy enough to implement.
> 
> 'all' for leaf functions is likely wasteful.  If no other functions are
> called, one can determine exactly which registers might carry
> information out and thus need zeroing, and 'used' is thus likely enough,
> depending on the purpose of register scrubbing.  (In some scenarios, it
> might make sense to want scrubbing of all registers, even unused ones
> that carry incoming values)

Under what kinds of situations, we should clear the un-used registers for leaf functions?


> 
> Though some functions are coded as leaf functions, others may become
> leaf functions because of inlining or other optimizations.  It's hard
> for users to predict, so it makes sense to have a mode that tells the
> compiler to figure it out.

Yes, make sense.

Now I am wondering whether we should make “leafy” mode by default then?


Another thing is, do you have any information on how much this new mode can save the 
code size and run-time compared to mode “all”?


> 
> 
> There's room for a follow-up improvement, to save on a little more
> potentially-wasteful anti-leaking scrubbing even in non-leaf functions:
> for this purpose, they need not scrub registers that they don't use
> themselves, if all potential callees are known to have scrubbed them.

Yes, looks like another potential improvement we might add. 
> 
> I have not (yet?) implemented this variant; I haven't even found a name
> I'm happy with for it.  (seal?  plug?  cork?  another leak antonym?)

For this improvement, I am still thinking no need to add a new mode, just add it by default?

Qing
> 
> I'm not entirely happy with leafy either, FWIW.  Bikeshedding anyone? :-)
> 
> https://gcc.gnu.org/pipermail/gcc-patches/2022-October/604083.html
> 
> -- 
> 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] 13+ messages in thread

* Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
  2022-10-25 15:22     ` Qing Zhao
@ 2022-10-26 21:29       ` Alexandre Oliva
  2022-10-27 13:30         ` Qing Zhao
  0 siblings, 1 reply; 13+ messages in thread
From: Alexandre Oliva @ 2022-10-26 21:29 UTC (permalink / raw)
  To: Qing Zhao; +Cc: gcc-patches

On Oct 25, 2022, Qing Zhao <qing.zhao@oracle.com> wrote:

>> 'all' for leaf functions is likely wasteful.  If no other functions are
>> called, one can determine exactly which registers might carry
>> information out and thus need zeroing, and 'used' is thus likely enough,
>> depending on the purpose of register scrubbing.  (In some scenarios, it
>> might make sense to want scrubbing of all registers, even unused ones
>> that carry incoming values)

> Under what kinds of situations, we should clear the un-used registers
> for leaf functions?

The one (admittedly contrived) scenario that comes to mind is calling an
out-of-line, empty leaf function with 'all' for explicit register
scrubbing at desired points in the program.  I.e., this empty leaf
function would be in charge of scrubbing the caller's registers.  It
could even be tail-called.

I'm sure there are other scenarios in which keeping at least the
possibility of 'all' is useful.

> Now I am wondering whether we should make “leafy” mode by default then?

I'm not sure what you mean by default.  I think "skip" is the right
default for general use, where register scrubbing is not explicitly
requested.  When it is, perhaps -fzero-call-used-regs without
'=<choice>' could be 'leafy' indeed or, even better, the extended form
thereof that is in search of a name and so far unimplemented.

> Another thing is, do you have any information on how much this new mode can save the 
> code size and run-time compared to mode “all”?

I'm afraid I have not performed any measurements.

>> I have not (yet?) implemented this variant; I haven't even found a name
>> I'm happy with for it.  (seal?  plug?  cork?  another leak antonym?)

> For this improvement, I am still thinking no need to add a new mode,
> just add it by default?

Even if it is default, it may still need a name to appear before
e.g. '-gpr'.  'default-gpr' might do, but I'm not happy with it either.


-- 
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] 13+ messages in thread

* Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
  2022-10-26 21:29       ` Alexandre Oliva
@ 2022-10-27 13:30         ` Qing Zhao
  2023-06-16  7:26           ` Alexandre Oliva
  0 siblings, 1 reply; 13+ messages in thread
From: Qing Zhao @ 2022-10-27 13:30 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches



> On Oct 26, 2022, at 5:29 PM, Alexandre Oliva <oliva@adacore.com> wrote:
> 
> On Oct 25, 2022, Qing Zhao <qing.zhao@oracle.com> wrote:
> 
>>> 'all' for leaf functions is likely wasteful.  If no other functions are
>>> called, one can determine exactly which registers might carry
>>> information out and thus need zeroing, and 'used' is thus likely enough,
>>> depending on the purpose of register scrubbing.  (In some scenarios, it
>>> might make sense to want scrubbing of all registers, even unused ones
>>> that carry incoming values)
> 
>> Under what kinds of situations, we should clear the un-used registers
>> for leaf functions?
> 
> The one (admittedly contrived) scenario that comes to mind is calling an
> out-of-line, empty leaf function with 'all' for explicit register
> scrubbing at desired points in the program.  I.e., this empty leaf
> function would be in charge of scrubbing the caller's registers.  It
> could even be tail-called.
> 
> I'm sure there are other scenarios in which keeping at least the
> possibility of 'all' is useful.
Okay.

> 
>> Now I am wondering whether we should make “leafy” mode by default then?
> 
> I'm not sure what you mean by default.  I think "skip" is the right
> default for general use, where register scrubbing is not explicitly
> requested.  When it is, perhaps -fzero-call-used-regs without
> '=<choice>' could be 'leafy' indeed or, even better, the extended form
> thereof that is in search of a name and so far unimplemented.

I guess that I was not clear in the previous email with the “by default”.
My previous point was:

If there is no need to clear the un-used registers for leaf functions, we can make the following change:

+  if ((zero_regs_type & LEAFY_MODE) && leaf_function_p ())
+    only_used = true;
+

As 

+  if ( leaf_function_p ())
+    only_used = true;
+

i.e, instead introducing a new MODE “LEAFY_MODE” and a new user sub-option, for LEAF functions, only
Clear its’ used registers even for “ALL”.

However, since there is need to clear the un-used registers for leaf functions. It looks like it is needed to provide
This new sub-option to users.

Is this clear this time?

> 
>> Another thing is, do you have any information on how much this new mode can save the 
>> code size and run-time compared to mode “all”?
> 
> I'm afraid I have not performed any measurements.

The major purpose of this new mode is to provide some improvement for the run-time and code-size. So, I think that 
Some information on this will be very helpful. Just a suggestion.


Another suggestion is: If this new mode is decided to add into GCC, the documentation might need to add more details on what’s the LEAFY mode,
The purpose of it, and how to use it, provide more details to the end-users
> 
>>> I have not (yet?) implemented this variant; I haven't even found a name
>>> I'm happy with for it.  (seal?  plug?  cork?  another leak antonym?)
> 
>> For this improvement, I am still thinking no need to add a new mode,
>> just add it by default?
> 
> Even if it is default, it may still need a name to appear before
> e.g. '-gpr'.  'default-gpr' might do, but I'm not happy with it either.

Default here, also means, no-need to introduce a user sub option, just add an optimization to the compiler. -:)

Qing
> 
> 
> -- 
> 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] 13+ messages in thread

* Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
  2022-10-27 13:30         ` Qing Zhao
@ 2023-06-16  7:26           ` Alexandre Oliva
  2023-06-16 19:34             ` Qing Zhao
  0 siblings, 1 reply; 13+ messages in thread
From: Alexandre Oliva @ 2023-06-16  7:26 UTC (permalink / raw)
  To: Qing Zhao; +Cc: gcc-patches

Hello, Qing,

On Oct 27, 2022, Qing Zhao <qing.zhao@oracle.com> wrote:
<https://gcc.gnu.org/pipermail/gcc-patches/2022-October/604480.html>

> On Oct 26, 2022, at 5:29 PM, Alexandre Oliva <oliva@adacore.com> wrote:
>> I'm sure there are other scenarios in which keeping at least the
>> possibility of 'all' is useful.
> Okay.


> i.e, instead introducing a new MODE “LEAFY_MODE” and a new user
> sub-option, for LEAF functions, only
> Clear its’ used registers even for “ALL”.

> However, since there is need to clear the un-used registers for leaf
> functions. It looks like it is needed to provide
> This new sub-option to users.

> Is this clear this time?

Yeah, I guess I understand what you mean.  But since there are cases in
which clearing all (call-clobbered) registers in a leaf function is
useful, I suppose it makes sense to offer both possibilities.

If there was a default operation mode for -fzero-call-used-regs, I guess
it would make sense to consider leafy the default, rather than all, but
since there isn't, and it always has to be specified explicitly, that's
not something to be considered.

So the available choices are:

1. introduce 'leafy' as a separate mode, leaving 'all' alone

2. change the behavior of 'all' to that of the proposed 'leafy', and either

2.a) add another mode that retains the currently-useful behavior of 'all',
   or

2.b) make the current behavior of 'all' no longer available

Personally, I find 1. the least disruptive to existing users of
-fzero-call-used-regs.  If we were introducing the option now, maybe 2.a
would be more sensible, but at this point, changing the meaning of 'all'
seems to be a disservice to security-sensitive users.

Those who would prefer the leaner operation on leaf functions can then
switch to 'leafy' mode, but that's better than finding carefully-crafted
code relying on the current behavior of 'all' for security suddenly
changes from under them, isn't it?


That said, I'm willing to implement the alternate change, if changing
the expected behavior is preferred over offering a different choice, if
needed to get closure on this feature.

For now, I'm just pinging the refreshed and retested patch.
Ok to install?


Add leafy mode for zero-call-used-regs

Introduce 'leafy' to auto-select between 'used' and 'all' for leaf and
nonleaf functions, respectively.


for  gcc/ChangeLog

	* doc/extend.texi (zero-call-used-regs): Document leafy and
	variants thereof.
	* flag-types.h (zero_regs_flags): Add LEAFY_MODE, as well as
	LEAFY and variants.
	* function.cc (gen_call_ued_regs_seq): Set only_used for leaf
	functions in leafy mode.
	* opts.cc (zero_call_used_regs_opts): Add leafy and variants.

for  gcc/testsuite/ChangeLog

	* c-c++-common/zero-scratch-regs-leafy-1.c: New.
	* c-c++-common/zero-scratch-regs-leafy-2.c: New.
	* gcc.target/i386/zero-scratch-regs-leafy-1.c: New.
	* gcc.target/i386/zero-scratch-regs-leafy-2.c: New.
---
 gcc/doc/extend.texi                                |   22 ++++++++++++++++++--
 gcc/flag-types.h                                   |    5 +++++
 gcc/function.cc                                    |    3 +++
 gcc/opts.cc                                        |    4 ++++
 .../c-c++-common/zero-scratch-regs-leafy-1.c       |   15 ++++++++++++++
 .../c-c++-common/zero-scratch-regs-leafy-2.c       |   21 +++++++++++++++++++
 .../gcc.target/i386/zero-scratch-regs-leafy-1.c    |   12 +++++++++++
 .../gcc.target/i386/zero-scratch-regs-leafy-2.c    |   16 +++++++++++++++
 8 files changed, 96 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
 create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 7b5592502734e..f8b0bb53ef5d4 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -4412,10 +4412,28 @@ zeros all call-used registers that pass arguments.
 @item all-gpr-arg
 zeros all call-used general purpose registers that pass
 arguments.
+
+@item leafy
+Same as @samp{used} in a leaf function, and same as @samp{all} in a
+nonleaf function.
+
+@item leafy-gpr
+Same as @samp{used-gpr} in a leaf function, and same as @samp{all-gpr}
+in a nonleaf function.
+
+@item leafy-arg
+Same as @samp{used-arg} in a leaf function, and same as @samp{all-arg}
+in a nonleaf function.
+
+@item leafy-gpr-arg
+Same as @samp{used-gpr-arg} in a leaf function, and same as
+@samp{all-gpr-arg} in a nonleaf function.
+
 @end table
 
-Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{all-arg},
-and @samp{all-gpr-arg} are mainly used for ROP mitigation.
+Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{leafy-arg},
+@samp{leafy-gpr-arg}, @samp{all-arg}, and @samp{all-gpr-arg} are mainly
+used for ROP mitigation.
 
 The default for the attribute is controlled by @option{-fzero-call-used-regs}.
 @end table
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index f83d165fbfef1..6a2e1beb997ef 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -348,6 +348,7 @@ namespace zero_regs_flags {
   const unsigned int ONLY_GPR = 1UL << 2;
   const unsigned int ONLY_ARG = 1UL << 3;
   const unsigned int ENABLED = 1UL << 4;
+  const unsigned int LEAFY_MODE = 1UL << 5;
   const unsigned int USED_GPR_ARG = ENABLED | ONLY_USED | ONLY_GPR | ONLY_ARG;
   const unsigned int USED_GPR = ENABLED | ONLY_USED | ONLY_GPR;
   const unsigned int USED_ARG = ENABLED | ONLY_USED | ONLY_ARG;
@@ -356,6 +357,10 @@ namespace zero_regs_flags {
   const unsigned int ALL_GPR = ENABLED | ONLY_GPR;
   const unsigned int ALL_ARG = ENABLED | ONLY_ARG;
   const unsigned int ALL = ENABLED;
+  const unsigned int LEAFY_GPR_ARG = ENABLED | LEAFY_MODE | ONLY_GPR | ONLY_ARG;
+  const unsigned int LEAFY_GPR = ENABLED | LEAFY_MODE | ONLY_GPR;
+  const unsigned int LEAFY_ARG = ENABLED | LEAFY_MODE | ONLY_ARG;
+  const unsigned int LEAFY = ENABLED | LEAFY_MODE;
 }
 
 /* Settings of flag_incremental_link.  */
diff --git a/gcc/function.cc b/gcc/function.cc
index 82102ed78d7e6..7b03f9e744199 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -5868,6 +5868,9 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
   only_used = zero_regs_type & ONLY_USED;
   only_arg = zero_regs_type & ONLY_ARG;
 
+  if ((zero_regs_type & LEAFY_MODE) && leaf_function_p ())
+    only_used = true;
+
   /* For each of the hard registers, we should zero it if:
 	    1. it is a call-used register;
 	and 2. it is not a fixed register;
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 86b94d62b588c..93c78be8b0d9a 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -2114,6 +2114,10 @@ const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
   ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
   ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
   ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
+  ZERO_CALL_USED_REGS_OPT (leafy-gpr-arg, zero_regs_flags::LEAFY_GPR_ARG),
+  ZERO_CALL_USED_REGS_OPT (leafy-gpr, zero_regs_flags::LEAFY_GPR),
+  ZERO_CALL_USED_REGS_OPT (leafy-arg, zero_regs_flags::LEAFY_ARG),
+  ZERO_CALL_USED_REGS_OPT (leafy, zero_regs_flags::LEAFY),
 #undef ZERO_CALL_USED_REGS_OPT
   {NULL, 0U}
 };
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
new file mode 100644
index 0000000000000..c1a0c31ba1c37
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fzero-call-used-regs=leafy" } */
+
+volatile int result = 0;
+int 
+__attribute__((noipa))
+foo (int x)
+{
+  return x;
+}
+int main()
+{
+  result = foo (2);
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
new file mode 100644
index 0000000000000..d450620c1fcfe
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <assert.h>
+int result = 0;
+
+int 
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("leafy")))
+foo1 (int x)
+{
+  return (x + 1);
+}
+
+int 
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("leafy")))
+foo2 (int x)
+{
+  return foo1 (x + 2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
new file mode 100644
index 0000000000000..2277710c771b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fzero-call-used-regs=leafy -fno-stack-protector -fno-PIC" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
new file mode 100644
index 0000000000000..24b85c3dbb766
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fzero-call-used-regs=leafy-gpr -fno-stack-protector -fno-PIC" } */
+
+extern int bar (int);
+
+void
+foo (void)
+{
+  int x = bar (0);
+  if (x)
+    bar (1);
+}
+
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%ecx, %ecx" } } */


-- 
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] 13+ messages in thread

* Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
  2023-06-16  7:26           ` Alexandre Oliva
@ 2023-06-16 19:34             ` Qing Zhao
  2023-06-22  1:16               ` Alexandre Oliva
  0 siblings, 1 reply; 13+ messages in thread
From: Qing Zhao @ 2023-06-16 19:34 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

Hi, Alexandre,

> On Jun 16, 2023, at 3:26 AM, Alexandre Oliva <oliva@adacore.com> wrote:
> 
> Hello, Qing,
> 
> On Oct 27, 2022, Qing Zhao <qing.zhao@oracle.com> wrote:
> <https://gcc.gnu.org/pipermail/gcc-patches/2022-October/604480.html>
> 
>> On Oct 26, 2022, at 5:29 PM, Alexandre Oliva <oliva@adacore.com> wrote:
>>> I'm sure there are other scenarios in which keeping at least the
>>> possibility of 'all' is useful.
>> Okay.
> 
> 
>> i.e, instead introducing a new MODE “LEAFY_MODE” and a new user
>> sub-option, for LEAF functions, only
>> Clear its’ used registers even for “ALL”.
> 
>> However, since there is need to clear the un-used registers for leaf
>> functions. It looks like it is needed to provide
>> This new sub-option to users.
> 
>> Is this clear this time?
> 
> Yeah, I guess I understand what you mean.  But since there are cases in
> which clearing all (call-clobbered) registers in a leaf function is
> useful, I suppose it makes sense to offer both possibilities.
agreed.
> 
> If there was a default operation mode for -fzero-call-used-regs, I guess
> it would make sense to consider leafy the default, rather than all, but
> since there isn't, and it always has to be specified explicitly, that's
> not something to be considered.
> 
> So the available choices are:
> 
> 1. introduce 'leafy' as a separate mode, leaving 'all' alone
> 
> 2. change the behavior of 'all' to that of the proposed 'leafy', and either
> 
> 2.a) add another mode that retains the currently-useful behavior of 'all',
>   or
> 
> 2.b) make the current behavior of 'all' no longer available
> 
> Personally, I find 1. the least disruptive to existing users of
> -fzero-call-used-regs.  If we were introducing the option now, maybe 2.a
> would be more sensible, but at this point, changing the meaning of 'all'
> seems to be a disservice to security-sensitive users.
> 
> Those who would prefer the leaner operation on leaf functions can then
> switch to 'leafy' mode, but that's better than finding carefully-crafted
> code relying on the current behavior of 'all' for security suddenly
> changes from under them, isn't it?

Yes, I agree.
> 
> 
> That said, I'm willing to implement the alternate change, if changing
> the expected behavior is preferred over offering a different choice, if
> needed to get closure on this feature.
> 
> For now, I'm just pinging the refreshed and retested patch.

As I mentioned in the previous round of review, I think that the documentation
 might need to add more details on what’s the LEAFY mode,
The purpose of it, and how to use it, provide more details to the end-users.


> Ok to install?
> 
> 
> Add leafy mode for zero-call-used-regs
> 
> Introduce 'leafy' to auto-select between 'used' and 'all' for leaf and
> nonleaf functions, respectively.
> 
> 
> for  gcc/ChangeLog
> 
> 	* doc/extend.texi (zero-call-used-regs): Document leafy and
> 	variants thereof.
> 	* flag-types.h (zero_regs_flags): Add LEAFY_MODE, as well as
> 	LEAFY and variants.
> 	* function.cc (gen_call_ued_regs_seq): Set only_used for leaf
> 	functions in leafy mode.
> 	* opts.cc (zero_call_used_regs_opts): Add leafy and variants.
> 
> for  gcc/testsuite/ChangeLog
> 
> 	* c-c++-common/zero-scratch-regs-leafy-1.c: New.
> 	* c-c++-common/zero-scratch-regs-leafy-2.c: New.
> 	* gcc.target/i386/zero-scratch-regs-leafy-1.c: New.
> 	* gcc.target/i386/zero-scratch-regs-leafy-2.c: New.
> ---
> gcc/doc/extend.texi                                |   22 ++++++++++++++++++--
> gcc/flag-types.h                                   |    5 +++++
> gcc/function.cc                                    |    3 +++
> gcc/opts.cc                                        |    4 ++++
> .../c-c++-common/zero-scratch-regs-leafy-1.c       |   15 ++++++++++++++
> .../c-c++-common/zero-scratch-regs-leafy-2.c       |   21 +++++++++++++++++++
> .../gcc.target/i386/zero-scratch-regs-leafy-1.c    |   12 +++++++++++
> .../gcc.target/i386/zero-scratch-regs-leafy-2.c    |   16 +++++++++++++++
> 8 files changed, 96 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> 
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 7b5592502734e..f8b0bb53ef5d4 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi

I think in the documentation of zero_call_used_regs, 

After the description of the 3 basic values: “skip”, “used”, and “all”. 
The description of the new value “leafy” need to be added first.

In addition to the below doc change.

The others LGTM.

Thanks.

Qing

> @@ -4412,10 +4412,28 @@ zeros all call-used registers that pass arguments.
> @item all-gpr-arg
> zeros all call-used general purpose registers that pass
> arguments.
> +
> +@item leafy
> +Same as @samp{used} in a leaf function, and same as @samp{all} in a
> +nonleaf function.
> +
> +@item leafy-gpr
> +Same as @samp{used-gpr} in a leaf function, and same as @samp{all-gpr}
> +in a nonleaf function.
> +
> +@item leafy-arg
> +Same as @samp{used-arg} in a leaf function, and same as @samp{all-arg}
> +in a nonleaf function.
> +
> +@item leafy-gpr-arg
> +Same as @samp{used-gpr-arg} in a leaf function, and same as
> +@samp{all-gpr-arg} in a nonleaf function.
> +
> @end table
> 
> -Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{all-arg},
> -and @samp{all-gpr-arg} are mainly used for ROP mitigation.
> +Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{leafy-arg},
> +@samp{leafy-gpr-arg}, @samp{all-arg}, and @samp{all-gpr-arg} are mainly
> +used for ROP mitigation.
> 
> The default for the attribute is controlled by @option{-fzero-call-used-regs}.
> @end table
> diff --git a/gcc/flag-types.h b/gcc/flag-types.h
> index f83d165fbfef1..6a2e1beb997ef 100644
> --- a/gcc/flag-types.h
> +++ b/gcc/flag-types.h
> @@ -348,6 +348,7 @@ namespace zero_regs_flags {
>   const unsigned int ONLY_GPR = 1UL << 2;
>   const unsigned int ONLY_ARG = 1UL << 3;
>   const unsigned int ENABLED = 1UL << 4;
> +  const unsigned int LEAFY_MODE = 1UL << 5;
>   const unsigned int USED_GPR_ARG = ENABLED | ONLY_USED | ONLY_GPR | ONLY_ARG;
>   const unsigned int USED_GPR = ENABLED | ONLY_USED | ONLY_GPR;
>   const unsigned int USED_ARG = ENABLED | ONLY_USED | ONLY_ARG;
> @@ -356,6 +357,10 @@ namespace zero_regs_flags {
>   const unsigned int ALL_GPR = ENABLED | ONLY_GPR;
>   const unsigned int ALL_ARG = ENABLED | ONLY_ARG;
>   const unsigned int ALL = ENABLED;
> +  const unsigned int LEAFY_GPR_ARG = ENABLED | LEAFY_MODE | ONLY_GPR | ONLY_ARG;
> +  const unsigned int LEAFY_GPR = ENABLED | LEAFY_MODE | ONLY_GPR;
> +  const unsigned int LEAFY_ARG = ENABLED | LEAFY_MODE | ONLY_ARG;
> +  const unsigned int LEAFY = ENABLED | LEAFY_MODE;
> }
> 
> /* Settings of flag_incremental_link.  */
> diff --git a/gcc/function.cc b/gcc/function.cc
> index 82102ed78d7e6..7b03f9e744199 100644
> --- a/gcc/function.cc
> +++ b/gcc/function.cc
> @@ -5868,6 +5868,9 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
>   only_used = zero_regs_type & ONLY_USED;
>   only_arg = zero_regs_type & ONLY_ARG;
> 
> +  if ((zero_regs_type & LEAFY_MODE) && leaf_function_p ())
> +    only_used = true;
> +
>   /* For each of the hard registers, we should zero it if:
> 	    1. it is a call-used register;
> 	and 2. it is not a fixed register;
> diff --git a/gcc/opts.cc b/gcc/opts.cc
> index 86b94d62b588c..93c78be8b0d9a 100644
> --- a/gcc/opts.cc
> +++ b/gcc/opts.cc
> @@ -2114,6 +2114,10 @@ const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
>   ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
>   ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
>   ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
> +  ZERO_CALL_USED_REGS_OPT (leafy-gpr-arg, zero_regs_flags::LEAFY_GPR_ARG),
> +  ZERO_CALL_USED_REGS_OPT (leafy-gpr, zero_regs_flags::LEAFY_GPR),
> +  ZERO_CALL_USED_REGS_OPT (leafy-arg, zero_regs_flags::LEAFY_ARG),
> +  ZERO_CALL_USED_REGS_OPT (leafy, zero_regs_flags::LEAFY),
> #undef ZERO_CALL_USED_REGS_OPT
>   {NULL, 0U}
> };
> diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> new file mode 100644
> index 0000000000000..c1a0c31ba1c37
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> @@ -0,0 +1,15 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -fzero-call-used-regs=leafy" } */
> +
> +volatile int result = 0;
> +int 
> +__attribute__((noipa))
> +foo (int x)
> +{
> +  return x;
> +}
> +int main()
> +{
> +  result = foo (2);
> +  return 0;
> +}
> diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> new file mode 100644
> index 0000000000000..d450620c1fcfe
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> @@ -0,0 +1,21 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include <assert.h>
> +int result = 0;
> +
> +int 
> +__attribute__((noipa))
> +__attribute__ ((zero_call_used_regs("leafy")))
> +foo1 (int x)
> +{
> +  return (x + 1);
> +}
> +
> +int 
> +__attribute__((noipa))
> +__attribute__ ((zero_call_used_regs("leafy")))
> +foo2 (int x)
> +{
> +  return foo1 (x + 2);
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> new file mode 100644
> index 0000000000000..2277710c771b7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fzero-call-used-regs=leafy -fno-stack-protector -fno-PIC" } */
> +
> +void
> +foo (void)
> +{
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> new file mode 100644
> index 0000000000000..24b85c3dbb766
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fzero-call-used-regs=leafy-gpr -fno-stack-protector -fno-PIC" } */
> +
> +extern int bar (int);
> +
> +void
> +foo (void)
> +{
> +  int x = bar (0);
> +  if (x)
> +    bar (1);
> +}
> +
> +/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]+%ecx, %ecx" } } */
> 
> 
> -- 
> 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] 13+ messages in thread

* Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
  2023-06-16 19:34             ` Qing Zhao
@ 2023-06-22  1:16               ` Alexandre Oliva
  2023-06-23 14:47                 ` Qing Zhao
  0 siblings, 1 reply; 13+ messages in thread
From: Alexandre Oliva @ 2023-06-22  1:16 UTC (permalink / raw)
  To: Qing Zhao; +Cc: gcc-patches

Hello, Qing,

On Jun 16, 2023, Qing Zhao <qing.zhao@oracle.com> wrote:

> As I mentioned in the previous round of review, I think that the documentation
>  might need to add more details on what’s the LEAFY mode,
> The purpose of it, and how to use it, provide more details to the end-users.

I'm afraid I'm having difficulty picturing what it is that you're
looking for.  The proposal incorporates, by reference, all the
documentation for 'used' and for 'all', and the way to use it is no
different.

>> +Same as @samp{used} in a leaf function, and same as @samp{all} in a
>> +nonleaf function.

If there was documentation on how to choose between e.g. all and used, I
suppose I could build on that to add this intermediate choice, but...  I
can't find any such docs, and I'm uncertain on whether adding that would
be useful to begin with.

Did you have something else in mind?

-- 
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] 13+ messages in thread

* Re: [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs
  2023-06-22  1:16               ` Alexandre Oliva
@ 2023-06-23 14:47                 ` Qing Zhao
  2023-06-23 23:27                   ` [PATCH v3] " Alexandre Oliva
  0 siblings, 1 reply; 13+ messages in thread
From: Qing Zhao @ 2023-06-23 14:47 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

Hi, Alexandre,


> On Jun 21, 2023, at 9:16 PM, Alexandre Oliva <oliva@adacore.com> wrote:
> 
> Hello, Qing,
> 
> On Jun 16, 2023, Qing Zhao <qing.zhao@oracle.com> wrote:
> 
>> As I mentioned in the previous round of review, I think that the documentation
>> might need to add more details on what’s the LEAFY mode,
>> The purpose of it, and how to use it, provide more details to the end-users.
> 
> I'm afraid I'm having difficulty picturing what it is that you're
> looking for.  The proposal incorporates, by reference, all the
> documentation for 'used' and for 'all', and the way to use it is no
> different.
> 
>>> +Same as @samp{used} in a leaf function, and same as @samp{all} in a
>>> +nonleaf function.

Oh, yeah.  The definition of “leafy” is here. -:)

It’s better to add this definition earlier in the list of the “three basic values”, to make it “four basic values”, like the following:

=======
In order to satisfy users with different security needs and control the
run-time overhead at the same time, the @var{choice} parameter provides a
flexible way to choose the subset of the call-used registers to be zeroed.
The four basic values of @var{choice} are:

@itemize @bullet
@item
@samp{skip} doesn't zero any call-used registers.

@item
@samp{used} only zeros call-used registers that are used in the function.
A ``used'' register is one whose content has been set or referenced in
the function.

@item
@samp{all} zeros all call-used registers.
@end itemize

@item
@samp{leafy} Same as @samp{used} in a leaf function, and same as @samp{all} in a
    nonleaf function. This value is mainly to provide users a more efficient mode to zero 
    call-used registers in leaf functions.
@end itemize
======

Then,  in the full list of choice, add the new values of leafy, leafy-gpr, leafy-arg, leafy-gpr-arg 

The sentence "This value is mainly to provide users a more efficient mode to zero 
    call-used registers in leaf functions.” just for your reference,  the wording can certainly be improved.  -:)
> 
> If there was documentation on how to choose between e.g. all and used, I
> suppose I could build on that to add this intermediate choice, but...  I
> can't find any such docs, and I'm uncertain on whether adding that would
> be useful to begin with.
> 
> Did you have something else in mind?


Hope this time I am clear (and sorry for the confusion in the previous emails).

thanks.

Qing

> 
> -- 
> 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] 13+ messages in thread

* [PATCH v3] Add leafy mode for zero-call-used-regs
  2023-06-23 14:47                 ` Qing Zhao
@ 2023-06-23 23:27                   ` Alexandre Oliva
  2023-06-26 13:58                     ` Qing Zhao
  0 siblings, 1 reply; 13+ messages in thread
From: Alexandre Oliva @ 2023-06-23 23:27 UTC (permalink / raw)
  To: Qing Zhao via Gcc-patches; +Cc: Qing Zhao

On Jun 23, 2023, Qing Zhao via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:

> It’s better to add this definition earlier in the list of the “three
> basic values”, to make it “four basic values”, like the following:

Oh, my, sorry for being so dense, I had managed to miss that bit all
this time somehow :-(

> The sentence "This value is mainly to provide users a more efficient mode to zero 
>     call-used registers in leaf functions.” just for your reference,
> the wording can certainly be improved.  -:)

:-)  got it, thanks.  How about this?


Add leafy mode for zero-call-used-regs

Introduce 'leafy' to auto-select between 'used' and 'all' for leaf and
nonleaf functions, respectively.

Regstrapped on x86_64-linux-gnu.  Ok to install?


for  gcc/ChangeLog

	* doc/extend.texi (zero-call-used-regs): Document leafy and
	variants thereof.
	* flag-types.h (zero_regs_flags): Add LEAFY_MODE, as well as
	LEAFY and variants.
	* function.cc (gen_call_ued_regs_seq): Set only_used for leaf
	functions in leafy mode.
	* opts.cc (zero_call_used_regs_opts): Add leafy and variants.

for  gcc/testsuite/ChangeLog

	* c-c++-common/zero-scratch-regs-leafy-1.c: New.
	* c-c++-common/zero-scratch-regs-leafy-2.c: New.
	* gcc.target/i386/zero-scratch-regs-leafy-1.c: New.
	* gcc.target/i386/zero-scratch-regs-leafy-2.c: New.
---
 gcc/doc/extend.texi                                |   30 ++++++++++++++++++--
 gcc/flag-types.h                                   |    5 +++
 gcc/function.cc                                    |    3 ++
 gcc/opts.cc                                        |    4 +++
 .../c-c++-common/zero-scratch-regs-leafy-1.c       |   15 ++++++++++
 .../c-c++-common/zero-scratch-regs-leafy-2.c       |   21 ++++++++++++++
 .../gcc.target/i386/zero-scratch-regs-leafy-1.c    |   12 ++++++++
 .../gcc.target/i386/zero-scratch-regs-leafy-2.c    |   16 +++++++++++
 8 files changed, 103 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
 create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 852f6b629bea8..739c40368f556 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -4349,7 +4349,7 @@ through registers.
 In order to satisfy users with different security needs and control the
 run-time overhead at the same time, the @var{choice} parameter provides a
 flexible way to choose the subset of the call-used registers to be zeroed.
-The three basic values of @var{choice} are:
+The four basic values of @var{choice} are:
 
 @itemize @bullet
 @item
@@ -4362,10 +4362,16 @@ the function.
 
 @item
 @samp{all} zeros all call-used registers.
+
+@item
+@samp{leafy} behaves like @samp{used} in a leaf function, and like
+@samp{all} in a nonleaf function.  This makes for leaner zeroing in leaf
+functions, where the set of used registers is known, and that may be
+enough for some purposes of register zeroing.
 @end itemize
 
 In addition to these three basic choices, it is possible to modify
-@samp{used} or @samp{all} as follows:
+@samp{used}, @samp{all}, and @samp{leafy} as follows:
 
 @itemize @bullet
 @item
@@ -4412,10 +4418,28 @@ zeros all call-used registers that pass arguments.
 @item all-gpr-arg
 zeros all call-used general purpose registers that pass
 arguments.
+
+@item leafy
+Same as @samp{used} in a leaf function, and same as @samp{all} in a
+nonleaf function.
+
+@item leafy-gpr
+Same as @samp{used-gpr} in a leaf function, and same as @samp{all-gpr}
+in a nonleaf function.
+
+@item leafy-arg
+Same as @samp{used-arg} in a leaf function, and same as @samp{all-arg}
+in a nonleaf function.
+
+@item leafy-gpr-arg
+Same as @samp{used-gpr-arg} in a leaf function, and same as
+@samp{all-gpr-arg} in a nonleaf function.
+
 @end table
 
 Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{all-arg},
-and @samp{all-gpr-arg} are mainly used for ROP mitigation.
+@samp{all-gpr-arg}, @samp{leafy-arg}, and @samp{leafy-gpr-arg} are
+mainly used for ROP mitigation.
 
 The default for the attribute is controlled by @option{-fzero-call-used-regs}.
 @end table
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 2e650bf1c487c..0d2dab1b99dd4 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -348,6 +348,7 @@ namespace zero_regs_flags {
   const unsigned int ONLY_GPR = 1UL << 2;
   const unsigned int ONLY_ARG = 1UL << 3;
   const unsigned int ENABLED = 1UL << 4;
+  const unsigned int LEAFY_MODE = 1UL << 5;
   const unsigned int USED_GPR_ARG = ENABLED | ONLY_USED | ONLY_GPR | ONLY_ARG;
   const unsigned int USED_GPR = ENABLED | ONLY_USED | ONLY_GPR;
   const unsigned int USED_ARG = ENABLED | ONLY_USED | ONLY_ARG;
@@ -356,6 +357,10 @@ namespace zero_regs_flags {
   const unsigned int ALL_GPR = ENABLED | ONLY_GPR;
   const unsigned int ALL_ARG = ENABLED | ONLY_ARG;
   const unsigned int ALL = ENABLED;
+  const unsigned int LEAFY_GPR_ARG = ENABLED | LEAFY_MODE | ONLY_GPR | ONLY_ARG;
+  const unsigned int LEAFY_GPR = ENABLED | LEAFY_MODE | ONLY_GPR;
+  const unsigned int LEAFY_ARG = ENABLED | LEAFY_MODE | ONLY_ARG;
+  const unsigned int LEAFY = ENABLED | LEAFY_MODE;
 }
 
 /* Settings of flag_incremental_link.  */
diff --git a/gcc/function.cc b/gcc/function.cc
index 6a79a8290f67e..dd2c1136e0725 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -5866,6 +5866,9 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
   only_used = zero_regs_type & ONLY_USED;
   only_arg = zero_regs_type & ONLY_ARG;
 
+  if ((zero_regs_type & LEAFY_MODE) && leaf_function_p ())
+    only_used = true;
+
   /* For each of the hard registers, we should zero it if:
 	    1. it is a call-used register;
 	and 2. it is not a fixed register;
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 3087bdac2c6c9..ac81d4e42944d 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -2115,6 +2115,10 @@ const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
   ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
   ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
   ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
+  ZERO_CALL_USED_REGS_OPT (leafy-gpr-arg, zero_regs_flags::LEAFY_GPR_ARG),
+  ZERO_CALL_USED_REGS_OPT (leafy-gpr, zero_regs_flags::LEAFY_GPR),
+  ZERO_CALL_USED_REGS_OPT (leafy-arg, zero_regs_flags::LEAFY_ARG),
+  ZERO_CALL_USED_REGS_OPT (leafy, zero_regs_flags::LEAFY),
 #undef ZERO_CALL_USED_REGS_OPT
   {NULL, 0U}
 };
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
new file mode 100644
index 0000000000000..c1a0c31ba1c37
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fzero-call-used-regs=leafy" } */
+
+volatile int result = 0;
+int 
+__attribute__((noipa))
+foo (int x)
+{
+  return x;
+}
+int main()
+{
+  result = foo (2);
+  return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
new file mode 100644
index 0000000000000..d450620c1fcfe
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <assert.h>
+int result = 0;
+
+int 
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("leafy")))
+foo1 (int x)
+{
+  return (x + 1);
+}
+
+int 
+__attribute__((noipa))
+__attribute__ ((zero_call_used_regs("leafy")))
+foo2 (int x)
+{
+  return foo1 (x + 2);
+}
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
new file mode 100644
index 0000000000000..2277710c771b7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fzero-call-used-regs=leafy -fno-stack-protector -fno-PIC" } */
+
+void
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler-not "vzeroall" } } */
+/* { dg-final { scan-assembler-not "%xmm" } } */
+/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
+/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
new file mode 100644
index 0000000000000..24b85c3dbb766
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fzero-call-used-regs=leafy-gpr -fno-stack-protector -fno-PIC" } */
+
+extern int bar (int);
+
+void
+foo (void)
+{
+  int x = bar (0);
+  if (x)
+    bar (1);
+}
+
+/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
+/* { dg-final { scan-assembler "xorl\[ \t\]+%ecx, %ecx" } } */


-- 
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] 13+ messages in thread

* Re: [PATCH v3] Add leafy mode for zero-call-used-regs
  2023-06-23 23:27                   ` [PATCH v3] " Alexandre Oliva
@ 2023-06-26 13:58                     ` Qing Zhao
  2023-06-27  6:27                       ` Richard Biener
  0 siblings, 1 reply; 13+ messages in thread
From: Qing Zhao @ 2023-06-26 13:58 UTC (permalink / raw)
  To: Alexandre Oliva, Richard Biener; +Cc: Qing Zhao via Gcc-patches



> On Jun 23, 2023, at 7:27 PM, Alexandre Oliva <oliva@adacore.com> wrote:
> 
> On Jun 23, 2023, Qing Zhao via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
> 
>> It’s better to add this definition earlier in the list of the “three
>> basic values”, to make it “four basic values”, like the following:
> 
> Oh, my, sorry for being so dense, I had managed to miss that bit all
> this time somehow :-(
> 
>> The sentence "This value is mainly to provide users a more efficient mode to zero 
>>    call-used registers in leaf functions.” just for your reference,
>> the wording can certainly be improved.  -:)
> 
> :-)  got it, thanks.  How about this?
> 
> 
> Add leafy mode for zero-call-used-regs
> 
> Introduce 'leafy' to auto-select between 'used' and 'all' for leaf and
> nonleaf functions, respectively.
> 
> Regstrapped on x86_64-linux-gnu.  Ok to install?

LGTM now.

However, I am not a reviewer,  you might still need approval from a middle-end reviewer.

thanks.

Qing


> 
> 
> for  gcc/ChangeLog
> 
> 	* doc/extend.texi (zero-call-used-regs): Document leafy and
> 	variants thereof.
> 	* flag-types.h (zero_regs_flags): Add LEAFY_MODE, as well as
> 	LEAFY and variants.
> 	* function.cc (gen_call_ued_regs_seq): Set only_used for leaf
> 	functions in leafy mode.
> 	* opts.cc (zero_call_used_regs_opts): Add leafy and variants.
> 
> for  gcc/testsuite/ChangeLog
> 
> 	* c-c++-common/zero-scratch-regs-leafy-1.c: New.
> 	* c-c++-common/zero-scratch-regs-leafy-2.c: New.
> 	* gcc.target/i386/zero-scratch-regs-leafy-1.c: New.
> 	* gcc.target/i386/zero-scratch-regs-leafy-2.c: New.
> ---
> gcc/doc/extend.texi                                |   30 ++++++++++++++++++--
> gcc/flag-types.h                                   |    5 +++
> gcc/function.cc                                    |    3 ++
> gcc/opts.cc                                        |    4 +++
> .../c-c++-common/zero-scratch-regs-leafy-1.c       |   15 ++++++++++
> .../c-c++-common/zero-scratch-regs-leafy-2.c       |   21 ++++++++++++++
> .../gcc.target/i386/zero-scratch-regs-leafy-1.c    |   12 ++++++++
> .../gcc.target/i386/zero-scratch-regs-leafy-2.c    |   16 +++++++++++
> 8 files changed, 103 insertions(+), 3 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> 
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 852f6b629bea8..739c40368f556 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -4349,7 +4349,7 @@ through registers.
> In order to satisfy users with different security needs and control the
> run-time overhead at the same time, the @var{choice} parameter provides a
> flexible way to choose the subset of the call-used registers to be zeroed.
> -The three basic values of @var{choice} are:
> +The four basic values of @var{choice} are:
> 
> @itemize @bullet
> @item
> @@ -4362,10 +4362,16 @@ the function.
> 
> @item
> @samp{all} zeros all call-used registers.
> +
> +@item
> +@samp{leafy} behaves like @samp{used} in a leaf function, and like
> +@samp{all} in a nonleaf function.  This makes for leaner zeroing in leaf
> +functions, where the set of used registers is known, and that may be
> +enough for some purposes of register zeroing.
> @end itemize
> 
> In addition to these three basic choices, it is possible to modify
> -@samp{used} or @samp{all} as follows:
> +@samp{used}, @samp{all}, and @samp{leafy} as follows:
> 
> @itemize @bullet
> @item
> @@ -4412,10 +4418,28 @@ zeros all call-used registers that pass arguments.
> @item all-gpr-arg
> zeros all call-used general purpose registers that pass
> arguments.
> +
> +@item leafy
> +Same as @samp{used} in a leaf function, and same as @samp{all} in a
> +nonleaf function.
> +
> +@item leafy-gpr
> +Same as @samp{used-gpr} in a leaf function, and same as @samp{all-gpr}
> +in a nonleaf function.
> +
> +@item leafy-arg
> +Same as @samp{used-arg} in a leaf function, and same as @samp{all-arg}
> +in a nonleaf function.
> +
> +@item leafy-gpr-arg
> +Same as @samp{used-gpr-arg} in a leaf function, and same as
> +@samp{all-gpr-arg} in a nonleaf function.
> +
> @end table
> 
> Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{all-arg},
> -and @samp{all-gpr-arg} are mainly used for ROP mitigation.
> +@samp{all-gpr-arg}, @samp{leafy-arg}, and @samp{leafy-gpr-arg} are
> +mainly used for ROP mitigation.
> 
> The default for the attribute is controlled by @option{-fzero-call-used-regs}.
> @end table
> diff --git a/gcc/flag-types.h b/gcc/flag-types.h
> index 2e650bf1c487c..0d2dab1b99dd4 100644
> --- a/gcc/flag-types.h
> +++ b/gcc/flag-types.h
> @@ -348,6 +348,7 @@ namespace zero_regs_flags {
>   const unsigned int ONLY_GPR = 1UL << 2;
>   const unsigned int ONLY_ARG = 1UL << 3;
>   const unsigned int ENABLED = 1UL << 4;
> +  const unsigned int LEAFY_MODE = 1UL << 5;
>   const unsigned int USED_GPR_ARG = ENABLED | ONLY_USED | ONLY_GPR | ONLY_ARG;
>   const unsigned int USED_GPR = ENABLED | ONLY_USED | ONLY_GPR;
>   const unsigned int USED_ARG = ENABLED | ONLY_USED | ONLY_ARG;
> @@ -356,6 +357,10 @@ namespace zero_regs_flags {
>   const unsigned int ALL_GPR = ENABLED | ONLY_GPR;
>   const unsigned int ALL_ARG = ENABLED | ONLY_ARG;
>   const unsigned int ALL = ENABLED;
> +  const unsigned int LEAFY_GPR_ARG = ENABLED | LEAFY_MODE | ONLY_GPR | ONLY_ARG;
> +  const unsigned int LEAFY_GPR = ENABLED | LEAFY_MODE | ONLY_GPR;
> +  const unsigned int LEAFY_ARG = ENABLED | LEAFY_MODE | ONLY_ARG;
> +  const unsigned int LEAFY = ENABLED | LEAFY_MODE;
> }
> 
> /* Settings of flag_incremental_link.  */
> diff --git a/gcc/function.cc b/gcc/function.cc
> index 6a79a8290f67e..dd2c1136e0725 100644
> --- a/gcc/function.cc
> +++ b/gcc/function.cc
> @@ -5866,6 +5866,9 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
>   only_used = zero_regs_type & ONLY_USED;
>   only_arg = zero_regs_type & ONLY_ARG;
> 
> +  if ((zero_regs_type & LEAFY_MODE) && leaf_function_p ())
> +    only_used = true;
> +
>   /* For each of the hard registers, we should zero it if:
> 	    1. it is a call-used register;
> 	and 2. it is not a fixed register;
> diff --git a/gcc/opts.cc b/gcc/opts.cc
> index 3087bdac2c6c9..ac81d4e42944d 100644
> --- a/gcc/opts.cc
> +++ b/gcc/opts.cc
> @@ -2115,6 +2115,10 @@ const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
>   ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
>   ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
>   ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
> +  ZERO_CALL_USED_REGS_OPT (leafy-gpr-arg, zero_regs_flags::LEAFY_GPR_ARG),
> +  ZERO_CALL_USED_REGS_OPT (leafy-gpr, zero_regs_flags::LEAFY_GPR),
> +  ZERO_CALL_USED_REGS_OPT (leafy-arg, zero_regs_flags::LEAFY_ARG),
> +  ZERO_CALL_USED_REGS_OPT (leafy, zero_regs_flags::LEAFY),
> #undef ZERO_CALL_USED_REGS_OPT
>   {NULL, 0U}
> };
> diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> new file mode 100644
> index 0000000000000..c1a0c31ba1c37
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> @@ -0,0 +1,15 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -fzero-call-used-regs=leafy" } */
> +
> +volatile int result = 0;
> +int 
> +__attribute__((noipa))
> +foo (int x)
> +{
> +  return x;
> +}
> +int main()
> +{
> +  result = foo (2);
> +  return 0;
> +}
> diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> new file mode 100644
> index 0000000000000..d450620c1fcfe
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> @@ -0,0 +1,21 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include <assert.h>
> +int result = 0;
> +
> +int 
> +__attribute__((noipa))
> +__attribute__ ((zero_call_used_regs("leafy")))
> +foo1 (int x)
> +{
> +  return (x + 1);
> +}
> +
> +int 
> +__attribute__((noipa))
> +__attribute__ ((zero_call_used_regs("leafy")))
> +foo2 (int x)
> +{
> +  return foo1 (x + 2);
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> new file mode 100644
> index 0000000000000..2277710c771b7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fzero-call-used-regs=leafy -fno-stack-protector -fno-PIC" } */
> +
> +void
> +foo (void)
> +{
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
> +/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> new file mode 100644
> index 0000000000000..24b85c3dbb766
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fzero-call-used-regs=leafy-gpr -fno-stack-protector -fno-PIC" } */
> +
> +extern int bar (int);
> +
> +void
> +foo (void)
> +{
> +  int x = bar (0);
> +  if (x)
> +    bar (1);
> +}
> +
> +/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]+%ecx, %ecx" } } */
> 
> 
> -- 
> 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] 13+ messages in thread

* Re: [PATCH v3] Add leafy mode for zero-call-used-regs
  2023-06-26 13:58                     ` Qing Zhao
@ 2023-06-27  6:27                       ` Richard Biener
  0 siblings, 0 replies; 13+ messages in thread
From: Richard Biener @ 2023-06-27  6:27 UTC (permalink / raw)
  To: Qing Zhao; +Cc: Alexandre Oliva, Qing Zhao via Gcc-patches

On Mon, 26 Jun 2023, Qing Zhao wrote:

> 
> 
> > On Jun 23, 2023, at 7:27 PM, Alexandre Oliva <oliva@adacore.com> wrote:
> > 
> > On Jun 23, 2023, Qing Zhao via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
> > 
> >> It?s better to add this definition earlier in the list of the ?three
> >> basic values?, to make it ?four basic values?, like the following:
> > 
> > Oh, my, sorry for being so dense, I had managed to miss that bit all
> > this time somehow :-(
> > 
> >> The sentence "This value is mainly to provide users a more efficient mode to zero 
> >>    call-used registers in leaf functions.? just for your reference,
> >> the wording can certainly be improved.  -:)
> > 
> > :-)  got it, thanks.  How about this?
> > 
> > 
> > Add leafy mode for zero-call-used-regs
> > 
> > Introduce 'leafy' to auto-select between 'used' and 'all' for leaf and
> > nonleaf functions, respectively.
> > 
> > Regstrapped on x86_64-linux-gnu.  Ok to install?
> 
> LGTM now.
> 
> However, I am not a reviewer,  you might still need approval from a middle-end reviewer.

OK.

> thanks.
> 
> Qing
> 
> 
> > 
> > 
> > for  gcc/ChangeLog
> > 
> > 	* doc/extend.texi (zero-call-used-regs): Document leafy and
> > 	variants thereof.
> > 	* flag-types.h (zero_regs_flags): Add LEAFY_MODE, as well as
> > 	LEAFY and variants.
> > 	* function.cc (gen_call_ued_regs_seq): Set only_used for leaf
> > 	functions in leafy mode.
> > 	* opts.cc (zero_call_used_regs_opts): Add leafy and variants.
> > 
> > for  gcc/testsuite/ChangeLog
> > 
> > 	* c-c++-common/zero-scratch-regs-leafy-1.c: New.
> > 	* c-c++-common/zero-scratch-regs-leafy-2.c: New.
> > 	* gcc.target/i386/zero-scratch-regs-leafy-1.c: New.
> > 	* gcc.target/i386/zero-scratch-regs-leafy-2.c: New.
> > ---
> > gcc/doc/extend.texi                                |   30 ++++++++++++++++++--
> > gcc/flag-types.h                                   |    5 +++
> > gcc/function.cc                                    |    3 ++
> > gcc/opts.cc                                        |    4 +++
> > .../c-c++-common/zero-scratch-regs-leafy-1.c       |   15 ++++++++++
> > .../c-c++-common/zero-scratch-regs-leafy-2.c       |   21 ++++++++++++++
> > .../gcc.target/i386/zero-scratch-regs-leafy-1.c    |   12 ++++++++
> > .../gcc.target/i386/zero-scratch-regs-leafy-2.c    |   16 +++++++++++
> > 8 files changed, 103 insertions(+), 3 deletions(-)
> > create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> > create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> > create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> > create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> > 
> > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> > index 852f6b629bea8..739c40368f556 100644
> > --- a/gcc/doc/extend.texi
> > +++ b/gcc/doc/extend.texi
> > @@ -4349,7 +4349,7 @@ through registers.
> > In order to satisfy users with different security needs and control the
> > run-time overhead at the same time, the @var{choice} parameter provides a
> > flexible way to choose the subset of the call-used registers to be zeroed.
> > -The three basic values of @var{choice} are:
> > +The four basic values of @var{choice} are:
> > 
> > @itemize @bullet
> > @item
> > @@ -4362,10 +4362,16 @@ the function.
> > 
> > @item
> > @samp{all} zeros all call-used registers.
> > +
> > +@item
> > +@samp{leafy} behaves like @samp{used} in a leaf function, and like
> > +@samp{all} in a nonleaf function.  This makes for leaner zeroing in leaf
> > +functions, where the set of used registers is known, and that may be
> > +enough for some purposes of register zeroing.
> > @end itemize
> > 
> > In addition to these three basic choices, it is possible to modify
> > -@samp{used} or @samp{all} as follows:
> > +@samp{used}, @samp{all}, and @samp{leafy} as follows:
> > 
> > @itemize @bullet
> > @item
> > @@ -4412,10 +4418,28 @@ zeros all call-used registers that pass arguments.
> > @item all-gpr-arg
> > zeros all call-used general purpose registers that pass
> > arguments.
> > +
> > +@item leafy
> > +Same as @samp{used} in a leaf function, and same as @samp{all} in a
> > +nonleaf function.
> > +
> > +@item leafy-gpr
> > +Same as @samp{used-gpr} in a leaf function, and same as @samp{all-gpr}
> > +in a nonleaf function.
> > +
> > +@item leafy-arg
> > +Same as @samp{used-arg} in a leaf function, and same as @samp{all-arg}
> > +in a nonleaf function.
> > +
> > +@item leafy-gpr-arg
> > +Same as @samp{used-gpr-arg} in a leaf function, and same as
> > +@samp{all-gpr-arg} in a nonleaf function.
> > +
> > @end table
> > 
> > Of this list, @samp{used-arg}, @samp{used-gpr-arg}, @samp{all-arg},
> > -and @samp{all-gpr-arg} are mainly used for ROP mitigation.
> > +@samp{all-gpr-arg}, @samp{leafy-arg}, and @samp{leafy-gpr-arg} are
> > +mainly used for ROP mitigation.
> > 
> > The default for the attribute is controlled by @option{-fzero-call-used-regs}.
> > @end table
> > diff --git a/gcc/flag-types.h b/gcc/flag-types.h
> > index 2e650bf1c487c..0d2dab1b99dd4 100644
> > --- a/gcc/flag-types.h
> > +++ b/gcc/flag-types.h
> > @@ -348,6 +348,7 @@ namespace zero_regs_flags {
> >   const unsigned int ONLY_GPR = 1UL << 2;
> >   const unsigned int ONLY_ARG = 1UL << 3;
> >   const unsigned int ENABLED = 1UL << 4;
> > +  const unsigned int LEAFY_MODE = 1UL << 5;
> >   const unsigned int USED_GPR_ARG = ENABLED | ONLY_USED | ONLY_GPR | ONLY_ARG;
> >   const unsigned int USED_GPR = ENABLED | ONLY_USED | ONLY_GPR;
> >   const unsigned int USED_ARG = ENABLED | ONLY_USED | ONLY_ARG;
> > @@ -356,6 +357,10 @@ namespace zero_regs_flags {
> >   const unsigned int ALL_GPR = ENABLED | ONLY_GPR;
> >   const unsigned int ALL_ARG = ENABLED | ONLY_ARG;
> >   const unsigned int ALL = ENABLED;
> > +  const unsigned int LEAFY_GPR_ARG = ENABLED | LEAFY_MODE | ONLY_GPR | ONLY_ARG;
> > +  const unsigned int LEAFY_GPR = ENABLED | LEAFY_MODE | ONLY_GPR;
> > +  const unsigned int LEAFY_ARG = ENABLED | LEAFY_MODE | ONLY_ARG;
> > +  const unsigned int LEAFY = ENABLED | LEAFY_MODE;
> > }
> > 
> > /* Settings of flag_incremental_link.  */
> > diff --git a/gcc/function.cc b/gcc/function.cc
> > index 6a79a8290f67e..dd2c1136e0725 100644
> > --- a/gcc/function.cc
> > +++ b/gcc/function.cc
> > @@ -5866,6 +5866,9 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
> >   only_used = zero_regs_type & ONLY_USED;
> >   only_arg = zero_regs_type & ONLY_ARG;
> > 
> > +  if ((zero_regs_type & LEAFY_MODE) && leaf_function_p ())
> > +    only_used = true;
> > +
> >   /* For each of the hard registers, we should zero it if:
> > 	    1. it is a call-used register;
> > 	and 2. it is not a fixed register;
> > diff --git a/gcc/opts.cc b/gcc/opts.cc
> > index 3087bdac2c6c9..ac81d4e42944d 100644
> > --- a/gcc/opts.cc
> > +++ b/gcc/opts.cc
> > @@ -2115,6 +2115,10 @@ const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
> >   ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
> >   ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
> >   ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
> > +  ZERO_CALL_USED_REGS_OPT (leafy-gpr-arg, zero_regs_flags::LEAFY_GPR_ARG),
> > +  ZERO_CALL_USED_REGS_OPT (leafy-gpr, zero_regs_flags::LEAFY_GPR),
> > +  ZERO_CALL_USED_REGS_OPT (leafy-arg, zero_regs_flags::LEAFY_ARG),
> > +  ZERO_CALL_USED_REGS_OPT (leafy, zero_regs_flags::LEAFY),
> > #undef ZERO_CALL_USED_REGS_OPT
> >   {NULL, 0U}
> > };
> > diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> > new file mode 100644
> > index 0000000000000..c1a0c31ba1c37
> > --- /dev/null
> > +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-1.c
> > @@ -0,0 +1,15 @@
> > +/* { dg-do run } */
> > +/* { dg-options "-O2 -fzero-call-used-regs=leafy" } */
> > +
> > +volatile int result = 0;
> > +int 
> > +__attribute__((noipa))
> > +foo (int x)
> > +{
> > +  return x;
> > +}
> > +int main()
> > +{
> > +  result = foo (2);
> > +  return 0;
> > +}
> > diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> > new file mode 100644
> > index 0000000000000..d450620c1fcfe
> > --- /dev/null
> > +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-leafy-2.c
> > @@ -0,0 +1,21 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2" } */
> > +
> > +#include <assert.h>
> > +int result = 0;
> > +
> > +int 
> > +__attribute__((noipa))
> > +__attribute__ ((zero_call_used_regs("leafy")))
> > +foo1 (int x)
> > +{
> > +  return (x + 1);
> > +}
> > +
> > +int 
> > +__attribute__((noipa))
> > +__attribute__ ((zero_call_used_regs("leafy")))
> > +foo2 (int x)
> > +{
> > +  return foo1 (x + 2);
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> > new file mode 100644
> > index 0000000000000..2277710c771b7
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-1.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fzero-call-used-regs=leafy -fno-stack-protector -fno-PIC" } */
> > +
> > +void
> > +foo (void)
> > +{
> > +}
> > +
> > +/* { dg-final { scan-assembler-not "vzeroall" } } */
> > +/* { dg-final { scan-assembler-not "%xmm" } } */
> > +/* { dg-final { scan-assembler-not "xorl\[ \t\]+%" } } */
> > +/* { dg-final { scan-assembler-not "movl\[ \t\]+%" } } */
> > diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> > new file mode 100644
> > index 0000000000000..24b85c3dbb766
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-leafy-2.c
> > @@ -0,0 +1,16 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -fzero-call-used-regs=leafy-gpr -fno-stack-protector -fno-PIC" } */
> > +
> > +extern int bar (int);
> > +
> > +void
> > +foo (void)
> > +{
> > +  int x = bar (0);
> > +  if (x)
> > +    bar (1);
> > +}
> > +
> > +/* { dg-final { scan-assembler "xorl\[ \t\]+%eax, %eax" } } */
> > +/* { dg-final { scan-assembler "xorl\[ \t\]+%edx, %edx" } } */
> > +/* { dg-final { scan-assembler "xorl\[ \t\]+%ecx, %ecx" } } */
> > 
> > 
> > -- 
> > 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>
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg,
Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman;
HRB 36809 (AG Nuernberg)

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

end of thread, other threads:[~2023-06-27  6:27 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-21  7:31 [PATCH zero-call-used-regs] Add leafy mode for zero-call-used-regs Alexandre Oliva
2022-10-21 14:26 ` Qing Zhao
2022-10-25  2:48   ` Alexandre Oliva
2022-10-25 15:22     ` Qing Zhao
2022-10-26 21:29       ` Alexandre Oliva
2022-10-27 13:30         ` Qing Zhao
2023-06-16  7:26           ` Alexandre Oliva
2023-06-16 19:34             ` Qing Zhao
2023-06-22  1:16               ` Alexandre Oliva
2023-06-23 14:47                 ` Qing Zhao
2023-06-23 23:27                   ` [PATCH v3] " Alexandre Oliva
2023-06-26 13:58                     ` Qing Zhao
2023-06-27  6:27                       ` 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).