public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Victor Rodriguez <vm.rod25@gmail.com>
To: Qing Zhao <QING.ZHAO@oracle.com>
Cc: Richard Biener <rguenther@suse.de>,
	Uros Bizjak <ubizjak@gmail.com>,  "H.J. Lu" <hjl.tools@gmail.com>,
	Jakub Jelinek <jakub@redhat.com>,
	 "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>,
	Kees Cook <keescook@chromium.org>,
	 "Rodriguez Bahena, Victor" <victor.rodriguez.bahena@intel.com>
Subject: Re: [Patch][Middle-end]Add -fzero-call-used-regs=[skip|used-gpr|all-gpr|used|all]
Date: Thu, 16 Jul 2020 08:17:24 -0500	[thread overview]
Message-ID: <CAK5mtewsYaq6PHxj-P4uKciC5Tb44Qr30X5Co=nZm2B_FUQBbg@mail.gmail.com> (raw)
In-Reply-To: <4ADA2BFC-DE6C-449E-84F7-2FFED4AF0789@ORACLE.COM>

On Tue, Jul 14, 2020 at 9:52 AM Qing Zhao via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Hi, Gcc team,
>
> This patch is a follow-up on the previous patch and corresponding discussion:
> https://gcc.gnu.org/pipermail/gcc-patches/2020-May/545101.html <https://gcc.gnu.org/pipermail/gcc-patches/2020-May/545101.html>
>
> From the previous round of discussion, the major issues raised were:
>
> A. should be rewritten by using regsets infrastructure.
> B. Put the patch into middle-end instead of x86 backend.
>
> This new patch is rewritten based on the above 2 comments.  The major changes compared to the previous patch are:
>
> 1. Change the names of the option and attribute from
> -mzero-caller-saved-regs=[skip|used-gpr|all-gpr|used|all]  and zero_caller_saved_regs("skip|used-gpr|all-gpr||used|all”)
> to:
> -fzero-call-used-regs=[skip|used-gpr|all-gpr|used|all]   and  zero_call_used_regs("skip|used-gpr|all-gpr||used|all”)
> Add the new option and  new attribute in general.
> 2. The main code generation part is moved from i386 backend to middle-end;
> 3. Add 4 target-hooks;
> 4. Implement these 4 target-hooks on i386 backend.
> 5. On a target that does not implement the target hook, issue error for the new option, issue warning for the new attribute.
>
> The patch is as following:
>
> [PATCH] Add -fzero-call-used-regs=[skip|used-gpr|all-gpr|used|all]
> command-line option and
> zero_call_used_regs("skip|used-gpr|all-gpr||used|all") function attribue:
>
>   1. -fzero-call-used-regs=skip and zero_call_used_regs("skip")
>
>   Don't zero call-used registers upon function return.
>
>   2. -fzero-call-used-regs=used-gpr and zero_call_used_regs("used-gpr")
>
>   Zero used call-used general purpose registers upon function return.
>
>   3. -fzero-call-used-regs=all-gpr and zero_call_used_regs("all-gpr")
>
>   Zero all call-used general purpose registers upon function return.
>
>   4. -fzero-call-used-regs=used and zero_call_used_regs("used")
>
>   Zero used call-used registers upon function return.
>
>   5. -fzero-call-used-regs=all and zero_call_used_regs("all")
>
>   Zero all call-used registers upon function return.
>
> The feature is implemented in middle-end. But currently is only valid on X86.
>
> Tested on x86-64 and aarch64 with bootstrapping GCC trunk, making
> -fzero-call-used-regs=used-gpr, -fzero-call-used-regs=all-gpr
> -fzero-call-used-regs=used, and -fzero-call-used-regs=all enabled
> by default on x86-64.
>
> Please take a look and let me know any more comment?
>
> thanks.
>
> Qing
>
>
> ====================================
>
> gcc/ChangeLog:
>
> 2020-07-13  qing zhao  <qing.zhao@oracle.com <mailto:qing.zhao@oracle.com>>
> 2020-07-13  H.J. Lu <hjl.tools@gmail.com <mailto:hjl.tools@gmail.com>>
>
>         * common.opt: Add new option -fzero-call-used-regs.
>         * config/i386/i386.c (ix86_zero_call_used_regno_p): New function.
>         (ix86_zero_call_used_regno_mode): Likewise.
>         (ix86_zero_all_vector_registers): Likewise.
>         (ix86_expand_prologue): Replace gen_prologue_use with
>         gen_pro_epilogue_use.
>         (TARGET_ZERO_CALL_USED_REGNO_P): Define.
>         (TARGET_ZERO_CALL_USED_REGNO_MODE): Define.
>         (TARGET_PRO_EPILOGUE_USE): Define.
>         (TARGET_ZERO_ALL_VECTOR_REGISTERS): Define.
>         * config/i386/i386.md: Replace UNSPECV_PROLOGUE_USE
>         with UNSPECV_PRO_EPILOGUE_USE.
>         * coretypes.h (enum zero_call_used_regs): New type.
>         * doc/extend.texi: Document the new zero_call_used_regs attribute.
>         * doc/invoke.texi: Document the new -fzero-call-used-regs option.
>         * doc/tm.texi: Regenerate.
>         * doc/tm.texi.in (TARGET_ZERO_CALL_USED_REGNO_P): New hook.
>         (TARGET_ZERO_CALL_USED_REGNO_MODE): Likewise.
>         (TARGET_PRO_EPILOGUE_USE): Likewise.
>         (TARGET_ZERO_ALL_VECTOR_REGISTERS): Likewise.
>         * function.c (is_live_reg_at_exit): New function.
>         (gen_call_used_regs_seq): Likewise.
>         (make_epilogue_seq): Call gen_call_used_regs_seq.
>         * function.h (is_live_reg_at_exit): Declare.
>         * target.def (zero_call_used_regno_p): New hook.
>         (zero_call_used_regno_mode): Likewise.
>         (pro_epilogue_use): Likewise.
>         (zero_all_vector_registers): Likewise.
>         * targhooks.c (default_zero_call_used_regno_p): New function.
>         (default_zero_call_used_regno_mode): Likewise.
>         * targhooks.h (default_zero_call_used_regno_p): Declare.
>         (default_zero_call_used_regno_mode): Declare.
>         * toplev.c (process_options): Issue errors when -fzero-call-used-regs
>         is used on targets that do not support it.
>         * tree-core.h (struct tree_decl_with_vis): New field
>         zero_call_used_regs_type.
>         * tree.h (DECL_ZERO_CALL_USED_REGS): New macro.
>
> gcc/c-family/ChangeLog:
>
> 2020-07-13  qing zhao  <qing.zhao@oracle.com <mailto:qing.zhao@oracle.com>>
> 2020-07-13  H.J. Lu <hjl.tools@gmail.com <mailto:hjl.tools@gmail.com>>
>
>         * c-attribs.c (c_common_attribute_table): Add new attribute
>         zero_call_used_regs.
>         (handle_zero_call_used_regs_attribute): New function.
>
> gcc/c/ChangeLog:
>
> 2020-07-13  qing zhao  <qing.zhao@oracle.com <mailto:qing.zhao@oracle.com>>
> 2020-07-13  H.J. Lu <hjl.tools@gmail.com <mailto:hjl.tools@gmail.com>>
>
>         * c-decl.c (merge_decls): Merge zero_call_used_regs_type.
>
> gcc/testsuite/ChangeLog:
>
> 2020-07-13  qing zhao  <qing.zhao@oracle.com <mailto:qing.zhao@oracle.com>>
> 2020-07-13  H.J. Lu <hjl.tools@gmail.com <mailto:hjl.tools@gmail.com>>
>
>         * c-c++-common/zero-scratch-regs-1.c: New test.
>         * c-c++-common/zero-scratch-regs-2.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-1.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-10.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-11.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-12.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-13.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-14.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-15.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-16.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-17.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-18.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-19.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-2.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-20.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-21.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-22.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-23.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-3.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-4.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-5.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-6.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-7.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-8.c: Likewise.
>         * gcc.target/i386/zero-scratch-regs-9.c: Likewise.
>
> ---
> gcc/c-family/c-attribs.c                           |  68 ++++++++++
> gcc/c/c-decl.c                                     |   4 +
> gcc/common.opt                                     |  23 ++++
> gcc/config/i386/i386.c                             |  58 ++++++++-
> gcc/config/i386/i386.md                            |   6 +-
> gcc/coretypes.h                                    |  10 ++
> gcc/doc/extend.texi                                |  11 ++
> gcc/doc/invoke.texi                                |  13 +-
> gcc/doc/tm.texi                                    |  27 ++++
> gcc/doc/tm.texi.in                                 |   8 ++
> gcc/function.c                                     | 145 +++++++++++++++++++++
> gcc/function.h                                     |   2 +
> gcc/target.def                                     |  33 +++++
> gcc/targhooks.c                                    |  17 +++
> gcc/targhooks.h                                    |   3 +
> gcc/testsuite/c-c++-common/zero-scratch-regs-1.c   |   3 +
> gcc/testsuite/c-c++-common/zero-scratch-regs-2.c   |   4 +
> .../gcc.target/i386/zero-scratch-regs-1.c          |  12 ++
> .../gcc.target/i386/zero-scratch-regs-10.c         |  21 +++
> .../gcc.target/i386/zero-scratch-regs-11.c         |  39 ++++++
> .../gcc.target/i386/zero-scratch-regs-12.c         |  39 ++++++
> .../gcc.target/i386/zero-scratch-regs-13.c         |  21 +++
> .../gcc.target/i386/zero-scratch-regs-14.c         |  19 +++
> .../gcc.target/i386/zero-scratch-regs-15.c         |  14 ++
> .../gcc.target/i386/zero-scratch-regs-16.c         |  14 ++
> .../gcc.target/i386/zero-scratch-regs-17.c         |  13 ++
> .../gcc.target/i386/zero-scratch-regs-18.c         |  13 ++
> .../gcc.target/i386/zero-scratch-regs-19.c         |  12 ++
> .../gcc.target/i386/zero-scratch-regs-2.c          |  19 +++
> .../gcc.target/i386/zero-scratch-regs-20.c         |  23 ++++
> .../gcc.target/i386/zero-scratch-regs-21.c         |  14 ++
> .../gcc.target/i386/zero-scratch-regs-22.c         |  19 +++
> .../gcc.target/i386/zero-scratch-regs-23.c         |  19 +++
> .../gcc.target/i386/zero-scratch-regs-3.c          |  12 ++
> .../gcc.target/i386/zero-scratch-regs-4.c          |  14 ++
> .../gcc.target/i386/zero-scratch-regs-5.c          |  20 +++
> .../gcc.target/i386/zero-scratch-regs-6.c          |  14 ++
> .../gcc.target/i386/zero-scratch-regs-7.c          |  13 ++
> .../gcc.target/i386/zero-scratch-regs-8.c          |  19 +++
> .../gcc.target/i386/zero-scratch-regs-9.c          |  15 +++
> gcc/toplev.c                                       |   9 ++
> gcc/tree-core.h                                    |   6 +-
> gcc/tree.h                                         |   5 +
> 43 files changed, 866 insertions(+), 7 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-1.c
> create mode 100644 gcc/testsuite/c-c++-common/zero-scratch-regs-2.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-1.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-10.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-11.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-12.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-13.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-14.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-15.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-16.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-17.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-18.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-19.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-2.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-20.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-21.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-22.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-23.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-3.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-4.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-5.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-6.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-7.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-8.c
> create mode 100644 gcc/testsuite/gcc.target/i386/zero-scratch-regs-9.c
>
> diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
> index 3721483..cc93d6f 100644
> --- a/gcc/c-family/c-attribs.c
> +++ b/gcc/c-family/c-attribs.c
> @@ -136,6 +136,8 @@ static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
> static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
> static tree ignore_attribute (tree *, tree, tree, int, bool *);
> static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
> +static tree handle_zero_call_used_regs_attribute (tree *, tree, tree, int,
> +                                                bool *);
> static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
> static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *);
> static tree handle_returns_nonnull_attribute (tree *, tree, tree, int, bool *);
> @@ -434,6 +436,9 @@ const struct attribute_spec c_common_attribute_table[] =
>                               ignore_attribute, NULL },
>   { "no_split_stack",         0, 0, true,  false, false, false,
>                               handle_no_split_stack_attribute, NULL },
> +  { "zero_call_used_regs",    1, 1, true, false, false, false,
> +                             handle_zero_call_used_regs_attribute, NULL },
> +
>   /* For internal use (marking of builtins and runtime functions) only.
>      The name contains space to prevent its usage in source code.  */
>   { "fn spec",                1, 1, false, true, true, false,
> @@ -4506,6 +4511,69 @@ handle_no_split_stack_attribute (tree *node, tree name,
>   return NULL_TREE;
> }
>
> +/* Handle a "zero_call_used_regs" attribute; arguments as in
> +   struct attribute_spec.handler.  */
> +
> +static tree
> +handle_zero_call_used_regs_attribute (tree *node, tree name, tree args,
> +                                     int ARG_UNUSED (flags),
> +                                     bool *no_add_attris)
> +{
> +  tree decl = *node;
> +  tree id = TREE_VALUE (args);
> +  enum zero_call_used_regs zero_call_used_regs_type = zero_call_used_regs_unset;
> +
> +  if (TREE_CODE (decl) != FUNCTION_DECL)
> +    {
> +      error_at (DECL_SOURCE_LOCATION (decl),
> +               "%qE attribute applies only to functions", name);
> +      *no_add_attris = true;
> +      return NULL_TREE;
> +    }
> +  else if (DECL_INITIAL (decl))
> +    {
> +      error_at (DECL_SOURCE_LOCATION (decl),
> +               "cannot set %qE attribute after definition", name);
> +      *no_add_attris = true;
> +      return NULL_TREE;
> +    }
> +
> +  if (TREE_CODE (id) != STRING_CST)
> +    {
> +      error ("attribute %qE arguments not a string", name);
> +      *no_add_attris = true;
> +      return NULL_TREE;
> +    }
> +
> +  if (!targetm.calls.pro_epilogue_use)
> +    {
> +      warning (OPT_Wattributes, "%qE attribute directive ignored", name);
> +      return NULL_TREE;
> +    }
> +
> +  if (strcmp (TREE_STRING_POINTER (id), "skip") == 0)
> +    zero_call_used_regs_type = zero_call_used_regs_skip;
> +  else if (strcmp (TREE_STRING_POINTER (id), "used-gpr") == 0)
> +    zero_call_used_regs_type = zero_call_used_regs_used_gpr;
> +  else if (strcmp (TREE_STRING_POINTER (id), "all-gpr") == 0)
> +    zero_call_used_regs_type = zero_call_used_regs_all_gpr;
> +  else if (strcmp (TREE_STRING_POINTER (id), "used") == 0)
> +    zero_call_used_regs_type = zero_call_used_regs_used;
> +  else if (strcmp (TREE_STRING_POINTER (id), "all") == 0)
> +    zero_call_used_regs_type = zero_call_used_regs_all;
> +  else
> +    {
> +      error ("attribute %qE argument must be one of %qs, %qs, %qs, %qs, or %qs",
> +            name, "skip", "used-gpr", "all-gpr", "used", "all");
> +      *no_add_attris = true;
> +      return NULL_TREE;
> +    }
> +
> +  DECL_ZERO_CALL_USED_REGS (decl) = zero_call_used_regs_type;
> +
> +  return NULL_TREE;
> +}
> +
> /* Handle a "returns_nonnull" attribute; arguments as in
>    struct attribute_spec.handler.  */
>
> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> index 81bd2ee..ded1880 100644
> --- a/gcc/c/c-decl.c
> +++ b/gcc/c/c-decl.c
> @@ -2681,6 +2681,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
>           DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
>         }
>
> +      /* Merge the zero_call_used_regs_type information.  */
> +      if (TREE_CODE (newdecl) == FUNCTION_DECL)
> +       DECL_ZERO_CALL_USED_REGS (newdecl) = DECL_ZERO_CALL_USED_REGS (olddecl);
> +
>       /* Merge the storage class information.  */
>       merge_weak (newdecl, olddecl);
>
> diff --git a/gcc/common.opt b/gcc/common.opt
> index df8af36..19900f9 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -3083,6 +3083,29 @@ fzero-initialized-in-bss
> Common Report Var(flag_zero_initialized_in_bss) Init(1)
> Put zero initialized data in the bss section.
>
> +fzero-call-used-regs=
> +Common Report RejectNegative Joined Enum(zero_call_used_regs) Var(flag_zero_call_used_regs) Init(zero_call_used_regs_skip)
> +Clear call-used registers upon function return.
> +
> +Enum
> +Name(zero_call_used_regs) Type(enum zero_call_used_regs)
> +Known choices of clearing call-used registers upon function return (for use with the -fzero-call-used-regs= option):
> +
> +EnumValue
> +Enum(zero_call_used_regs) String(skip) Value(zero_call_used_regs_skip)
> +
> +EnumValue
> +Enum(zero_call_used_regs) String(used-gpr) Value(zero_call_used_regs_used_gpr)
> +
> +EnumValue
> +Enum(zero_call_used_regs) String(all-gpr) Value(zero_call_used_regs_all_gpr)
> +
> +EnumValue
> +Enum(zero_call_used_regs) String(used) Value(zero_call_used_regs_used)
> +
> +EnumValue
> +Enum(zero_call_used_regs) String(all) Value(zero_call_used_regs_all)
> +
> g
> Common Driver RejectNegative JoinedOrMissing
> Generate debug information in default format.
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 5c373c0..fd1aa9c 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -3551,6 +3551,48 @@ ix86_function_value_regno_p (const unsigned int regno)
>   return false;
> }
>
> +/* TARGET_ZERO_CALL_USED_REGNO_P.  */
> +
> +static bool
> +ix86_zero_call_used_regno_p (const unsigned int regno,
> +                            bool gpr_only)
> +{
> +  return GENERAL_REGNO_P (regno) || (!gpr_only && SSE_REGNO_P (regno));
> +}
> +
> +/* TARGET_ZERO_CALL_USED_REGNO_MODE.  */
> +
> +static machine_mode
> +ix86_zero_call_used_regno_mode (const unsigned int regno, machine_mode)
> +{
> +  /* NB: We only need to zero the lower 32 bits for integer registers
> +     and the lower 128 bits for vector registers since destination are
> +     zero-extended to the full register width.  */
> +  return GENERAL_REGNO_P (regno) ? SImode : V4SFmode;
> +}
> +
> +/* TARGET_ZERO_ALL_VECTOR_REGISTERS.  */
> +
> +static rtx
> +ix86_zero_all_vector_registers (bool used_only)
> +{
> +  if (!TARGET_AVX)
> +    return NULL;
> +
> +  for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
> +    if ((IN_RANGE (regno, FIRST_SSE_REG, LAST_SSE_REG)
> +        || (TARGET_64BIT
> +            && (REX_SSE_REGNO_P (regno)
> +                || (TARGET_AVX512F && EXT_REX_SSE_REGNO_P (regno)))))
> +       && (!this_target_hard_regs->x_call_used_regs[regno]
> +           || fixed_regs[regno]
> +           || is_live_reg_at_exit (regno)
> +           || (used_only && !df_regs_ever_live_p (regno))))
> +      return NULL;
> +
> +  return gen_avx_vzeroall ();
> +}
> +
> /* Define how to find the value returned by a function.
>    VALTYPE is the data type of the value (as a tree).
>    If the precise function being called is known, FUNC is its FUNCTION_DECL;
> @@ -8513,7 +8555,7 @@ ix86_expand_prologue (void)
>       insn = emit_insn (gen_set_got (pic));
>       RTX_FRAME_RELATED_P (insn) = 1;
>       add_reg_note (insn, REG_CFA_FLUSH_QUEUE, NULL_RTX);
> -      emit_insn (gen_prologue_use (pic));
> +      emit_insn (gen_pro_epilogue_use (pic));
>       /* Deleting already emmitted SET_GOT if exist and allocated to
>          REAL_PIC_OFFSET_TABLE_REGNUM.  */
>       ix86_elim_entry_set_got (pic);
> @@ -8542,7 +8584,7 @@ ix86_expand_prologue (void)
>      Further, prevent alloca modifications to the stack pointer from being
>      combined with prologue modifications.  */
>   if (TARGET_SEH)
> -    emit_insn (gen_prologue_use (stack_pointer_rtx));
> +    emit_insn (gen_pro_epilogue_use (stack_pointer_rtx));
> }
>
> /* Emit code to restore REG using a POP insn.  */
> @@ -23319,6 +23361,18 @@ ix86_run_selftests (void)
> #undef TARGET_FUNCTION_VALUE_REGNO_P
> #define TARGET_FUNCTION_VALUE_REGNO_P ix86_function_value_regno_p
>
> +#undef TARGET_ZERO_CALL_USED_REGNO_P
> +#define TARGET_ZERO_CALL_USED_REGNO_P ix86_zero_call_used_regno_p
> +
> +#undef TARGET_ZERO_CALL_USED_REGNO_MODE
> +#define TARGET_ZERO_CALL_USED_REGNO_MODE ix86_zero_call_used_regno_mode
> +
> +#undef TARGET_PRO_EPILOGUE_USE
> +#define TARGET_PRO_EPILOGUE_USE gen_pro_epilogue_use
> +
> +#undef TARGET_ZERO_ALL_VECTOR_REGISTERS
> +#define TARGET_ZERO_ALL_VECTOR_REGISTERS ix86_zero_all_vector_registers
> +
> #undef TARGET_PROMOTE_FUNCTION_MODE
> #define TARGET_PROMOTE_FUNCTION_MODE ix86_promote_function_mode
>
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index d0ecd9e..e7df59f 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -194,7 +194,7 @@
>   UNSPECV_STACK_PROBE
>   UNSPECV_PROBE_STACK_RANGE
>   UNSPECV_ALIGN
> -  UNSPECV_PROLOGUE_USE
> +  UNSPECV_PRO_EPILOGUE_USE
>   UNSPECV_SPLIT_STACK_RETURN
>   UNSPECV_CLD
>   UNSPECV_NOPS
> @@ -13525,8 +13525,8 @@
>
> ;; As USE insns aren't meaningful after reload, this is used instead
> ;; to prevent deleting instructions setting registers for PIC code
> -(define_insn "prologue_use"
> -  [(unspec_volatile [(match_operand 0)] UNSPECV_PROLOGUE_USE)]
> +(define_insn "pro_epilogue_use"
> +  [(unspec_volatile [(match_operand 0)] UNSPECV_PRO_EPILOGUE_USE)]
>   ""
>   ""
>   [(set_attr "length" "0")])
> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
> index 6b6cfcd..e56d6ec 100644
> --- a/gcc/coretypes.h
> +++ b/gcc/coretypes.h
> @@ -418,6 +418,16 @@ enum symbol_visibility
>   VISIBILITY_INTERNAL
> };
>
> +/* Zero call-used registers type.  */
> +enum zero_call_used_regs {
> +  zero_call_used_regs_unset = 0,
> +  zero_call_used_regs_skip,
> +  zero_call_used_regs_used_gpr,
> +  zero_call_used_regs_all_gpr,
> +  zero_call_used_regs_used,
> +  zero_call_used_regs_all
> +};
> +
> /* enums used by the targetm.excess_precision hook.  */
>
> enum flt_eval_method
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index c800b74..b32c55f 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -3984,6 +3984,17 @@ performing a link with relocatable output (i.e.@: @code{ld -r}) on them.
> A declaration to which @code{weakref} is attached and that is associated
> with a named @code{target} must be @code{static}.
>
> +@item zero_call_used_regs ("@var{choice}")
> +@cindex @code{zero_call_used_regs} function attribute
> +The @code{zero_call_used_regs} attribute causes the compiler to zero
> +call-used registers at function return according to @var{choice}.
> +@samp{skip} doesn't zero call-used registers. @samp{used-gpr} zeros
> +call-used general purpose registers which are used in funciton.
> +@samp{all-gpr} zeros all call-used general purpose registers.
> +@samp{used} zeros call-used registers which are used in function.
> +@samp{all} zeros all call-used registers.  The default for the
> +attribute is controlled by @option{-fzero-call-used-regs}.
> +
> @end table
>
> @c This is the end of the target-independent attribute table
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 09bcc5b..da02686 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -542,7 +542,7 @@ Objective-C and Objective-C++ Dialects}.
> -funit-at-a-time  -funroll-all-loops  -funroll-loops @gol
> -funsafe-math-optimizations  -funswitch-loops @gol
> -fipa-ra  -fvariable-expansion-in-unroller  -fvect-cost-model  -fvpt @gol
> --fweb  -fwhole-program  -fwpa  -fuse-linker-plugin @gol
> +-fweb  -fwhole-program  -fwpa  -fuse-linker-plugin -fzero-call-used-regs @gol
> --param @var{name}=@var{value}
> -O  -O0  -O1  -O2  -O3  -Os  -Ofast  -Og}
>
> @@ -12273,6 +12273,17 @@ int foo (void)
>
> Not all targets support this option.
>
> +@item -fzero-call-used-regs=@var{choice}
> +@opindex fzero-call-used-regs
> +Zero call-used registers at function return according to
> +@var{choice}.  @samp{skip}, which is the default, doesn't zero
> +call-used registers.  @samp{used-gpr} zeros call-used general purpose
> +registers which are used in function.  @samp{all-gpr} zeros all
> +call-used registers.  @samp{used} zeros call-used registers which
> +are used in function.  @samp{all} zeros all call-used registers.  You
> +can control this behavior for a specific function by using the function
> +attribute @code{zero_call_used_regs}.  @xref{Function Attributes}.
> +
> @item --param @var{name}=@var{value}
> @opindex param
> In some places, GCC uses various constants to control the amount of
> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> index 6e7d9dc..43dddd3 100644
> --- a/gcc/doc/tm.texi
> +++ b/gcc/doc/tm.texi
> @@ -4571,6 +4571,22 @@ should recognize only the caller's register numbers.
> If this hook is not defined, then FUNCTION_VALUE_REGNO_P will be used.
> @end deftypefn
>
> +@deftypefn {Target Hook} bool TARGET_ZERO_CALL_USED_REGNO_P (const unsigned int @var{regno}, bool @var{general_reg_only_p})
> +A target hook that returns @code{true} if @var{regno} is the number of a
> +call used register.  If @var{general_reg_only_p} is @code{true},
> +@var{regno} must be the number of a hard general register.
> +
> +If this hook is not defined, then default_zero_call_used_regno_p will be used.
> +@end deftypefn
> +
> +@deftypefn {Target Hook} machine_mode TARGET_ZERO_CALL_USED_REGNO_MODE (const unsigned int @var{regno}, machine_mode @var{mode})
> +A target hook that returns a mode of suitable to zero the register for the
> +call used register @var{regno} in @var{mode}.
> +
> +If this hook is not defined, then default_zero_call_used_regno_mode will be
> +used.
> +@end deftypefn
> +
> @defmac APPLY_RESULT_SIZE
> Define this macro if @samp{untyped_call} and @samp{untyped_return}
> need more space than is implied by @code{FUNCTION_VALUE_REGNO_P} for
> @@ -12043,6 +12059,17 @@ argument list due to stack realignment.  Return @code{NULL} if no DRAP
> is needed.
> @end deftypefn
>
> +@deftypefn {Target Hook} rtx TARGET_PRO_EPILOGUE_USE (rtx @var{reg})
> +This hook should return a UNSPEC_VOLATILE rtx to mark a register in use to
> +prevent deleting register setting instructions in proprologue and epilogue.
> +@end deftypefn
> +
> +@deftypefn {Target Hook} rtx TARGET_ZERO_ALL_VECTOR_REGISTERS (bool @var{used_only})
> +This hook should return an rtx to zero all vector registers at function
> +exit.  If @var{used_only} is @code{true}, only used vector registers should
> +be zeroed.  Return @code{NULL} if possible
> +@end deftypefn
> +
> @deftypefn {Target Hook} bool TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS (void)
> When optimization is disabled, this hook indicates whether or not
> arguments should be allocated to stack slots.  Normally, GCC allocates
> diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
> index 3be984b..bee917a 100644
> --- a/gcc/doc/tm.texi.in
> +++ b/gcc/doc/tm.texi.in
> @@ -3430,6 +3430,10 @@ for a new target instead.
>
> @hook TARGET_FUNCTION_VALUE_REGNO_P
>
> +@hook TARGET_ZERO_CALL_USED_REGNO_P
> +
> +@hook TARGET_ZERO_CALL_USED_REGNO_MODE
> +
> @defmac APPLY_RESULT_SIZE
> Define this macro if @samp{untyped_call} and @samp{untyped_return}
> need more space than is implied by @code{FUNCTION_VALUE_REGNO_P} for
> @@ -8109,6 +8113,10 @@ and the associated definitions of those functions.
>
> @hook TARGET_GET_DRAP_RTX
>
> +@hook TARGET_PRO_EPILOGUE_USE
> +
> +@hook TARGET_ZERO_ALL_VECTOR_REGISTERS
> +
> @hook TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
>
> @hook TARGET_CONST_ANCHOR
> diff --git a/gcc/function.c b/gcc/function.c
> index 9eee9b5..9908530 100644
> --- a/gcc/function.c
> +++ b/gcc/function.c
> @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
> #include "emit-rtl.h"
> #include "recog.h"
> #include "rtl-error.h"
> +#include "hard-reg-set.h"
> #include "alias.h"
> #include "fold-const.h"
> #include "stor-layout.h"
> @@ -5808,6 +5809,147 @@ make_prologue_seq (void)
>   return seq;
> }
>
> +/* Check whether the hard register REGNO is live at the exit block
> + * of the current routine.  */
> +bool
> +is_live_reg_at_exit (unsigned int regno)
> +{
> +  edge e;
> +  edge_iterator ei;
> +
> +  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
> +    {
> +      bitmap live_out = df_get_live_out (e->src);
> +      if (REGNO_REG_SET_P (live_out, regno))
> +       return true;
> +    }
> +
> +  return false;
> +}
> +
> +/* Emit a sequence of insns to zero the call-used-registers for the current
> + * function.  */
> +
> +static void
> +gen_call_used_regs_seq (void)
> +{
> +  if (!targetm.calls.pro_epilogue_use)
> +    return;
> +
> +  bool gpr_only = true;
> +  bool used_only = true;
> +  enum zero_call_used_regs zero_call_used_regs_type = zero_call_used_regs_unset;
> +
> +  if (flag_zero_call_used_regs)
> +    if (DECL_ZERO_CALL_USED_REGS (current_function_decl)
> +       == zero_call_used_regs_unset)
> +      zero_call_used_regs_type = flag_zero_call_used_regs;
> +    else
> +      zero_call_used_regs_type
> +       = DECL_ZERO_CALL_USED_REGS (current_function_decl);
> +  else
> +    zero_call_used_regs_type = DECL_ZERO_CALL_USED_REGS (current_function_decl);
> +
> +  /* No need to zero call-used-regs when no user request is present.  */
> +  if (zero_call_used_regs_type <= zero_call_used_regs_skip)
> +    return;
> +
> +  /* No need to zero call-used-regs in main ().  */
> +  if (MAIN_NAME_P (DECL_NAME (current_function_decl)))
> +    return;
> +
> +  /* No need to zero call-used-regs if __builtin_eh_return is called
> +     since it isn't a normal function return.  */
> +  if (crtl->calls_eh_return)
> +    return;
> +
> +  /* If gpr_only is true, only zero call-used-registers that are
> +     general-purpose registers; if used_only is true, only zero
> +     call-used-registers that are used in the current function.  */
> +  switch (zero_call_used_regs_type)
> +    {
> +      case zero_call_used_regs_all_gpr:
> +       used_only = false;
> +       break;
> +      case zero_call_used_regs_used:
> +       gpr_only = false;
> +       break;
> +      case zero_call_used_regs_all:
> +       gpr_only = false;
> +       used_only = false;
> +       break;
> +      default:
> +       break;
> +    }
> +
> +  /* An optimization to use a single hard insn to zero all vector registers on
> +     the target that provides such insn.  */
> +  if (!gpr_only
> +      && targetm.calls.zero_all_vector_registers)
> +    {
> +      rtx zero_all_vec_insn
> +       = targetm.calls.zero_all_vector_registers (used_only);
> +      if (zero_all_vec_insn)
> +       {
> +         emit_insn (zero_all_vec_insn);
> +         gpr_only = true;
> +       }
> +    }
> +
> +  /* For each of the hard registers, check to see whether we should zero it if:
> +     1. it is a call-used-registers;
> + and 2. it is not a fixed-registers;
> + and 3. it is not live at the end of the routine;
> + and 4. it is general purpose register if gpr_only is true;
> + and 5. it is used in the routine if used_only is true;
> +   */
> +
> +  /* This array holds the zero rtx with the correponding machine mode.  */
> +  rtx zero_rtx[(int)MAX_MACHINE_MODE];
> +  for (int i = 0; i < (int) MAX_MACHINE_MODE; i++)
> +    zero_rtx[i] = NULL_RTX;
> +
> +  for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
> +    {
> +      if (!this_target_hard_regs->x_call_used_regs[regno])
> +       continue;
> +      if (fixed_regs[regno])
> +       continue;
> +      if (is_live_reg_at_exit (regno))
> +       continue;
> +      if (!targetm.calls.zero_call_used_regno_p (regno, gpr_only))
> +       continue;
> +      if (used_only && !df_regs_ever_live_p (regno))
> +       continue;
> +
> +      /* Now we can emit insn to zero this register.  */
> +      rtx reg, tmp;
> +
> +      machine_mode mode
> +       = targetm.calls.zero_call_used_regno_mode (regno,
> +                                                  reg_raw_mode[regno]);
> +      if (mode == VOIDmode)
> +       continue;
> +      if (!have_regs_of_mode[mode])
> +       continue;
> +
> +      reg = gen_rtx_REG (mode, regno);
> +      if (zero_rtx[(int)mode] == NULL_RTX)
> +       {
> +         zero_rtx[(int)mode] = reg;
> +         tmp = gen_rtx_SET (reg, const0_rtx);
> +         emit_insn (tmp);
> +       }
> +      else
> +       emit_move_insn (reg, zero_rtx[(int)mode]);
> +
> +      emit_insn (targetm.calls.pro_epilogue_use (reg));
> +    }
> +
> +  return;
> +}
> +
> +
> /* Return a sequence to be used as the epilogue for the current function,
>    or NULL.  */
>
> @@ -5819,6 +5961,9 @@ make_epilogue_seq (void)
>
>   start_sequence ();
>   emit_note (NOTE_INSN_EPILOGUE_BEG);
> +
> +  gen_call_used_regs_seq ();
> +
>   rtx_insn *seq = targetm.gen_epilogue ();
>   if (seq)
>     emit_jump_insn (seq);
> diff --git a/gcc/function.h b/gcc/function.h
> index d55cbdd..fc36c3e 100644
> --- a/gcc/function.h
> +++ b/gcc/function.h
> @@ -705,4 +705,6 @@ extern const char *current_function_name (void);
>
> extern void used_types_insert (tree);
>
> +extern bool is_live_reg_at_exit (unsigned int);
> +
> #endif  /* GCC_FUNCTION_H */
> diff --git a/gcc/target.def b/gcc/target.def
> index 07059a8..8aab63e 100644
> --- a/gcc/target.def
> +++ b/gcc/target.def
> @@ -5022,6 +5022,26 @@ If this hook is not defined, then FUNCTION_VALUE_REGNO_P will be used.",
>  default_function_value_regno_p)
>
> DEFHOOK
> +(zero_call_used_regno_p,
> + "A target hook that returns @code{true} if @var{regno} is the number of a\n\
> +call used register.  If @var{general_reg_only_p} is @code{true},\n\
> +@var{regno} must be the number of a hard general register.\n\
> +\n\
> +If this hook is not defined, then default_zero_call_used_regno_p will be used.",
> + bool, (const unsigned int regno, bool general_reg_only_p),
> + default_zero_call_used_regno_p)
> +
> +DEFHOOK
> +(zero_call_used_regno_mode,
> + "A target hook that returns a mode of suitable to zero the register for the\n\
> +call used register @var{regno} in @var{mode}.\n\
> +\n\
> +If this hook is not defined, then default_zero_call_used_regno_mode will be\n\
> +used.",
> + machine_mode, (const unsigned int regno, machine_mode mode),
> + default_zero_call_used_regno_mode)
> +
> +DEFHOOK
> (fntype_abi,
>  "Return the ABI used by a function with type @var{type}; see the\n\
> definition of @code{predefined_function_abi} for details of the ABI\n\
> @@ -5068,6 +5088,19 @@ argument list due to stack realignment.  Return @code{NULL} if no DRAP\n\
> is needed.",
>  rtx, (void), NULL)
>
> +DEFHOOK
> +(pro_epilogue_use,
> + "This hook should return a UNSPEC_VOLATILE rtx to mark a register in use to\n\
> +prevent deleting register setting instructions in proprologue and epilogue.",
> + rtx, (rtx reg), NULL)
> +
> +DEFHOOK
> +(zero_all_vector_registers,
> + "This hook should return an rtx to zero all vector registers at function\n\
> +exit.  If @var{used_only} is @code{true}, only used vector registers should\n\
> +be zeroed.  Return @code{NULL} if possible",
> + rtx, (bool used_only), NULL)
> +
> /* Return true if all function parameters should be spilled to the
>    stack.  */
> DEFHOOK
> diff --git a/gcc/targhooks.c b/gcc/targhooks.c
> index 0113c7b..ed02173 100644
> --- a/gcc/targhooks.c
> +++ b/gcc/targhooks.c
> @@ -987,6 +987,23 @@ default_function_value_regno_p (const unsigned int regno ATTRIBUTE_UNUSED)
> #endif
> }
>
> +/* The default hook for TARGET_ZERO_CALL_USED_REGNO_P.  */
> +
> +bool
> +default_zero_call_used_regno_p (const unsigned int,
> +                               bool)
> +{
> +  return false;
> +}
> +
> +/* The default hook for TARGET_ZERO_CALL_USED_REGNO_MODE.  */
> +
> +machine_mode
> +default_zero_call_used_regno_mode (const unsigned int, machine_mode mode)
> +{
> +  return mode;
> +}
> +
> rtx
> default_internal_arg_pointer (void)
> {
> diff --git a/gcc/targhooks.h b/gcc/targhooks.h
> index b572a36..370df19 100644
> --- a/gcc/targhooks.h
> +++ b/gcc/targhooks.h
> @@ -162,6 +162,9 @@ extern bool hook_bool_const_rtx_commutative_p (const_rtx, int);
> extern rtx default_function_value (const_tree, const_tree, bool);
> extern rtx default_libcall_value (machine_mode, const_rtx);
> extern bool default_function_value_regno_p (const unsigned int);
> +extern bool default_zero_call_used_regno_p (const unsigned int, bool);
> +extern machine_mode default_zero_call_used_regno_mode (const unsigned int,
> +                                                      machine_mode);
> extern rtx default_internal_arg_pointer (void);
> extern rtx default_static_chain (const_tree, bool);
> extern void default_trampoline_init (rtx, tree, rtx);
> diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-1.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-1.c
> new file mode 100644
> index 0000000..3c2ac72
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-1.c
> @@ -0,0 +1,3 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fzero-call-used-regs=used" } */
> +/* { dg-error "'-fzero-call-used-regs=' is not supported for this target" "" { target { ! "i?86-*-* x86_64-*-*" } } 0 } */
> diff --git a/gcc/testsuite/c-c++-common/zero-scratch-regs-2.c b/gcc/testsuite/c-c++-common/zero-scratch-regs-2.c
> new file mode 100644
> index 0000000..acf48c4
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/zero-scratch-regs-2.c
> @@ -0,0 +1,4 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2" } */
> +
> +extern int foo (int) __attribute__ ((zero_call_used_regs("all-gpr"))); /* { dg-warning " attribute directive ignored" "" {target { ! "i?86-*-* x86_64-*-*" } } 0 } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-1.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-1.c
> new file mode 100644
> index 0000000..9f61dc4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-1.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=used" } */
> +
> +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-10.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-10.c
> new file mode 100644
> index 0000000..09048e5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-10.c
> @@ -0,0 +1,21 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
> +
> +extern int foo (int) __attribute__ ((zero_call_used_regs("all-gpr")));
> +
> +int
> +foo (int x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%edx, %edx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %ecx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %esi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %edi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %r8d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %r9d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %r10d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %r11d" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-11.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-11.c
> new file mode 100644
> index 0000000..4862688
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-11.c
> @@ -0,0 +1,39 @@
> +/* { dg-do run { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=used-gpr" } */
> +
> +struct S { int i; };
> +__attribute__((const, noinline, noclone))
> +struct S foo (int x)
> +{
> +  struct S s;
> +  s.i = x;
> +  return s;
> +}
> +
> +int a[2048], b[2048], c[2048], d[2048];
> +struct S e[2048];
> +
> +__attribute__((noinline, noclone)) void
> +bar (void)
> +{
> +  int i;
> +  for (i = 0; i < 1024; i++)
> +    {
> +      e[i] = foo (i);
> +      a[i+2] = a[i] + a[i+1];
> +      b[10] = b[10] + i;
> +      c[i] = c[2047 - i];
> +      d[i] = d[i + 1];
> +    }
> +}
> +
> +int
> +main ()
> +{
> +  int i;
> +  bar ();
> +  for (i = 0; i < 1024; i++)
> +    if (e[i].i != i)
> +      __builtin_abort ();
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-12.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-12.c
> new file mode 100644
> index 0000000..500251b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-12.c
> @@ -0,0 +1,39 @@
> +/* { dg-do run { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all-gpr" } */
> +
> +struct S { int i; };
> +__attribute__((const, noinline, noclone))
> +struct S foo (int x)
> +{
> +  struct S s;
> +  s.i = x;
> +  return s;
> +}
> +
> +int a[2048], b[2048], c[2048], d[2048];
> +struct S e[2048];
> +
> +__attribute__((noinline, noclone)) void
> +bar (void)
> +{
> +  int i;
> +  for (i = 0; i < 1024; i++)
> +    {
> +      e[i] = foo (i);
> +      a[i+2] = a[i] + a[i+1];
> +      b[10] = b[10] + i;
> +      c[i] = c[2047 - i];
> +      d[i] = d[i + 1];
> +    }
> +}
> +
> +int
> +main ()
> +{
> +  int i;
> +  bar ();
> +  for (i = 0; i < 1024; i++)
> +    if (e[i].i != i)
> +      __builtin_abort ();
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-13.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-13.c
> new file mode 100644
> index 0000000..8b058e3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-13.c
> @@ -0,0 +1,21 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7" } */
> +
> +void
> +foo (void)
> +{
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler "pxor\[ \t\]*%xmm0, %xmm0" } } */
> +/* { dg-final { scan-assembler-times "movaps\[ \t\]*%xmm0, %xmm\[0-9\]+" 7 { target { ia32 } } } } */
> +/* { dg-final { scan-assembler-times "movaps\[ \t\]*%xmm0, %xmm\[0-9\]+" 15 { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%eax, %eax" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %ecx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %esi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r8d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r9d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r10d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r11d" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-14.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-14.c
> new file mode 100644
> index 0000000..d4eaaf7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-14.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7 -mavx" } */
> +
> +void
> +foo (void)
> +{
> +}
> +
> +/* { dg-final { scan-assembler-times "vzeroall" 1 } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%eax, %eax" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %ecx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %esi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r8d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r9d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r10d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r11d" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-15.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-15.c
> new file mode 100644
> index 0000000..dd3bb90
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-15.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
> +
> +extern void foo (void) __attribute__ ((zero_call_used_regs("used")));
> +
> +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-16.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-16.c
> new file mode 100644
> index 0000000..e2274f6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-16.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all" } */
> +
> +extern void foo (void) __attribute__ ((zero_call_used_regs("skip")));
> +
> +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-17.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-17.c
> new file mode 100644
> index 0000000..7f5d153
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-17.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=used" } */
> +
> +int
> +foo (int x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler-not "xorl\[ \t\]*%" { target ia32 } } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%edi, %edi" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-18.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-18.c
> new file mode 100644
> index 0000000..fe13d2b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-18.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=used -march=corei7" } */
> +
> +float
> +foo (float z, float y, float x)
> +{
> +  return x + y;
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler "pxor\[ \t\]*%xmm1, %xmm1" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movaps\[ \t\]*%xmm1, %xmm2" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "xorl\[ \t\]*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-19.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-19.c
> new file mode 100644
> index 0000000..205a532
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-19.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=used -march=corei7" } */
> +
> +float
> +foo (float z, float y, float x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler "pxor\[ \t\]*%xmm2, %xmm2" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "xorl\[ \t\]*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-2.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-2.c
> new file mode 100644
> index 0000000..e046684
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-2.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all-gpr" } */
> +
> +void
> +foo (void)
> +{
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%eax, %eax" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %ecx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %esi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r8d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r9d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r10d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r11d" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-20.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-20.c
> new file mode 100644
> index 0000000..4be8ff6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-20.c
> @@ -0,0 +1,23 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7" } */
> +
> +float
> +foo (float z, float y, float x)
> +{
> +  return x + y;
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler "pxor\[ \t\]*%xmm0, %xmm0" { target { ia32 } } } } */
> +/* { dg-final { scan-assembler "pxor\[ \t\]*%xmm1, %xmm1" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-times "movaps\[ \t\]*%xmm0, %xmm\[0-9\]+" 7 { target { ia32 } } } } */
> +/* { dg-final { scan-assembler-times "movaps\[ \t\]*%xmm1, %xmm\[0-9\]+" 14 { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%eax, %eax" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %ecx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %esi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r8d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r9d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r10d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r11d" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-21.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-21.c
> new file mode 100644
> index 0000000..0eb34e0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-21.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=skip -march=corei7" } */
> +
> +__attribute__ ((zero_call_used_regs("used")))
> +float
> +foo (float z, float y, float x)
> +{
> +  return x + y;
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler "pxor\[ \t\]*%xmm1, %xmm1" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movaps\[ \t\]*%xmm1, %xmm2" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler-not "xorl\[ \t\]*%" } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-22.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-22.c
> new file mode 100644
> index 0000000..cbb63a4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-22.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7 -mavx" } */
> +
> +void
> +foo (void)
> +{
> +}
> +
> +/* { dg-final { scan-assembler "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%eax, %eax" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %ecx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %esi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r8d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r9d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r10d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r11d" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-23.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-23.c
> new file mode 100644
> index 0000000..7573197
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-23.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all -march=corei7 -mavx512f" } */
> +
> +void
> +foo (void)
> +{
> +}
> +
> +/* { dg-final { scan-assembler "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%eax, %eax" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %ecx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %esi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r8d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r9d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r10d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r11d" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-3.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-3.c
> new file mode 100644
> index 0000000..de71223
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-3.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
> +
> +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-4.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-4.c
> new file mode 100644
> index 0000000..ccfa441
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-4.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
> +
> +extern void foo (void) __attribute__ ((zero_call_used_regs("used-gpr")));
> +
> +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-5.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-5.c
> new file mode 100644
> index 0000000..6b46ca3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-5.c
> @@ -0,0 +1,20 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
> +
> +__attribute__ ((zero_call_used_regs("all-gpr")))
> +void
> +foo (void)
> +{
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%eax, %eax" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %ecx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %esi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %edi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r8d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r9d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r10d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%eax, %r11d" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-6.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-6.c
> new file mode 100644
> index 0000000..0680f38
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-6.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all-gpr" } */
> +
> +extern void foo (void) __attribute__ ((zero_call_used_regs("skip")));
> +
> +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-7.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-7.c
> new file mode 100644
> index 0000000..534defa
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-7.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=used-gpr" } */
> +
> +int
> +foo (int x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler-not "xorl\[ \t\]*%" { target ia32 } } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%edi, %edi" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-8.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-8.c
> new file mode 100644
> index 0000000..477bb19
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-8.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=all-gpr" } */
> +
> +int
> +foo (int x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%edx, %edx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %ecx" } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %esi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %edi" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %r8d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %r9d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %r10d" { target { ! ia32 } } } } */
> +/* { dg-final { scan-assembler "movl\[ \t\]*%edx, %r11d" { target { ! ia32 } } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/zero-scratch-regs-9.c b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-9.c
> new file mode 100644
> index 0000000..a305a60
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/zero-scratch-regs-9.c
> @@ -0,0 +1,15 @@
> +/* { dg-do compile { target *-*-linux* } } */
> +/* { dg-options "-O2 -fzero-call-used-regs=skip" } */
> +
> +extern int foo (int) __attribute__ ((zero_call_used_regs("used-gpr")));
> +
> +int
> +foo (int x)
> +{
> +  return x;
> +}
> +
> +/* { dg-final { scan-assembler-not "vzeroall" } } */
> +/* { dg-final { scan-assembler-not "%xmm" } } */
> +/* { dg-final { scan-assembler-not "xorl\[ \t\]*%" { target ia32 } } } */
> +/* { dg-final { scan-assembler "xorl\[ \t\]*%edi, %edi" { target { ! ia32 } } } } */
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index 95eea63..01a1f24 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -1464,6 +1464,15 @@ process_options (void)
>         }
>     }
>
> +  if (flag_zero_call_used_regs != zero_call_used_regs_skip
> +      && !targetm.calls.pro_epilogue_use)
> +    {
> +      error_at (UNKNOWN_LOCATION,
> +               "%<-fzero-call-used-regs=%> is not supported for this "
> +               "target");
> +      flag_zero_call_used_regs = zero_call_used_regs_skip;
> +    }
> +
>   /* One region RA really helps to decrease the code size.  */
>   if (flag_ira_region == IRA_REGION_AUTODETECT)
>     flag_ira_region
> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> index 8c5a2e3..71badbd 100644
> --- a/gcc/tree-core.h
> +++ b/gcc/tree-core.h
> @@ -1825,7 +1825,11 @@ struct GTY(()) tree_decl_with_vis {
>  unsigned final : 1;
>  /* Belong to FUNCTION_DECL exclusively.  */
>  unsigned regdecl_flag : 1;
> - /* 14 unused bits. */
> +
> + /* How to clear call-used registers upon function return.  */
> + ENUM_BITFIELD(zero_call_used_regs) zero_call_used_regs_type : 3;
> +
> + /* 11 unused bits.  */
> };
>
> struct GTY(()) tree_var_decl {
> diff --git a/gcc/tree.h b/gcc/tree.h
> index cf546ed..d378a88 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -2925,6 +2925,11 @@ extern void decl_value_expr_insert (tree, tree);
> #define DECL_VISIBILITY(NODE) \
>   (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.visibility)
>
> +/* Value of the function decl's type of zeroing the call used
> +   registers upon return from function.  */
> +#define DECL_ZERO_CALL_USED_REGS(NODE) \
> +  (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.zero_call_used_regs_type)
> +
> /* Nonzero means that the decl (or an enclosing scope) had its
>    visibility specified rather than being inferred.  */
> #define DECL_VISIBILITY_SPECIFIED(NODE) \
> --
> 1.9.1

+1. Tested on x86

  reply	other threads:[~2020-07-16 13:17 UTC|newest]

Thread overview: 188+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-04 19:01 [PATCH 1/4] matcher-1.m: Change return type to int H.J. Lu
2020-05-04 19:01 ` [PATCH 2/4] x86: Add -mzero-caller-saved-regs=[skip|used-gpr|all-gpr|used|all] H.J. Lu
2020-05-04 23:19   ` Rodriguez Bahena, Victor
2020-05-05  8:14   ` Uros Bizjak
2020-05-05  8:20     ` Richard Biener
2020-07-14 14:45       ` [Patch][Middle-end]Add -fzero-call-used-regs=[skip|used-gpr|all-gpr|used|all] Qing Zhao
2020-07-16 13:17         ` Victor Rodriguez [this message]
2020-07-28 20:05         ` PING " Qing Zhao
2020-07-31 17:57           ` Uros Bizjak
2020-08-03 15:42             ` Qing Zhao
2020-08-04  7:35               ` Richard Biener
2020-08-04 18:23                 ` H.J. Lu
2020-08-05  7:06                   ` Richard Biener
2020-08-05 12:26                     ` H.J. Lu
2020-08-05 12:30                       ` Richard Biener
2020-08-05 12:34                         ` H.J. Lu
2020-08-05 14:45                           ` H.J. Lu
2020-08-05 15:00                             ` Qing Zhao
2020-08-05 18:53                             ` Richard Biener
2020-08-05 19:08                               ` H.J. Lu
2020-08-05 20:22                               ` Qing Zhao
2020-08-06  8:37                                 ` Richard Biener
2020-08-06 15:45                                   ` Qing Zhao
2020-08-06 20:45                                   ` Kees Cook
2020-08-07  6:21                                     ` Richard Biener
2020-08-07 16:15                                       ` Qing Zhao
2020-08-05 21:35                 ` Qing Zhao
2020-08-06  8:31                   ` Richard Biener
2020-08-06  8:41                     ` Jakub Jelinek
2020-08-06  9:31                       ` Uros Bizjak
2020-08-06 14:56                     ` Qing Zhao
2020-08-06 23:37                     ` Segher Boessenkool
2020-08-07 16:06                       ` Qing Zhao
2020-08-07 22:59                         ` Segher Boessenkool
2020-08-10 16:34                           ` Qing Zhao
2020-08-10 19:51                             ` Qing Zhao
2020-08-19 20:05                       ` Qing Zhao
2020-08-19 22:57                         ` Segher Boessenkool
2020-08-19 23:27                           ` Qing Zhao
2020-08-24 14:47                             ` Rodriguez Bahena, Victor
2020-08-24 17:59                               ` Segher Boessenkool
2020-08-24 18:48                                 ` Qing Zhao
2020-08-24 20:26                                   ` Segher Boessenkool
2020-08-24 20:49                                     ` Qing Zhao
2020-09-04 15:18                                       ` Segher Boessenkool
2020-09-04 17:34                                         ` H.J. Lu
2020-09-04 18:09                                           ` Segher Boessenkool
2020-09-04 18:52                                             ` H.J. Lu
2020-09-07 14:06                                               ` Segher Boessenkool
2020-09-07 15:58                                                 ` H.J. Lu
2020-09-08 16:43                                                   ` Qing Zhao
2020-09-10 22:05                                                     ` Segher Boessenkool
2020-09-10 22:50                                                       ` Qing Zhao
2020-09-11 17:18                                                         ` Segher Boessenkool
2020-09-11 19:53                                                           ` Qing Zhao
2020-08-24 17:49                             ` Segher Boessenkool
2020-08-24 18:02                               ` Qing Zhao
2020-08-24 20:20                                 ` Segher Boessenkool
2020-08-24 20:43                                   ` Qing Zhao
2020-08-25  6:41                                     ` Uros Bizjak
2020-08-25 14:05                                       ` Qing Zhao
2020-08-25 22:31                                         ` Qing Zhao
2020-09-04 15:26                                     ` Segher Boessenkool
2020-08-25 21:54                                   ` Qing Zhao
2020-09-03 14:29                                     ` Qing Zhao
2020-09-03 15:08                                       ` Qing Zhao
2020-09-03 16:19                                         ` Qing Zhao
2020-09-03 17:13                                       ` Kees Cook
2020-09-03 17:43                                         ` Qing Zhao
2020-09-04  1:23                                           ` Rodriguez Bahena, Victor
2020-09-04 14:18                                             ` Qing Zhao
2020-09-07 13:06                                               ` Rodriguez Bahena, Victor
2020-09-08 15:00                                                 ` Qing Zhao
2020-09-10 19:07                                                   ` Kees Cook
2020-09-10 22:40                                                     ` Qing Zhao
2020-09-11 10:06                                                     ` Richard Sandiford
2020-09-11 16:14                                                       ` Segher Boessenkool
2020-09-11 16:52                                                         ` Qing Zhao
2020-09-11 17:13                                                           ` Segher Boessenkool
2020-09-11 19:40                                                             ` Qing Zhao
2020-09-11 20:05                                                               ` Segher Boessenkool
2020-09-11 20:17                                                                 ` Qing Zhao
2020-09-11 20:36                                                                   ` Segher Boessenkool
2020-09-11 21:12                                                                     ` Qing Zhao
2020-09-11 17:32                                                           ` Richard Sandiford
2020-09-11 20:01                                                             ` Segher Boessenkool
2020-09-11 20:14                                                             ` Qing Zhao
2020-09-11 21:03                                                               ` Segher Boessenkool
2020-09-11 21:29                                                                 ` Qing Zhao
2020-09-11 21:51                                                                   ` Segher Boessenkool
2020-09-11 22:41                                                                     ` Qing Zhao
2020-09-14 23:09                                                                       ` Segher Boessenkool
2020-09-15  3:07                                                                         ` Qing Zhao
2020-09-15 18:51                                                                           ` Segher Boessenkool
2020-09-11 21:44                                                               ` Richard Sandiford
2020-09-11 22:24                                                                 ` Qing Zhao
2020-09-11 22:56                                                                   ` Richard Sandiford
2020-09-14 14:56                                                                     ` Qing Zhao
2020-09-14 16:33                                                                       ` Richard Sandiford
2020-09-14 18:50                                                                         ` Qing Zhao
2020-09-14 19:20                                                                           ` Richard Sandiford
2020-09-14 20:24                                                                             ` Qing Zhao
2020-09-15  9:11                                                                               ` Richard Sandiford
2020-09-15 15:05                                                                                 ` Qing Zhao
2020-09-15 19:41                                                                                 ` Segher Boessenkool
2020-09-15 22:31                                                                                   ` Qing Zhao
2020-09-15 23:09                                                                                     ` Segher Boessenkool
2020-09-16  1:51                                                                                       ` Qing Zhao
2020-09-16 10:35                                                                                         ` Segher Boessenkool
2020-09-16 20:57                                                                                           ` Qing Zhao
2020-09-17  6:17                                                                                             ` Richard Sandiford
2020-09-17 14:40                                                                                               ` Qing Zhao
2020-09-17 16:27                                                                                                 ` Richard Sandiford
2020-09-17 19:07                                                                                                   ` Qing Zhao
2020-09-22 17:06                                                                                                     ` Richard Sandiford
2020-09-22 21:32                                                                                                       ` Qing Zhao
2020-09-23 11:05                                                                                                         ` Richard Sandiford
2020-09-23 14:14                                                                                                           ` Qing Zhao
2020-09-23 14:32                                                                                                             ` Richard Sandiford
2020-09-23 14:48                                                                                                               ` Qing Zhao
2020-09-23 15:21                                                                                                                 ` Richard Sandiford
2020-09-23 16:08                                                                                                                   ` Qing Zhao
2020-09-23 23:46                                                                                                           ` Segher Boessenkool
2020-09-22 22:37                                                                                                       ` Segher Boessenkool
2020-09-23 14:28                                                                                                         ` Qing Zhao
2020-09-23 23:40                                                                                                           ` Segher Boessenkool
2020-09-17 22:26                                                                                                   ` Segher Boessenkool
2020-09-14 23:35                                                                         ` Segher Boessenkool
2020-09-15 11:46                                                                           ` Richard Sandiford
2020-09-15 19:22                                                                             ` Segher Boessenkool
2020-09-14 23:20                                                                   ` Segher Boessenkool
2020-09-18 20:31                                                                 ` Qing Zhao
2020-09-18 22:51                                                                   ` Segher Boessenkool
2020-09-21 14:13                                                                     ` Qing Zhao
2020-09-21 20:34                                                                       ` Segher Boessenkool
2020-09-21 20:58                                                                         ` Qing Zhao
2020-09-22  0:25                                                                           ` Segher Boessenkool
2020-09-21  7:23                                                                   ` Richard Sandiford
2020-09-21 14:29                                                                     ` Qing Zhao
2020-09-21 15:35                                                                       ` Richard Sandiford
2020-09-21 16:34                                                                         ` Qing Zhao
2020-09-21 19:11                                                                           ` Richard Sandiford
2020-09-21 19:22                                                                             ` Qing Zhao
2020-09-21 20:05                                                                               ` Qing Zhao
2020-09-22 16:31                                                                                 ` Richard Sandiford
2020-09-22 18:25                                                                                   ` Qing Zhao
2020-09-22 18:35                                                                                     ` H.J. Lu
2020-09-22 19:34                                                                                       ` Qing Zhao
2020-09-23 10:43                                                                                         ` Richard Sandiford
2020-09-23 13:54                                                                                           ` Qing Zhao
2020-09-23 14:22                                                                                             ` Richard Sandiford
2020-09-23 14:35                                                                                               ` Qing Zhao
2020-09-23 14:40                                                                                                 ` Richard Sandiford
2020-09-23 14:49                                                                                                   ` Qing Zhao
2020-09-07 14:44                                             ` Segher Boessenkool
2020-09-08 15:05                                               ` Patrick McGehearty
2020-09-10 12:11                                                 ` Richard Sandiford
2020-09-10 14:34                                                   ` Qing Zhao
2020-09-10 14:59                                                     ` Rodriguez Bahena, Victor
2020-09-03 17:48                                         ` Ramana Radhakrishnan
2020-09-03 19:20                                           ` Qing Zhao
2020-09-04 15:43                                         ` Segher Boessenkool
2020-09-04 17:18                                           ` Qing Zhao
2020-09-04 18:04                                             ` Segher Boessenkool
2020-09-04 19:00                                               ` Qing Zhao
2020-09-07 14:36                                                 ` Segher Boessenkool
2020-09-08 14:55                                                   ` Qing Zhao
2020-09-10 21:56                                                     ` Segher Boessenkool
2020-08-24 14:36                           ` Rodriguez Bahena, Victor
2020-08-06 22:32                   ` Qing Zhao
2020-08-07 13:20           ` Alexandre Oliva
2020-08-07 17:04             ` Qing Zhao
2020-08-11  2:39               ` Alexandre Oliva
2020-08-11  5:57                 ` Kees Cook
2020-08-11 17:30                 ` Qing Zhao
2020-08-24 10:50                   ` Richard Biener
2020-08-24 14:48                     ` Qing Zhao
2020-08-25  5:16                     ` Alexandre Oliva
2020-08-25 14:19                       ` Jeff Law
2020-08-26 12:02                         ` Alexandre Oliva
2020-08-26 17:58                           ` Qing Zhao
2020-08-28  7:47                             ` Alexandre Oliva
2020-08-28 15:21                               ` Qing Zhao
2020-08-28 15:33                                 ` H.J. Lu
2020-08-26 18:36                           ` Jeff Law
2020-05-04 19:01 ` [PATCH 3/4] x86: Add ix86_any_return_p H.J. Lu
2020-05-04 19:01 ` [PATCH 4/4] Update gcc.target/i386/ret-thunk-2[234].c H.J. Lu
2020-05-05 16:29 ` [PATCH 1/4] matcher-1.m: Change return type to int Jeff Law

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAK5mtewsYaq6PHxj-P4uKciC5Tb44Qr30X5Co=nZm2B_FUQBbg@mail.gmail.com' \
    --to=vm.rod25@gmail.com \
    --cc=QING.ZHAO@oracle.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=hjl.tools@gmail.com \
    --cc=jakub@redhat.com \
    --cc=keescook@chromium.org \
    --cc=rguenther@suse.de \
    --cc=ubizjak@gmail.com \
    --cc=victor.rodriguez.bahena@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).