public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Biener <richard.guenther@gmail.com>
To: Alexandre Oliva <oliva@adacore.com>
Cc: Thomas Schwinge <thomas@codesourcery.com>,
	Tobias Burnus <tobias@codesourcery.com>,
	 gcc-patches@gcc.gnu.org,
	Jeremy Bennett <jeremy.bennett@embecosm.com>,
	 Craig Blackmore <craig.blackmore@embecosm.com>,
	Graham Markall <graham.markall@embecosm.com>,
	 Martin Jambor <mjambor@suse.cz>, Jan Hubicka <hubicka@ucw.cz>,
	Jim Wilson <wilson@tuliptree.org>,
	 Jeff Law <jeffreyalaw@gmail.com>,
	Jakub Jelinek <jakub@redhat.com>,
	 Tom de Vries <tdevries@suse.de>
Subject: Re: [PATCH] strub: enable conditional support
Date: Thu, 7 Dec 2023 08:24:43 +0100	[thread overview]
Message-ID: <CAFiYyc3vw5EQGgXUq3hUyG-MocrSVjGrdCh+pp6UQ-x5ER5A3g@mail.gmail.com> (raw)
In-Reply-To: <orjzpqd6u0.fsf_-_@lxoliva.fsfla.org>

On Thu, Dec 7, 2023 at 4:34 AM Alexandre Oliva <oliva@adacore.com> wrote:
>
> On Dec  6, 2023, Alexandre Oliva <oliva@adacore.com> wrote:
>
> > Disabling the runtime bits is easy, once we determine what condition we
> > wish to test for.  I suppose testing for target support in the compiler,
> > issuing a 'sorry' in case the feature is required, would provide
> > something for libgcc configure and testsuite effective-target to test
> > for and decide whether to enable runtime support and run the tests.
>
> Instead of doing something equivalent to an implicit -fstrub=disable,
> that would quietly compile without stack scrubbing, I thought it would
> be safer to be noisy if the feature is used (requested, really) when
> support is not available.
>
>
> Targets that don't expose callee stacks to callers, such as nvptx, as
> well as -fsplit-stack compilations, violate fundamental assumptions of
> the current strub implementation.  This patch enables targets to
> disable strub, and disables it when -fsplit-stack is enabled.
>
> When strub support is disabled, the testsuite will now skip strub
> tests, and libgcc will not build the strub runtime components.
>
> Regstrapped on x86_64-linux-gnu.  Also tested with an additional patch
> for i386.cc that mirrors the nvptx.cc change, to check that strub gets
> disabled without noisy test results.  Ok to install?

OK.

Thanks,
Richard.

>
> for  gcc/ChangeLog
>
>         * target.def (have_strub_support_for): New hook.
>         * doc/tm.texi.in: Document it.
>         * doc/tm.texi: Rebuild.
>         * ipa-strub.cc: Include target.h.
>         (strub_target_support_p): New.
>         (can_strub_p): Call it.  Test for no flag_split_stack.
>         (pass_ipa_strub::adjust_at_calls_call): Check for target
>         support.
>         * config/nvptx/nvptx.cc (TARGET_HAVE_STRUB_SUPPORT_FOR):
>         Disable.
>         * doc/sourcebuild.texi (strub): Document new effective
>         target.
>
> for  gcc/testsuite/ChangeLog
>
>         * gcc.dg/strub-split-stack.c: New.
>         * gcc.dg/strub-unsupported.c: New.
>         * gcc.dg/strub-unsupported-2.c: New.
>         * gcc.dg/strub-unsupported-3.c: New.
>         * lib/target-supports.exp (check_effective_target_strub): New.
>         * c-c++-common/strub-O0.c: Require effective target strub.
>         * c-c++-common/strub-O1.c: Likewise.
>         * c-c++-common/strub-O2.c: Likewise.
>         * c-c++-common/strub-O2fni.c: Likewise.
>         * c-c++-common/strub-O3.c: Likewise.
>         * c-c++-common/strub-O3fni.c: Likewise.
>         * c-c++-common/strub-Og.c: Likewise.
>         * c-c++-common/strub-Os.c: Likewise.
>         * c-c++-common/strub-all1.c: Likewise.
>         * c-c++-common/strub-all2.c: Likewise.
>         * c-c++-common/strub-apply1.c: Likewise.
>         * c-c++-common/strub-apply2.c: Likewise.
>         * c-c++-common/strub-apply3.c: Likewise.
>         * c-c++-common/strub-apply4.c: Likewise.
>         * c-c++-common/strub-at-calls1.c: Likewise.
>         * c-c++-common/strub-at-calls2.c: Likewise.
>         * c-c++-common/strub-defer-O1.c: Likewise.
>         * c-c++-common/strub-defer-O2.c: Likewise.
>         * c-c++-common/strub-defer-O3.c: Likewise.
>         * c-c++-common/strub-defer-Os.c: Likewise.
>         * c-c++-common/strub-internal1.c: Likewise.
>         * c-c++-common/strub-internal2.c: Likewise.
>         * c-c++-common/strub-parms1.c: Likewise.
>         * c-c++-common/strub-parms2.c: Likewise.
>         * c-c++-common/strub-parms3.c: Likewise.
>         * c-c++-common/strub-relaxed1.c: Likewise.
>         * c-c++-common/strub-relaxed2.c: Likewise.
>         * c-c++-common/strub-short-O0-exc.c: Likewise.
>         * c-c++-common/strub-short-O0.c: Likewise.
>         * c-c++-common/strub-short-O1.c: Likewise.
>         * c-c++-common/strub-short-O2.c: Likewise.
>         * c-c++-common/strub-short-O3.c: Likewise.
>         * c-c++-common/strub-short-Os.c: Likewise.
>         * c-c++-common/strub-strict1.c: Likewise.
>         * c-c++-common/strub-strict2.c: Likewise.
>         * c-c++-common/strub-tail-O1.c: Likewise.
>         * c-c++-common/strub-tail-O2.c: Likewise.
>         * c-c++-common/strub-var1.c: Likewise.
>         * c-c++-common/torture/strub-callable1.c: Likewise.
>         * c-c++-common/torture/strub-callable2.c: Likewise.
>         * c-c++-common/torture/strub-const1.c: Likewise.
>         * c-c++-common/torture/strub-const2.c: Likewise.
>         * c-c++-common/torture/strub-const3.c: Likewise.
>         * c-c++-common/torture/strub-const4.c: Likewise.
>         * c-c++-common/torture/strub-data1.c: Likewise.
>         * c-c++-common/torture/strub-data2.c: Likewise.
>         * c-c++-common/torture/strub-data3.c: Likewise.
>         * c-c++-common/torture/strub-data4.c: Likewise.
>         * c-c++-common/torture/strub-data5.c: Likewise.
>         * c-c++-common/torture/strub-indcall1.c: Likewise.
>         * c-c++-common/torture/strub-indcall2.c: Likewise.
>         * c-c++-common/torture/strub-indcall3.c: Likewise.
>         * c-c++-common/torture/strub-inlinable1.c: Likewise.
>         * c-c++-common/torture/strub-inlinable2.c: Likewise.
>         * c-c++-common/torture/strub-ptrfn1.c: Likewise.
>         * c-c++-common/torture/strub-ptrfn2.c: Likewise.
>         * c-c++-common/torture/strub-ptrfn3.c: Likewise.
>         * c-c++-common/torture/strub-ptrfn4.c: Likewise.
>         * c-c++-common/torture/strub-pure1.c: Likewise.
>         * c-c++-common/torture/strub-pure2.c: Likewise.
>         * c-c++-common/torture/strub-pure3.c: Likewise.
>         * c-c++-common/torture/strub-pure4.c: Likewise.
>         * c-c++-common/torture/strub-run1.c: Likewise.
>         * c-c++-common/torture/strub-run2.c: Likewise.
>         * c-c++-common/torture/strub-run3.c: Likewise.
>         * c-c++-common/torture/strub-run4.c: Likewise.
>         * c-c++-common/torture/strub-run4c.c: Likewise.
>         * c-c++-common/torture/strub-run4d.c: Likewise.
>         * c-c++-common/torture/strub-run4i.c: Likewise.
>         * g++.dg/strub-run1.C: Likewise.
>         * g++.dg/torture/strub-init1.C: Likewise.
>         * g++.dg/torture/strub-init2.C: Likewise.
>         * g++.dg/torture/strub-init3.C: Likewise.
>         * gnat.dg/strub_attr.adb: Likewise.
>         * gnat.dg/strub_ind.adb: Likewise.
>         * gnat.dg/strub_access.adb: Likewise.
>         * gnat.dg/strub_access1.adb: Likewise.
>         * gnat.dg/strub_disp.adb: Likewise.
>         * gnat.dg/strub_disp1.adb: Likewise.
>         * gnat.dg/strub_ind1.adb: Likewise.
>         * gnat.dg/strub_ind2.adb: Likewise.
>         * gnat.dg/strub_intf.adb: Likewise.
>         * gnat.dg/strub_intf1.adb: Likewise.
>         * gnat.dg/strub_intf2.adb: Likewise.
>         * gnat.dg/strub_renm.adb: Likewise.
>         * gnat.dg/strub_renm1.adb: Likewise.
>         * gnat.dg/strub_renm2.adb: Likewise.
>         * gnat.dg/strub_var.adb: Likewise.
>         * gnat.dg/strub_var1.adb: Likewise.
>
> for  libgcc/ChangeLog
>
>         * configure.ac: Check for strub support.
>         * configure: Rebuilt.
>         * Makefile.in: Compile strub.c conditionally.
> ---
>  gcc/config/nvptx/nvptx.cc                          |    3 +
>  gcc/doc/sourcebuild.texi                           |    3 +
>  gcc/doc/tm.texi                                    |    6 ++
>  gcc/doc/tm.texi.in                                 |    2 +
>  gcc/ipa-strub.cc                                   |   54 +++++++++++++++++++-
>  gcc/target.def                                     |    8 +++
>  gcc/testsuite/c-c++-common/strub-O0.c              |    1
>  gcc/testsuite/c-c++-common/strub-O1.c              |    1
>  gcc/testsuite/c-c++-common/strub-O2.c              |    1
>  gcc/testsuite/c-c++-common/strub-O2fni.c           |    1
>  gcc/testsuite/c-c++-common/strub-O3.c              |    1
>  gcc/testsuite/c-c++-common/strub-O3fni.c           |    1
>  gcc/testsuite/c-c++-common/strub-Og.c              |    1
>  gcc/testsuite/c-c++-common/strub-Os.c              |    1
>  gcc/testsuite/c-c++-common/strub-all1.c            |    1
>  gcc/testsuite/c-c++-common/strub-all2.c            |    1
>  gcc/testsuite/c-c++-common/strub-apply1.c          |    1
>  gcc/testsuite/c-c++-common/strub-apply2.c          |    1
>  gcc/testsuite/c-c++-common/strub-apply3.c          |    1
>  gcc/testsuite/c-c++-common/strub-apply4.c          |    1
>  gcc/testsuite/c-c++-common/strub-at-calls1.c       |    1
>  gcc/testsuite/c-c++-common/strub-at-calls2.c       |    1
>  gcc/testsuite/c-c++-common/strub-defer-O1.c        |    1
>  gcc/testsuite/c-c++-common/strub-defer-O2.c        |    1
>  gcc/testsuite/c-c++-common/strub-defer-O3.c        |    1
>  gcc/testsuite/c-c++-common/strub-defer-Os.c        |    1
>  gcc/testsuite/c-c++-common/strub-internal1.c       |    1
>  gcc/testsuite/c-c++-common/strub-internal2.c       |    1
>  gcc/testsuite/c-c++-common/strub-parms1.c          |    1
>  gcc/testsuite/c-c++-common/strub-parms2.c          |    1
>  gcc/testsuite/c-c++-common/strub-parms3.c          |    1
>  gcc/testsuite/c-c++-common/strub-relaxed1.c        |    1
>  gcc/testsuite/c-c++-common/strub-relaxed2.c        |    1
>  gcc/testsuite/c-c++-common/strub-short-O0-exc.c    |    1
>  gcc/testsuite/c-c++-common/strub-short-O0.c        |    1
>  gcc/testsuite/c-c++-common/strub-short-O1.c        |    1
>  gcc/testsuite/c-c++-common/strub-short-O2.c        |    1
>  gcc/testsuite/c-c++-common/strub-short-O3.c        |    1
>  gcc/testsuite/c-c++-common/strub-short-Os.c        |    1
>  gcc/testsuite/c-c++-common/strub-split-stack.c     |   10 ++++
>  gcc/testsuite/c-c++-common/strub-strict1.c         |    1
>  gcc/testsuite/c-c++-common/strub-strict2.c         |    1
>  gcc/testsuite/c-c++-common/strub-tail-O1.c         |    1
>  gcc/testsuite/c-c++-common/strub-tail-O2.c         |    1
>  gcc/testsuite/c-c++-common/strub-unsupported-2.c   |   13 +++++
>  gcc/testsuite/c-c++-common/strub-unsupported-3.c   |   18 +++++++
>  gcc/testsuite/c-c++-common/strub-unsupported.c     |   21 ++++++++
>  gcc/testsuite/c-c++-common/strub-var1.c            |    1
>  .../c-c++-common/torture/strub-callable1.c         |    1
>  .../c-c++-common/torture/strub-callable2.c         |    1
>  gcc/testsuite/c-c++-common/torture/strub-const1.c  |    1
>  gcc/testsuite/c-c++-common/torture/strub-const2.c  |    1
>  gcc/testsuite/c-c++-common/torture/strub-const3.c  |    1
>  gcc/testsuite/c-c++-common/torture/strub-const4.c  |    1
>  gcc/testsuite/c-c++-common/torture/strub-data1.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-data2.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-data3.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-data4.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-data5.c   |    1
>  .../c-c++-common/torture/strub-indcall1.c          |    1
>  .../c-c++-common/torture/strub-indcall2.c          |    1
>  .../c-c++-common/torture/strub-indcall3.c          |    1
>  .../c-c++-common/torture/strub-inlinable1.c        |    1
>  .../c-c++-common/torture/strub-inlinable2.c        |    1
>  gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c  |    1
>  gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c  |    1
>  gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c  |    1
>  gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c  |    1
>  gcc/testsuite/c-c++-common/torture/strub-pure1.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-pure2.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-pure3.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-pure4.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-run1.c    |    1
>  gcc/testsuite/c-c++-common/torture/strub-run2.c    |    1
>  gcc/testsuite/c-c++-common/torture/strub-run3.c    |    1
>  gcc/testsuite/c-c++-common/torture/strub-run4.c    |    1
>  gcc/testsuite/c-c++-common/torture/strub-run4c.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-run4d.c   |    1
>  gcc/testsuite/c-c++-common/torture/strub-run4i.c   |    1
>  gcc/testsuite/g++.dg/strub-run1.C                  |    1
>  gcc/testsuite/g++.dg/torture/strub-init1.C         |    1
>  gcc/testsuite/g++.dg/torture/strub-init2.C         |    1
>  gcc/testsuite/g++.dg/torture/strub-init3.C         |    1
>  gcc/testsuite/gnat.dg/strub_access.adb             |    1
>  gcc/testsuite/gnat.dg/strub_access1.adb            |    1
>  gcc/testsuite/gnat.dg/strub_attr.adb               |    1
>  gcc/testsuite/gnat.dg/strub_disp.adb               |    1
>  gcc/testsuite/gnat.dg/strub_disp1.adb              |    1
>  gcc/testsuite/gnat.dg/strub_ind.adb                |    1
>  gcc/testsuite/gnat.dg/strub_ind1.adb               |    1
>  gcc/testsuite/gnat.dg/strub_ind2.adb               |    1
>  gcc/testsuite/gnat.dg/strub_intf.adb               |    1
>  gcc/testsuite/gnat.dg/strub_intf1.adb              |    1
>  gcc/testsuite/gnat.dg/strub_intf2.adb              |    1
>  gcc/testsuite/gnat.dg/strub_renm.adb               |    1
>  gcc/testsuite/gnat.dg/strub_renm1.adb              |    1
>  gcc/testsuite/gnat.dg/strub_renm2.adb              |    1
>  gcc/testsuite/gnat.dg/strub_var.adb                |    1
>  gcc/testsuite/gnat.dg/strub_var1.adb               |    1
>  gcc/testsuite/lib/target-supports.exp              |    7 +++
>  libgcc/Makefile.in                                 |    2 -
>  libgcc/configure                                   |   26 ++++++++++
>  libgcc/configure.ac                                |   13 +++++
>  103 files changed, 272 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/testsuite/c-c++-common/strub-split-stack.c
>  create mode 100644 gcc/testsuite/c-c++-common/strub-unsupported-2.c
>  create mode 100644 gcc/testsuite/c-c++-common/strub-unsupported-3.c
>  create mode 100644 gcc/testsuite/c-c++-common/strub-unsupported.c
>
> diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc
> index ae20802c87996..3fb1deb70fda1 100644
> --- a/gcc/config/nvptx/nvptx.cc
> +++ b/gcc/config/nvptx/nvptx.cc
> @@ -7789,6 +7789,9 @@ nvptx_asm_output_def_from_decls (FILE *stream, tree name, tree value)
>  #undef TARGET_LIBC_HAS_FUNCTION
>  #define TARGET_LIBC_HAS_FUNCTION nvptx_libc_has_function
>
> +#undef TARGET_HAVE_STRUB_SUPPORT_FOR
> +#define TARGET_HAVE_STRUB_SUPPORT_FOR hook_bool_tree_false
> +
>  struct gcc_target targetm = TARGET_INITIALIZER;
>
>  #include "gt-nvptx.h"
> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
> index c990902685417..26a7e9c350703 100644
> --- a/gcc/doc/sourcebuild.texi
> +++ b/gcc/doc/sourcebuild.texi
> @@ -2983,6 +2983,9 @@ Target supports statically linking @samp{libgfortran}.
>  @item string_merging
>  Target supports merging string constants at link time.
>
> +@item strub
> +Target supports attribute @code{strub} for stack scrubbing.
> +
>  @item ucn
>  Target supports compiling and assembling UCN.
>
> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> index 89a1735dd7992..768ada0af5222 100644
> --- a/gcc/doc/tm.texi
> +++ b/gcc/doc/tm.texi
> @@ -3450,6 +3450,12 @@ in DWARF 2 debug information.  The default is zero.  A different value
>  may reduce the size of debug information on some ports.
>  @end defmac
>
> +@deftypefn {Target Hook} bool TARGET_HAVE_STRUB_SUPPORT_FOR (tree)
> +Returns true if the target supports stack scrubbing for the given function
> +or type, otherwise return false.  The default implementation always returns
> +true.
> +@end deftypefn
> +
>  @defmac TARGET_STRUB_USE_DYNAMIC_ARRAY
>  If defined to nonzero, @code{__strub_leave} will allocate a dynamic
>  array covering the stack range that needs scrubbing before clearing it.
> diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
> index ebc1d3de5caaa..4fe0805394ea4 100644
> --- a/gcc/doc/tm.texi.in
> +++ b/gcc/doc/tm.texi.in
> @@ -2686,6 +2686,8 @@ in DWARF 2 debug information.  The default is zero.  A different value
>  may reduce the size of debug information on some ports.
>  @end defmac
>
> +@hook TARGET_HAVE_STRUB_SUPPORT_FOR
> +
>  @defmac TARGET_STRUB_USE_DYNAMIC_ARRAY
>  If defined to nonzero, @code{__strub_leave} will allocate a dynamic
>  array covering the stack range that needs scrubbing before clearing it.
> diff --git a/gcc/ipa-strub.cc b/gcc/ipa-strub.cc
> index 293bec132b885..2afb7a455751d 100644
> --- a/gcc/ipa-strub.cc
> +++ b/gcc/ipa-strub.cc
> @@ -60,6 +60,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "ipa-strub.h"
>  #include "symtab-thunks.h"
>  #include "attr-fnspec.h"
> +#include "target.h"
>
>  /* This file introduces two passes that, together, implement
>     machine-independent stack scrubbing, strub for short.  It arranges
> @@ -631,17 +632,60 @@ strub_always_inline_p (cgraph_node *node)
>    return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl));
>  }
>
> +/* Return TRUE iff the target has strub support for T, a function
> +   decl, or a type used in an indirect call, and optionally REPORT the
> +   reasons for ineligibility.  If T is a type and error REPORTing is
> +   enabled, the LOCation (of the indirect call) should be provided.  */
> +static inline bool
> +strub_target_support_p (tree t, bool report = false,
> +                       location_t loc = UNKNOWN_LOCATION)
> +{
> +  bool result = true;
> +
> +  if (!targetm.have_strub_support_for (t))
> +    {
> +      result = false;
> +
> +      if (!report)
> +       return result;
> +
> +      if (DECL_P (t))
> +       sorry_at (DECL_SOURCE_LOCATION (t),
> +                 "%qD is not eligible for %<strub%>"
> +                 " on the target system", t);
> +      else
> +       sorry_at (loc,
> +                 "unsupported %<strub%> call"
> +                 " on the target system");
> +    }
> +
> +  return result;
> +}
> +
>  /* Return TRUE iff NODE is potentially eligible for any strub-enabled mode, and
>     optionally REPORT the reasons for ineligibility.  */
>
>  static inline bool
>  can_strub_p (cgraph_node *node, bool report = false)
>  {
> -  bool result = true;
> +  bool result = strub_target_support_p (node->decl, report);
>
> -  if (!report && strub_always_inline_p (node))
> +  if (!report && (!result || strub_always_inline_p (node)))
>      return result;
>
> +  if (flag_split_stack)
> +    {
> +      result = false;
> +
> +      if (!report)
> +       return result;
> +
> +      sorry_at (DECL_SOURCE_LOCATION (node->decl),
> +               "%qD is not eligible for %<strub%>"
> +               " because %<-fsplit-stack%> is enabled",
> +               node->decl);
> +    }
> +
>    if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)))
>      {
>        result = false;
> @@ -2417,6 +2461,12 @@ pass_ipa_strub::adjust_at_calls_call (cgraph_edge *e, int named_args,
>                          && (TREE_TYPE (gimple_call_arg (ocall, named_args))
>                              == get_pwmt ())));
>
> +  tree tsup;
> +  if (!(tsup = gimple_call_fndecl (ocall)))
> +    tsup = TREE_TYPE (TREE_TYPE (gimple_call_fn (ocall)));
> +  if (!strub_target_support_p (tsup, true, gimple_location (ocall)))
> +    return;
> +
>    /* If we're already within a strub context, pass on the incoming watermark
>       pointer, and omit the enter and leave calls around the modified call, as an
>       optimization, or as a means to satisfy a tail-call requirement.  */
> diff --git a/gcc/target.def b/gcc/target.def
> index 52b83e091b94b..08218f3a42adf 100644
> --- a/gcc/target.def
> +++ b/gcc/target.def
> @@ -4457,6 +4457,14 @@ otherwise return false.  The default implementation always returns true.",
>   bool, (void),
>   hook_bool_void_true)
>
> +DEFHOOK
> +(have_strub_support_for,
> + "Returns true if the target supports stack scrubbing for the given function\n\
> +or type, otherwise return false.  The default implementation always returns\n\
> +true.",
> + bool, (tree),
> + hook_bool_tree_true)
> +
>  DEFHOOK
>  (have_speculation_safe_value,
>  "This hook is used to determine the level of target support for\n\
> diff --git a/gcc/testsuite/c-c++-common/strub-O0.c b/gcc/testsuite/c-c++-common/strub-O0.c
> index c7a79a6ea0d8a..f0a3f7b4c6f9a 100644
> --- a/gcc/testsuite/c-c++-common/strub-O0.c
> +++ b/gcc/testsuite/c-c++-common/strub-O0.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O0 -fstrub=strict -fdump-rtl-expand" } */
> +/* { dg-require-effective-target strub } */
>
>  /* At -O0, none of the strub builtins are expanded inline.  */
>
> diff --git a/gcc/testsuite/c-c++-common/strub-O1.c b/gcc/testsuite/c-c++-common/strub-O1.c
> index 96285c975d98e..50403426b18f2 100644
> --- a/gcc/testsuite/c-c++-common/strub-O1.c
> +++ b/gcc/testsuite/c-c++-common/strub-O1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O1 -fstrub=strict -fdump-rtl-expand" } */
> +/* { dg-require-effective-target strub } */
>
>  /* At -O1, without -fno-inline, we fully expand enter, but neither update nor
>     leave.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-O2.c b/gcc/testsuite/c-c++-common/strub-O2.c
> index 8edc0d8aa1321..37e02998e318e 100644
> --- a/gcc/testsuite/c-c++-common/strub-O2.c
> +++ b/gcc/testsuite/c-c++-common/strub-O2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O2 -fstrub=strict -fdump-rtl-expand" } */
> +/* { dg-require-effective-target strub } */
>
>  /* At -O2, without -fno-inline, we fully expand enter and update, and add a test
>     around the leave call.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-O2fni.c b/gcc/testsuite/c-c++-common/strub-O2fni.c
> index c6d900cf3c45b..905e2c6b2ffca 100644
> --- a/gcc/testsuite/c-c++-common/strub-O2fni.c
> +++ b/gcc/testsuite/c-c++-common/strub-O2fni.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O2 -fstrub=strict -fdump-rtl-expand -fno-inline" } */
> +/* { dg-require-effective-target strub } */
>
>  /* With -fno-inline, none of the strub builtins are inlined.  */
>
> diff --git a/gcc/testsuite/c-c++-common/strub-O3.c b/gcc/testsuite/c-c++-common/strub-O3.c
> index 33ee465e51cb6..3bbf132bdf1ea 100644
> --- a/gcc/testsuite/c-c++-common/strub-O3.c
> +++ b/gcc/testsuite/c-c++-common/strub-O3.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O3 -fstrub=strict -fdump-rtl-expand" } */
> +/* { dg-require-effective-target strub } */
>
>  int __attribute__ ((__strub__)) var;
>
> diff --git a/gcc/testsuite/c-c++-common/strub-O3fni.c b/gcc/testsuite/c-c++-common/strub-O3fni.c
> index 2936f82079e18..c46fce38e5c91 100644
> --- a/gcc/testsuite/c-c++-common/strub-O3fni.c
> +++ b/gcc/testsuite/c-c++-common/strub-O3fni.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O3 -fstrub=strict -fdump-rtl-expand -fno-inline" } */
> +/* { dg-require-effective-target strub } */
>
>  /* With -fno-inline, none of the strub builtins are inlined.  */
>
> diff --git a/gcc/testsuite/c-c++-common/strub-Og.c b/gcc/testsuite/c-c++-common/strub-Og.c
> index 479746e57d87e..3b8eb19765cd6 100644
> --- a/gcc/testsuite/c-c++-common/strub-Og.c
> +++ b/gcc/testsuite/c-c++-common/strub-Og.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-Og -fstrub=strict -fdump-rtl-expand" } */
> +/* { dg-require-effective-target strub } */
>
>  /* At -Og, without -fno-inline, we fully expand enter, but neither update nor
>     leave.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-Os.c b/gcc/testsuite/c-c++-common/strub-Os.c
> index 2241d4ea07f27..8cfb253d6764c 100644
> --- a/gcc/testsuite/c-c++-common/strub-Os.c
> +++ b/gcc/testsuite/c-c++-common/strub-Os.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-Os -fstrub=strict -fdump-rtl-expand" } */
> +/* { dg-require-effective-target strub } */
>
>  /* At -Os, without -fno-inline, we fully expand enter, and also update.  The
>     expanded update might be larger than a call proper, but argument saving and
> diff --git a/gcc/testsuite/c-c++-common/strub-all1.c b/gcc/testsuite/c-c++-common/strub-all1.c
> index a322bcc5da606..2037f681f2973 100644
> --- a/gcc/testsuite/c-c++-common/strub-all1.c
> +++ b/gcc/testsuite/c-c++-common/strub-all1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=all -fdump-ipa-strubm -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* h becomes STRUB_CALLABLE, rather than STRUB_INLINABLE, because of the
>     strub-enabling -fstrub flag, and gets inlined before pass_ipa_strub.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-all2.c b/gcc/testsuite/c-c++-common/strub-all2.c
> index db60026d0e080..c026e7d9d289b 100644
> --- a/gcc/testsuite/c-c++-common/strub-all2.c
> +++ b/gcc/testsuite/c-c++-common/strub-all2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=all -fdump-ipa-strubm -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* g becomes STRUB_INTERNAL, because of the flag.  Without inline, force_output
>     is set for static non-inline functions when not optimizing, and that keeps
> diff --git a/gcc/testsuite/c-c++-common/strub-apply1.c b/gcc/testsuite/c-c++-common/strub-apply1.c
> index 2f462adc1efe0..3edc89c54eea1 100644
> --- a/gcc/testsuite/c-c++-common/strub-apply1.c
> +++ b/gcc/testsuite/c-c++-common/strub-apply1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict" } */
> +/* { dg-require-effective-target strub } */
>
>  void __attribute__ ((__strub__ ("callable")))
>  apply_function (void *args)
> diff --git a/gcc/testsuite/c-c++-common/strub-apply2.c b/gcc/testsuite/c-c++-common/strub-apply2.c
> index a5d7551f5da5c..838fc75273450 100644
> --- a/gcc/testsuite/c-c++-common/strub-apply2.c
> +++ b/gcc/testsuite/c-c++-common/strub-apply2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict" } */
> +/* { dg-require-effective-target strub } */
>
>  extern void __attribute__ ((__strub__))
>  apply_function (void *args);
> diff --git a/gcc/testsuite/c-c++-common/strub-apply3.c b/gcc/testsuite/c-c++-common/strub-apply3.c
> index 64422a0d1e880..0206e4d930e7d 100644
> --- a/gcc/testsuite/c-c++-common/strub-apply3.c
> +++ b/gcc/testsuite/c-c++-common/strub-apply3.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict" } */
> +/* { dg-require-effective-target strub } */
>
>  void __attribute__ ((__strub__))
>  apply_function (void *args)
> diff --git a/gcc/testsuite/c-c++-common/strub-apply4.c b/gcc/testsuite/c-c++-common/strub-apply4.c
> index 15ffaa031b899..e82504728b2c6 100644
> --- a/gcc/testsuite/c-c++-common/strub-apply4.c
> +++ b/gcc/testsuite/c-c++-common/strub-apply4.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O2 -fstrub=strict -fdump-ipa-strubm" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that implicit enabling of strub mode selects internal strub when the
>     function uses __builtin_apply_args, that prevents the optimization to
> diff --git a/gcc/testsuite/c-c++-common/strub-at-calls1.c b/gcc/testsuite/c-c++-common/strub-at-calls1.c
> index b70843b4215a4..a20acc0a48a58 100644
> --- a/gcc/testsuite/c-c++-common/strub-at-calls1.c
> +++ b/gcc/testsuite/c-c++-common/strub-at-calls1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=at-calls -fdump-ipa-strubm -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* h becomes STRUB_CALLABLE, rather than STRUB_INLINABLE, because of the
>     strub-enabling -fstrub flag, and gets inlined before pass_ipa_strub.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-at-calls2.c b/gcc/testsuite/c-c++-common/strub-at-calls2.c
> index 97a3988a6b922..7915b33a39a0a 100644
> --- a/gcc/testsuite/c-c++-common/strub-at-calls2.c
> +++ b/gcc/testsuite/c-c++-common/strub-at-calls2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=at-calls -fdump-ipa-strubm -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* g does NOT become STRUB_AT_CALLS because it's not viable.  Without inline,
>     force_output is set for static non-inline functions when not optimizing, and
> diff --git a/gcc/testsuite/c-c++-common/strub-defer-O1.c b/gcc/testsuite/c-c++-common/strub-defer-O1.c
> index 3d73431b3dcd3..3689998b5a323 100644
> --- a/gcc/testsuite/c-c++-common/strub-defer-O1.c
> +++ b/gcc/testsuite/c-c++-common/strub-defer-O1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=strict -O1" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that a strub function called by another strub function does NOT defer
>     the strubbing to its caller at -O1.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-defer-O2.c b/gcc/testsuite/c-c++-common/strub-defer-O2.c
> index fddf3c745e7e6..9e01949db6be9 100644
> --- a/gcc/testsuite/c-c++-common/strub-defer-O2.c
> +++ b/gcc/testsuite/c-c++-common/strub-defer-O2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=strict -O2" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that a strub function called by another strub function does NOT defer
>     the strubbing to its caller at -O2.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-defer-O3.c b/gcc/testsuite/c-c++-common/strub-defer-O3.c
> index 7ebc65b58dd72..40ee8edd1e0e6 100644
> --- a/gcc/testsuite/c-c++-common/strub-defer-O3.c
> +++ b/gcc/testsuite/c-c++-common/strub-defer-O3.c
> @@ -1,5 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=strict -O3" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that a strub function called by another strub function defers the
>     strubbing to its caller at -O3.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-defer-Os.c b/gcc/testsuite/c-c++-common/strub-defer-Os.c
> index fbaf85fe0fafe..67ea9f0463975 100644
> --- a/gcc/testsuite/c-c++-common/strub-defer-Os.c
> +++ b/gcc/testsuite/c-c++-common/strub-defer-Os.c
> @@ -1,5 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=strict -Os" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that a strub function called by another strub function defers the
>     strubbing to its caller at -Os.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-internal1.c b/gcc/testsuite/c-c++-common/strub-internal1.c
> index e9d7b7b9ee0a8..d17254904e50a 100644
> --- a/gcc/testsuite/c-c++-common/strub-internal1.c
> +++ b/gcc/testsuite/c-c++-common/strub-internal1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=internal -fdump-ipa-strubm -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* h becomes STRUB_CALLABLE, rather than STRUB_INLINABLE, because of the
>     strub-enabling -fstrub flag, and gets inlined before pass_ipa_strub.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-internal2.c b/gcc/testsuite/c-c++-common/strub-internal2.c
> index 8b8e15a51c71c..afc9189701f82 100644
> --- a/gcc/testsuite/c-c++-common/strub-internal2.c
> +++ b/gcc/testsuite/c-c++-common/strub-internal2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=internal -fdump-ipa-strubm -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* g becomes STRUB_INTERNAL, because of the flag.  */
>  static void
> diff --git a/gcc/testsuite/c-c++-common/strub-parms1.c b/gcc/testsuite/c-c++-common/strub-parms1.c
> index 0a4a7539d3489..f410b268971a6 100644
> --- a/gcc/testsuite/c-c++-common/strub-parms1.c
> +++ b/gcc/testsuite/c-c++-common/strub-parms1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  #include <stdarg.h>
>
> diff --git a/gcc/testsuite/c-c++-common/strub-parms2.c b/gcc/testsuite/c-c++-common/strub-parms2.c
> index 147171d96d5a1..6f572115a88c3 100644
> --- a/gcc/testsuite/c-c++-common/strub-parms2.c
> +++ b/gcc/testsuite/c-c++-common/strub-parms2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  #include <stdarg.h>
>
> diff --git a/gcc/testsuite/c-c++-common/strub-parms3.c b/gcc/testsuite/c-c++-common/strub-parms3.c
> index 4e92682895a43..7383fea9ce881 100644
> --- a/gcc/testsuite/c-c++-common/strub-parms3.c
> +++ b/gcc/testsuite/c-c++-common/strub-parms3.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that uses of a strub variable implicitly enables internal strub for
>     publicly-visible functions, and causes the same transformations to their
> diff --git a/gcc/testsuite/c-c++-common/strub-relaxed1.c b/gcc/testsuite/c-c++-common/strub-relaxed1.c
> index e2f9d8aebca58..d2b4b52c51e60 100644
> --- a/gcc/testsuite/c-c++-common/strub-relaxed1.c
> +++ b/gcc/testsuite/c-c++-common/strub-relaxed1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=relaxed -fdump-ipa-strubm -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* The difference between relaxed and strict in this case is that we accept the
>     call from one internal-strub function to another.  Without the error,
> diff --git a/gcc/testsuite/c-c++-common/strub-relaxed2.c b/gcc/testsuite/c-c++-common/strub-relaxed2.c
> index 98474435d2e59..9e5a8e76b6c3d 100644
> --- a/gcc/testsuite/c-c++-common/strub-relaxed2.c
> +++ b/gcc/testsuite/c-c++-common/strub-relaxed2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=relaxed -fdump-ipa-strubm -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* The difference between relaxed and strict in this case is that we accept the
>     call from one internal-strub function to another.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-short-O0-exc.c b/gcc/testsuite/c-c++-common/strub-short-O0-exc.c
> index 1de15342595e4..aaeba2a2159a9 100644
> --- a/gcc/testsuite/c-c++-common/strub-short-O0-exc.c
> +++ b/gcc/testsuite/c-c++-common/strub-short-O0-exc.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O0 -fstrub=strict -fexceptions -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that the expected strub calls are issued.  */
>
> diff --git a/gcc/testsuite/c-c++-common/strub-short-O0.c b/gcc/testsuite/c-c++-common/strub-short-O0.c
> index f9209c819004b..30cbdd819f176 100644
> --- a/gcc/testsuite/c-c++-common/strub-short-O0.c
> +++ b/gcc/testsuite/c-c++-common/strub-short-O0.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O0 -fstrub=strict -fno-exceptions -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that the expected strub calls are issued.  */
>
> diff --git a/gcc/testsuite/c-c++-common/strub-short-O1.c b/gcc/testsuite/c-c++-common/strub-short-O1.c
> index bed1dcfb54a45..911fdfb6db9a5 100644
> --- a/gcc/testsuite/c-c++-common/strub-short-O1.c
> +++ b/gcc/testsuite/c-c++-common/strub-short-O1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O1 -fstrub=strict -fno-exceptions -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that the expected strub calls are issued.  */
>
> diff --git a/gcc/testsuite/c-c++-common/strub-short-O2.c b/gcc/testsuite/c-c++-common/strub-short-O2.c
> index 6bf0071f52b93..9b23ee3ac3312 100644
> --- a/gcc/testsuite/c-c++-common/strub-short-O2.c
> +++ b/gcc/testsuite/c-c++-common/strub-short-O2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O2 -fstrub=strict -fno-exceptions -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that the expected strub calls are issued.  */
>
> diff --git a/gcc/testsuite/c-c++-common/strub-short-O3.c b/gcc/testsuite/c-c++-common/strub-short-O3.c
> index 4732f515bf70c..4b3a8f843ea19 100644
> --- a/gcc/testsuite/c-c++-common/strub-short-O3.c
> +++ b/gcc/testsuite/c-c++-common/strub-short-O3.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O3 -fstrub=strict -fno-exceptions -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that the expected strub calls are issued.  At -O3 and -Os, we omit
>     enter and leave calls within strub contexts, passing on the enclosing
> diff --git a/gcc/testsuite/c-c++-common/strub-short-Os.c b/gcc/testsuite/c-c++-common/strub-short-Os.c
> index 8d6424c479a3a..3627a2406000b 100644
> --- a/gcc/testsuite/c-c++-common/strub-short-Os.c
> +++ b/gcc/testsuite/c-c++-common/strub-short-Os.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-Os -fstrub=strict -fno-exceptions -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that the expected strub calls are issued.  At -O3 and -Os, we omit
>     enter and leave calls within strub contexts, passing on the enclosing
> diff --git a/gcc/testsuite/c-c++-common/strub-split-stack.c b/gcc/testsuite/c-c++-common/strub-split-stack.c
> new file mode 100644
> index 0000000000000..7a030cdb9e9e6
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/strub-split-stack.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-fsplit-stack" } */
> +/* { dg-require-effective-target strub } */
> +/* { dg-require-effective-target split_stack } */
> +
> +void __attribute__ ((__strub__))
> +f () {} /* { dg-message "not eligible|requested" } */
> +
> +void __attribute__ ((__strub__ ("internal")))
> +g () {} /* { dg-message "not eligible|requested" } */
> diff --git a/gcc/testsuite/c-c++-common/strub-strict1.c b/gcc/testsuite/c-c++-common/strub-strict1.c
> index 368522442066e..503eb1734e36f 100644
> --- a/gcc/testsuite/c-c++-common/strub-strict1.c
> +++ b/gcc/testsuite/c-c++-common/strub-strict1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strubm" } */
> +/* { dg-require-effective-target strub } */
>
>  static int __attribute__ ((__strub__)) var;
>
> diff --git a/gcc/testsuite/c-c++-common/strub-strict2.c b/gcc/testsuite/c-c++-common/strub-strict2.c
> index b4f2888321821..3bf1aa30b4af1 100644
> --- a/gcc/testsuite/c-c++-common/strub-strict2.c
> +++ b/gcc/testsuite/c-c++-common/strub-strict2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strubm" } */
> +/* { dg-require-effective-target strub } */
>
>  static int __attribute__ ((__strub__)) var;
>
> diff --git a/gcc/testsuite/c-c++-common/strub-tail-O1.c b/gcc/testsuite/c-c++-common/strub-tail-O1.c
> index e48e0610e079b..ba4b1623e281a 100644
> --- a/gcc/testsuite/c-c++-common/strub-tail-O1.c
> +++ b/gcc/testsuite/c-c++-common/strub-tail-O1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O1 -fstrub=strict -fno-exceptions -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  #include "strub-tail-O2.c"
>
> diff --git a/gcc/testsuite/c-c++-common/strub-tail-O2.c b/gcc/testsuite/c-c++-common/strub-tail-O2.c
> index 87cda7ab21b16..043813b1de467 100644
> --- a/gcc/testsuite/c-c++-common/strub-tail-O2.c
> +++ b/gcc/testsuite/c-c++-common/strub-tail-O2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-O2 -fstrub=strict -fno-exceptions -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that the expected strub calls are issued.
>     Tail calls are short-circuited at -O2+.  */
> diff --git a/gcc/testsuite/c-c++-common/strub-unsupported-2.c b/gcc/testsuite/c-c++-common/strub-unsupported-2.c
> new file mode 100644
> index 0000000000000..3586f4f679dfe
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/strub-unsupported-2.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile } */
> +
> +/* Check that, when strub is not supported (so no dg-required-effective-target
> +   strub above), we report when pointers to strub functions are called.  This
> +   cannot be part of strub-unsupported.c because errors in the strub-mode pass
> +   prevent the main strub pass, where errors at calls are detected, from
> +   running.  */
> +
> +void __attribute__ ((__strub__ ("at-calls"))) (*p) (void);
> +
> +void m () {
> +  p (); /* { dg-message "unsupported" "" { target { ! strub } } } */
> +}
> diff --git a/gcc/testsuite/c-c++-common/strub-unsupported-3.c b/gcc/testsuite/c-c++-common/strub-unsupported-3.c
> new file mode 100644
> index 0000000000000..d6fb4c525c4a6
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/strub-unsupported-3.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +
> +/* Check that, when strub is not supported (so no dg-required-effective-target
> +   strub above), we report when strub functions that are not defined are
> +   called.  This cannot be part of strub-unsupported-2.c because errors in the
> +   strub-mode pass prevent the main strub pass, where errors at calls are
> +   detected, from running.  */
> +
> +extern void __attribute__ ((__strub__))
> +s (void); /* { dg-message "not eligible|requested" "" { target { ! strub } } } */
> +
> +extern void __attribute__ ((__strub__ ("internal")))
> +t (void); /* { dg-message "not eligible|requested" "" { target { ! strub } } } */
> +
> +void m () {
> +  s ();
> +  t ();
> +}
> diff --git a/gcc/testsuite/c-c++-common/strub-unsupported.c b/gcc/testsuite/c-c++-common/strub-unsupported.c
> new file mode 100644
> index 0000000000000..cb5c4049495c4
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/strub-unsupported.c
> @@ -0,0 +1,21 @@
> +/* { dg-do compile } */
> +
> +/* Check that, when strub is not supported (so no dg-required-effective-target
> +   strub above), we report when strub functions are defined, and when they're
> +   called in ways that would require changes.  */
> +
> +void __attribute__ ((__strub__))
> +f (void) {} /* { dg-message "not eligible|requested" "" { target { ! strub } } } */
> +
> +void __attribute__ ((__strub__ ("internal")))
> +g (void) {} /* { dg-message "not eligible|requested" "" { target { ! strub } } } */
> +
> +/* This only gets an error when called, see strub-unsupported-2.c.  */
> +void __attribute__ ((__strub__ ("at-calls"))) (*p) (void);
> +
> +/* These too, see strub-unsupported-3.c.  */
> +extern void __attribute__ ((__strub__))
> +s (void);
> +
> +extern void __attribute__ ((__strub__ ("internal")))
> +t (void);
> diff --git a/gcc/testsuite/c-c++-common/strub-var1.c b/gcc/testsuite/c-c++-common/strub-var1.c
> index eb6250fd39c90..67014aa5de84a 100644
> --- a/gcc/testsuite/c-c++-common/strub-var1.c
> +++ b/gcc/testsuite/c-c++-common/strub-var1.c
> @@ -1,4 +1,5 @@
>  /* { dg-do compile } */
> +/* { dg-require-effective-target strub } */
>
>  int __attribute__ ((strub)) x;
>  float __attribute__ ((strub)) f;
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-callable1.c b/gcc/testsuite/c-c++-common/torture/strub-callable1.c
> index b5e45ab0525ad..86dbee6746d1b 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-callable1.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-callable1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that strub and non-strub functions can be called from non-strub
>     contexts, and that strub and callable functions can be called from strub
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-callable2.c b/gcc/testsuite/c-c++-common/torture/strub-callable2.c
> index 96aa7fe4b07f7..9da120f615645 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-callable2.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-callable2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that impermissible (cross-strub-context) calls are reported.  */
>
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-const1.c b/gcc/testsuite/c-c++-common/torture/strub-const1.c
> index 5e956cb1a9b6b..22056713cce4b 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-const1.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-const1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that, along with a strub const function call, we issue an asm
>     statement to make sure the watermark passed to it is held in memory before
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-const2.c b/gcc/testsuite/c-c++-common/torture/strub-const2.c
> index 73d650292dfbf..a105c66d7a9c9 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-const2.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-const2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that, along with a strub implicitly-const function call, we issue an
>     asm statement to make sure the watermark passed to it is held in memory
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-const3.c b/gcc/testsuite/c-c++-common/torture/strub-const3.c
> index 2584f1f974a58..386200c2784a4 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-const3.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-const3.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that, along with a strub const wrapping call, we issue an asm statement
>     to make sure the watermark passed to it is held in memory before the call,
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-const4.c b/gcc/testsuite/c-c++-common/torture/strub-const4.c
> index d819f54ec0230..817e9fa2118b6 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-const4.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-const4.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that, along with a strub implicitly-const wrapping call, we issue an
>     asm statement to make sure the watermark passed to it is held in memory
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-data1.c b/gcc/testsuite/c-c++-common/torture/strub-data1.c
> index 7c27a2a1a6dca..132ab63ef733a 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-data1.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-data1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* The pointed-to data enables strubbing if accessed.  */
>  int __attribute__ ((__strub__)) var;
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-data2.c b/gcc/testsuite/c-c++-common/torture/strub-data2.c
> index e66d903780afd..b660702d26e75 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-data2.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-data2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* The pointer itself is a strub variable, enabling internal strubbing when
>     its value is used.  */
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-data3.c b/gcc/testsuite/c-c++-common/torture/strub-data3.c
> index 5e08e0e58c658..fc44eef6f8fb5 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-data3.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-data3.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* The pointer itself is a strub variable, that would enable internal strubbing
>     if its value was used.  Here, it's only overwritten, so no strub.  */
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-data4.c b/gcc/testsuite/c-c++-common/torture/strub-data4.c
> index a818e7a38bb5f..85e2f59055b57 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-data4.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-data4.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* The pointer itself is a strub variable, that would enable internal strubbing
>     if its value was used.  Here, it's only overwritten, so no strub.  */
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-data5.c b/gcc/testsuite/c-c++-common/torture/strub-data5.c
> index ddb0b5c0543b0..0a5edac414df1 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-data5.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-data5.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict" } */
> +/* { dg-require-effective-target strub } */
>
>  /* It would be desirable to issue at least warnings for these.  */
>
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-indcall1.c b/gcc/testsuite/c-c++-common/torture/strub-indcall1.c
> index c165f312f16de..988954e7ed6bc 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-indcall1.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-indcall1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  typedef void __attribute__ ((__strub__)) fntype ();
>  fntype (*ptr);
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-indcall2.c b/gcc/testsuite/c-c++-common/torture/strub-indcall2.c
> index 69fcff8d3763d..d3ca91389a700 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-indcall2.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-indcall2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  typedef void __attribute__ ((__strub__)) fntype (int, int);
>  fntype (*ptr);
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-indcall3.c b/gcc/testsuite/c-c++-common/torture/strub-indcall3.c
> index ff006224909bd..89b5979cf7b78 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-indcall3.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-indcall3.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  typedef void __attribute__ ((__strub__)) fntype (int, int, ...);
>  fntype (*ptr);
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-inlinable1.c b/gcc/testsuite/c-c++-common/torture/strub-inlinable1.c
> index 614b02228ba29..4917dda8826d9 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-inlinable1.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-inlinable1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=relaxed" } */
> +/* { dg-require-effective-target strub } */
>
>  inline void __attribute__ ((strub ("internal"), always_inline))
>  inl_int_ali (void)
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-inlinable2.c b/gcc/testsuite/c-c++-common/torture/strub-inlinable2.c
> index f9a6b4a16faf8..c45903856d4ff 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-inlinable2.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-inlinable2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=all" } */
> +/* { dg-require-effective-target strub } */
>
>  #include "strub-inlinable1.c"
>
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c b/gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c
> index b4a7f3992bbaa..b0d6139f0a870 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-ptrfn1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict" } */
> +/* { dg-require-effective-target strub } */
>
>  typedef void ft (void);
>  typedef void ft2 (int, int);
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c b/gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c
> index ef634d351265f..1148c246f2059 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-ptrfn2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=relaxed -Wpedantic" } */
> +/* { dg-require-effective-target strub } */
>
>  /* C++ does not warn about the partial incompatibilities.
>
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c b/gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c
> index e1f179e160e5c..06a72d86d2c58 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-ptrfn3.c
> @@ -1,6 +1,7 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=relaxed -Wpedantic -fpermissive" } */
>  /* { dg-prune-output "command-line option .-fpermissive." } */
> +/* { dg-require-effective-target strub } */
>
>  /* See strub-ptrfn2.c.  */
>
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c b/gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c
> index 70b558afad040..83ea1af7056e7 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-ptrfn4.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=relaxed" } */
> +/* { dg-require-effective-target strub } */
>
>  /* This is strub-ptrfn2.c without -Wpedantic.
>
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure1.c b/gcc/testsuite/c-c++-common/torture/strub-pure1.c
> index a262a086837b2..2643136f178cc 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-pure1.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-pure1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that, along with a strub pure function call, we issue an asm statement
>     to make sure the watermark passed to it is not assumed to be unchanged.  */
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure2.c b/gcc/testsuite/c-c++-common/torture/strub-pure2.c
> index 4c4bd50c209a0..8bda129b77dc6 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-pure2.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-pure2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that, along with a strub implicitly-pure function call, we issue an asm
>     statement to make sure the watermark passed to it is not assumed to be
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure3.c b/gcc/testsuite/c-c++-common/torture/strub-pure3.c
> index ce195c6b1f1b6..00bcbdd097af8 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-pure3.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-pure3.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that, along with a strub pure wrapping call, we issue an asm statement
>     to make sure the watermark passed to it is not assumed to be unchanged.  */
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-pure4.c b/gcc/testsuite/c-c++-common/torture/strub-pure4.c
> index 75cd54ccb5b5d..ea7c40e7912b4 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-pure4.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-pure4.c
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that, along with a strub implicitly-pure wrapping call, we issue an asm
>     statement to make sure the watermark passed to it is not assumed to be
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-run1.c b/gcc/testsuite/c-c++-common/torture/strub-run1.c
> index 7458b3fb54da5..fdf100428631d 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-run1.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-run1.c
> @@ -1,5 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=strict" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that a non-strub function leaves a string behind in the stack, and that
>     equivalent strub functions don't.  Avoid the use of red zones by avoiding
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-run2.c b/gcc/testsuite/c-c++-common/torture/strub-run2.c
> index 5d60a7775f4bb..1228a66599721 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-run2.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-run2.c
> @@ -1,5 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=strict" } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that a non-strub function leaves a string behind in the stack, and that
>     equivalent strub functions don't.  Allow red zones to be used.  */
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-run3.c b/gcc/testsuite/c-c++-common/torture/strub-run3.c
> index c2ad710858e87..e5047a988f5bf 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-run3.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-run3.c
> @@ -1,6 +1,7 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=strict" } */
>  /* { dg-require-effective-target alloca } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that a non-strub function leaves a string behind in the stack, and that
>     equivalent strub functions don't.  */
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-run4.c b/gcc/testsuite/c-c++-common/torture/strub-run4.c
> index 3b36b8e5d68ef..0e84a4bab80fc 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-run4.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-run4.c
> @@ -1,6 +1,7 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=all" } */
>  /* { dg-require-effective-target alloca } */
> +/* { dg-require-effective-target strub } */
>
>  /* Check that multi-level, multi-inlined functions still get cleaned up as
>     expected, without overwriting temporary stack allocations while they should
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-run4c.c b/gcc/testsuite/c-c++-common/torture/strub-run4c.c
> index 57f9baf758ded..edc98486dc93a 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-run4c.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-run4c.c
> @@ -1,5 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=at-calls" } */
>  /* { dg-require-effective-target alloca } */
> +/* { dg-require-effective-target strub } */
>
>  #include "strub-run4.c"
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-run4d.c b/gcc/testsuite/c-c++-common/torture/strub-run4d.c
> index 08de3f1c3b17c..487ed08bb6606 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-run4d.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-run4d.c
> @@ -1,6 +1,7 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=strict" } */
>  /* { dg-require-effective-target alloca } */
> +/* { dg-require-effective-target strub } */
>
>  #define ATTR_STRUB_AT_CALLS __attribute__ ((__strub__ ("at-calls")))
>
> diff --git a/gcc/testsuite/c-c++-common/torture/strub-run4i.c b/gcc/testsuite/c-c++-common/torture/strub-run4i.c
> index 459f6886c5499..a85447ffabfae 100644
> --- a/gcc/testsuite/c-c++-common/torture/strub-run4i.c
> +++ b/gcc/testsuite/c-c++-common/torture/strub-run4i.c
> @@ -1,5 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-options "-fstrub=internal" } */
>  /* { dg-require-effective-target alloca } */
> +/* { dg-require-effective-target strub } */
>
>  #include "strub-run4.c"
> diff --git a/gcc/testsuite/g++.dg/strub-run1.C b/gcc/testsuite/g++.dg/strub-run1.C
> index 0d367fb83d09d..beb8b811f8fca 100644
> --- a/gcc/testsuite/g++.dg/strub-run1.C
> +++ b/gcc/testsuite/g++.dg/strub-run1.C
> @@ -1,5 +1,6 @@
>  // { dg-do run }
>  // { dg-options "-fstrub=internal" }
> +// { dg-require-effective-target strub }
>
>  // Check that we don't get extra copies.
>
> diff --git a/gcc/testsuite/g++.dg/torture/strub-init1.C b/gcc/testsuite/g++.dg/torture/strub-init1.C
> index c226ab10ff651..6ae45fadd70ba 100644
> --- a/gcc/testsuite/g++.dg/torture/strub-init1.C
> +++ b/gcc/testsuite/g++.dg/torture/strub-init1.C
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +// { dg-require-effective-target strub }
>
>  extern int __attribute__((__strub__)) initializer ();
>
> diff --git a/gcc/testsuite/g++.dg/torture/strub-init2.C b/gcc/testsuite/g++.dg/torture/strub-init2.C
> index a7911f1fa7212..8f4849c7fde78 100644
> --- a/gcc/testsuite/g++.dg/torture/strub-init2.C
> +++ b/gcc/testsuite/g++.dg/torture/strub-init2.C
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +// { dg-require-effective-target strub }
>
>  extern int __attribute__((__strub__)) initializer ();
>
> diff --git a/gcc/testsuite/g++.dg/torture/strub-init3.C b/gcc/testsuite/g++.dg/torture/strub-init3.C
> index 6ebebcd01e8ea..14f28e3c276bd 100644
> --- a/gcc/testsuite/g++.dg/torture/strub-init3.C
> +++ b/gcc/testsuite/g++.dg/torture/strub-init3.C
> @@ -1,5 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-options "-fstrub=strict -fdump-ipa-strub" } */
> +// { dg-require-effective-target strub }
>
>  extern int __attribute__((__strub__)) initializer ();
>
> diff --git a/gcc/testsuite/gnat.dg/strub_access.adb b/gcc/testsuite/gnat.dg/strub_access.adb
> index 29e6996ecf61c..488a2d64afe31 100644
> --- a/gcc/testsuite/gnat.dg/strub_access.adb
> +++ b/gcc/testsuite/gnat.dg/strub_access.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fstrub=relaxed -fdump-ipa-strubm" }
> +--  { dg-require-effective-target strub }
>
>  --  The main subprogram doesn't read from the automatic variable, but
>  --  being an automatic variable, its presence should be enough for the
> diff --git a/gcc/testsuite/gnat.dg/strub_access1.adb b/gcc/testsuite/gnat.dg/strub_access1.adb
> index dae4706016436..4a8653c4d843f 100644
> --- a/gcc/testsuite/gnat.dg/strub_access1.adb
> +++ b/gcc/testsuite/gnat.dg/strub_access1.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fstrub=relaxed" }
> +--  { dg-require-effective-target strub }
>
>  --  Check that we reject 'Access of a strub variable whose type does
>  --  not carry a strub modifier.
> diff --git a/gcc/testsuite/gnat.dg/strub_attr.adb b/gcc/testsuite/gnat.dg/strub_attr.adb
> index 10445d7cf8451..eb7826dc990f4 100644
> --- a/gcc/testsuite/gnat.dg/strub_attr.adb
> +++ b/gcc/testsuite/gnat.dg/strub_attr.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fstrub=strict -fdump-ipa-strubm -fdump-ipa-strub" }
> +--  { dg-require-effective-target strub }
>
>  package body Strub_Attr is
>     E : exception;
> diff --git a/gcc/testsuite/gnat.dg/strub_disp.adb b/gcc/testsuite/gnat.dg/strub_disp.adb
> index 3dbcc4a357cba..f23d4675def38 100644
> --- a/gcc/testsuite/gnat.dg/strub_disp.adb
> +++ b/gcc/testsuite/gnat.dg/strub_disp.adb
> @@ -1,4 +1,5 @@
>  --  { dg-do compile }
> +--  { dg-require-effective-target strub }
>
>  procedure Strub_Disp is
>     package Foo is
> diff --git a/gcc/testsuite/gnat.dg/strub_disp1.adb b/gcc/testsuite/gnat.dg/strub_disp1.adb
> index 09756a74b7d81..9c4c7f696371d 100644
> --- a/gcc/testsuite/gnat.dg/strub_disp1.adb
> +++ b/gcc/testsuite/gnat.dg/strub_disp1.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fdump-ipa-strub" }
> +--  { dg-require-effective-target strub }
>
>  -- Check that at-calls dispatching calls are transformed.
>
> diff --git a/gcc/testsuite/gnat.dg/strub_ind.adb b/gcc/testsuite/gnat.dg/strub_ind.adb
> index da56acaa957d2..613db69305e05 100644
> --- a/gcc/testsuite/gnat.dg/strub_ind.adb
> +++ b/gcc/testsuite/gnat.dg/strub_ind.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fstrub=strict" }
> +--  { dg-require-effective-target strub }
>
>  --  This is essentially the same test as strub_attr.adb,
>  --  but applying attributes to access types as well.
> diff --git a/gcc/testsuite/gnat.dg/strub_ind1.adb b/gcc/testsuite/gnat.dg/strub_ind1.adb
> index 825e395e6819c..245b0a830f691 100644
> --- a/gcc/testsuite/gnat.dg/strub_ind1.adb
> +++ b/gcc/testsuite/gnat.dg/strub_ind1.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fstrub=strict -fdump-ipa-strubm" }
> +--  { dg-require-effective-target strub }
>
>  --  This is essentially the same test as strub_attr.adb,
>  --  but with an explicit conversion.
> diff --git a/gcc/testsuite/gnat.dg/strub_ind2.adb b/gcc/testsuite/gnat.dg/strub_ind2.adb
> index e918b39263117..b9bfe50e9296e 100644
> --- a/gcc/testsuite/gnat.dg/strub_ind2.adb
> +++ b/gcc/testsuite/gnat.dg/strub_ind2.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fstrub=strict" }
> +--  { dg-require-effective-target strub }
>
>  --  This is essentially the same test as strub_attr.adb,
>  --  but with an explicit conversion.
> diff --git a/gcc/testsuite/gnat.dg/strub_intf.adb b/gcc/testsuite/gnat.dg/strub_intf.adb
> index 8f0212a75866f..f43854705d073 100644
> --- a/gcc/testsuite/gnat.dg/strub_intf.adb
> +++ b/gcc/testsuite/gnat.dg/strub_intf.adb
> @@ -1,4 +1,5 @@
>  --  { dg-do compile }
> +--  { dg-require-effective-target strub }
>
>  --  Check that strub mode mismatches between overrider and overridden
>  --  subprograms are reported.
> diff --git a/gcc/testsuite/gnat.dg/strub_intf1.adb b/gcc/testsuite/gnat.dg/strub_intf1.adb
> index bf77321cef790..7a38a4c49ba8d 100644
> --- a/gcc/testsuite/gnat.dg/strub_intf1.adb
> +++ b/gcc/testsuite/gnat.dg/strub_intf1.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fdump-ipa-strub" }
> +--  { dg-require-effective-target strub }
>
>  -- Check that at-calls dispatching calls to interfaces are transformed.
>
> diff --git a/gcc/testsuite/gnat.dg/strub_intf2.adb b/gcc/testsuite/gnat.dg/strub_intf2.adb
> index e8880dbc43730..7992b7344fb87 100644
> --- a/gcc/testsuite/gnat.dg/strub_intf2.adb
> +++ b/gcc/testsuite/gnat.dg/strub_intf2.adb
> @@ -1,4 +1,5 @@
>  --  { dg-do compile }
> +--  { dg-require-effective-target strub }
>
>  --  Check that strub mode mismatches between overrider and overridden
>  --  subprograms are reported even when the overriders for an
> diff --git a/gcc/testsuite/gnat.dg/strub_renm.adb b/gcc/testsuite/gnat.dg/strub_renm.adb
> index 217367e712d82..abfb120b51468 100644
> --- a/gcc/testsuite/gnat.dg/strub_renm.adb
> +++ b/gcc/testsuite/gnat.dg/strub_renm.adb
> @@ -1,4 +1,5 @@
>  --  { dg-do compile }
> +--  { dg-require-effective-target strub }
>
>  procedure Strub_Renm is
>     procedure P (X : Integer);
> diff --git a/gcc/testsuite/gnat.dg/strub_renm1.adb b/gcc/testsuite/gnat.dg/strub_renm1.adb
> index a11adbfb5a9d6..68d3230b5356c 100644
> --- a/gcc/testsuite/gnat.dg/strub_renm1.adb
> +++ b/gcc/testsuite/gnat.dg/strub_renm1.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fstrub=relaxed -fdump-ipa-strub" }
> +--  { dg-require-effective-target strub }
>
>  procedure Strub_Renm1 is
>     V : Integer := 0;
> diff --git a/gcc/testsuite/gnat.dg/strub_renm2.adb b/gcc/testsuite/gnat.dg/strub_renm2.adb
> index c488c20826fdb..3cb81ea03f763 100644
> --- a/gcc/testsuite/gnat.dg/strub_renm2.adb
> +++ b/gcc/testsuite/gnat.dg/strub_renm2.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fstrub=strict -fdump-ipa-strub" }
> +--  { dg-require-effective-target strub }
>
>  procedure Strub_Renm2 is
>     V : Integer := 0;
> diff --git a/gcc/testsuite/gnat.dg/strub_var.adb b/gcc/testsuite/gnat.dg/strub_var.adb
> index 3d158de28031f..7c6affa06d4ab 100644
> --- a/gcc/testsuite/gnat.dg/strub_var.adb
> +++ b/gcc/testsuite/gnat.dg/strub_var.adb
> @@ -1,5 +1,6 @@
>  --  { dg-do compile }
>  --  { dg-options "-fstrub=strict -fdump-ipa-strubm" }
> +--  { dg-require-effective-target strub }
>
>  -- We don't read from the automatic variable, but being an automatic
>  --  variable, its presence should be enough for the procedure to get
> diff --git a/gcc/testsuite/gnat.dg/strub_var1.adb b/gcc/testsuite/gnat.dg/strub_var1.adb
> index 6a504e09198b6..64b7e65fe9b0f 100644
> --- a/gcc/testsuite/gnat.dg/strub_var1.adb
> +++ b/gcc/testsuite/gnat.dg/strub_var1.adb
> @@ -1,4 +1,5 @@
>  --  { dg-do compile }
> +--  { dg-require-effective-target strub }
>
>  with Strub_Attr;
>  procedure Strub_Var1 is
> diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
> index 3fcce6be49d6f..40a60c198cfe8 100644
> --- a/gcc/testsuite/lib/target-supports.exp
> +++ b/gcc/testsuite/lib/target-supports.exp
> @@ -1302,6 +1302,13 @@ proc check_stack_check_available { stack_kind } {
>      } "$stack_opt"]
>  }
>
> +# Return 1 if the target supports stack scrubbing.
> +proc check_effective_target_strub {} {
> +    return [check_no_compiler_messages strub assembly {
> +       void __attribute__ ((__strub__)) fn (void) {}
> +    } ""]
> +}
> +
>  # Return 1 if compilation with -freorder-blocks-and-partition is error-free
>  # for trivial code, 0 otherwise.  As some targets (ARM for example) only
>  # warn when -fprofile-use is also supplied we test that combination too.
> diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
> index d8163c5af9903..3f77283490ef6 100644
> --- a/libgcc/Makefile.in
> +++ b/libgcc/Makefile.in
> @@ -434,7 +434,7 @@ LIB2ADD += enable-execute-stack.c
>  LIB2ADD += $(srcdir)/hardcfr.c
>
>  # Stack scrubbing infrastructure.
> -LIB2ADD += $(srcdir)/strub.c
> +@HAVE_STRUB_SUPPORT@LIB2ADD += $(srcdir)/strub.c
>
>  # While emutls.c has nothing to do with EH, it is in LIB2ADDEH*
>  # instead of LIB2ADD because that's the way to be sure on some targets
> diff --git a/libgcc/configure b/libgcc/configure
> index cf149209652e3..567158955a329 100755
> --- a/libgcc/configure
> +++ b/libgcc/configure
> @@ -593,6 +593,7 @@ asm_hidden_op
>  extra_parts
>  cpu_type
>  get_gcc_base_ver
> +HAVE_STRUB_SUPPORT
>  thread_header
>  tm_defines
>  tm_file
> @@ -5702,6 +5703,31 @@ esac
>
>
>
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strub support" >&5
> +$as_echo_n "checking for strub support... " >&6; }
> +if ${libgcc_cv_strub_support+:} false; then :
> +  $as_echo_n "(cached) " >&6
> +else
> +  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> +/* end confdefs.h.  */
> +void __attribute__ ((__strub__)) fn (void) {}
> +_ACEOF
> +if ac_fn_c_try_compile "$LINENO"; then :
> +  libgcc_cv_strub_support=yes
> +else
> +  libgcc_cv_strub_support=no
> +fi
> +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
> +fi
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_strub_support" >&5
> +$as_echo "$libgcc_cv_strub_support" >&6; }
> +if test "x$libgcc_cv_strub_support" != xno; then
> +  HAVE_STRUB_SUPPORT=
> +else
> +  HAVE_STRUB_SUPPORT='# '
> +fi
> +
> +
>  # Determine what GCC version number to use in filesystem paths.
>
>    get_gcc_base_ver="cat"
> diff --git a/libgcc/configure.ac b/libgcc/configure.ac
> index 2fc9d5d7c93e9..9c0e415501a80 100644
> --- a/libgcc/configure.ac
> +++ b/libgcc/configure.ac
> @@ -694,6 +694,19 @@ AC_SUBST(tm_defines)
>  # Map from thread model to thread header.
>  GCC_AC_THREAD_HEADER([$target_thread_file])
>
> +AC_CACHE_CHECK([for strub support],
> +  [libgcc_cv_strub_support],
> +  [AC_COMPILE_IFELSE(
> +    [AC_LANG_SOURCE([void __attribute__ ((__strub__)) fn (void) {}])],
> +    [libgcc_cv_strub_support=yes],
> +    [libgcc_cv_strub_support=no])])
> +if test "x$libgcc_cv_strub_support" != xno; then
> +  HAVE_STRUB_SUPPORT=
> +else
> +  HAVE_STRUB_SUPPORT='# '
> +fi
> +AC_SUBST(HAVE_STRUB_SUPPORT)
> +
>  # Determine what GCC version number to use in filesystem paths.
>  GCC_BASE_VER
>
>
>
> --
> Alexandre Oliva, happy hacker            https://FSFLA.org/blogs/lxo/
>    Free Software Activist                   GNU Toolchain Engineer
> More tolerance and less prejudice are key for inclusion and diversity
> Excluding neuro-others for not behaving ""normal"" is *not* inclusive

  reply	other threads:[~2023-12-07  7:28 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <ormtqpsbuc.fsf@lxoliva.fsfla.org>
2021-09-09  7:11 ` [PATCH] strub: machine-independent stack scrubbing Alexandre Oliva
2022-07-29  6:16   ` [PATCH v2 00/10] Introduce " Alexandre Oliva
2022-07-29  6:24     ` [PATCH v2 01/10] Introduce strub: documentation, and new command-line options Alexandre Oliva
2022-07-29  6:25     ` [PATCH v2 02/10] Introduce strub: torture tests for C and C++ Alexandre Oliva
2022-08-09 13:34       ` Alexandre Oliva
2022-07-29  6:25     ` [PATCH v2 03/10] Introduce strub: non-torture " Alexandre Oliva
2022-07-29  6:26     ` [PATCH v2 04/10] Introduce strub: tests for C++ and Ada Alexandre Oliva
2022-07-29  6:26     ` [PATCH v2 05/10] Introduce strub: builtins and runtime Alexandre Oliva
2022-07-29  6:27     ` [PATCH v2 06/10] Introduce strub: attributes Alexandre Oliva
2022-07-29  6:28     ` [PATCH v2 07/10] Introduce strub: infrastructure interfaces and adjustments Alexandre Oliva
2022-07-29  6:28     ` [PATCH v2 08/10] Introduce strub: strub modes Alexandre Oliva
2022-07-29  6:30     ` [PATCH v2 09/10] Introduce strub: strubm (mode assignment) pass Alexandre Oliva
2022-07-29  6:34     ` [PATCH v2 10/10] Introduce strub: strub pass Alexandre Oliva
2022-07-29  6:36     ` [PATCH v2 00/10] Introduce strub: machine-independent stack scrubbing Alexandre Oliva
2022-10-10  8:48       ` Richard Biener
2022-10-11 11:57         ` Alexandre Oliva
2022-10-11 11:59           ` Richard Biener
2022-10-11 13:33             ` Alexandre Oliva
2022-10-13 11:38               ` Richard Biener
2022-10-13 13:15                 ` Alexandre Oliva
2023-06-16  6:09     ` [PATCH v3] " Alexandre Oliva
2023-06-27 21:28       ` Qing Zhao
2023-06-28  8:20         ` Alexandre Oliva
2023-10-20  6:03       ` [PATCH v4] " Alexandre Oliva
2023-10-26  6:15         ` Alexandre Oliva
2023-11-20 12:40           ` Alexandre Oliva
2023-11-22 14:14             ` Richard Biener
2023-11-23 10:56               ` Alexandre Oliva
2023-11-23 12:05                 ` Richard Biener
2023-11-29  8:53                   ` Alexandre Oliva
2023-11-29 12:48                     ` Richard Biener
2023-11-30  4:13                       ` Alexandre Oliva
2023-11-30 12:00                         ` Richard Biener
2023-12-02 17:56                           ` [PATCH v5] " Alexandre Oliva
2023-12-05  6:25                             ` Alexandre Oliva
2023-12-06  1:04                               ` Alexandre Oliva
2023-12-05  9:01                             ` Richard Biener
2023-12-06  8:36                             ` Causes to nvptx bootstrap fail: " Tobias Burnus
2023-12-06 11:32                               ` Thomas Schwinge
2023-12-06 22:12                                 ` Alexandre Oliva
2023-12-07  3:33                                   ` [PATCH] strub: enable conditional support Alexandre Oliva
2023-12-07  7:24                                     ` Richard Biener [this message]
2023-12-07 16:44                                     ` Thomas Schwinge
2023-12-07 17:52                                       ` [PATCH] Alexandre Oliva
2023-12-08  6:46                                         ` [PATCH] Richard Biener
2023-12-08  9:33                                         ` [PATCH] strub: skip emutls after strubm errors Thomas Schwinge
2023-12-10  9:16                                           ` FX Coudert
2023-12-07  7:21                                   ` Causes to nvptx bootstrap fail: [PATCH v5] Introduce strub: machine-independent stack scrubbing Richard Biener
2023-12-06 10:22                             ` Jan Hubicka
2023-12-07 21:19                               ` Alexandre Oliva
2023-12-07 21:39                               ` Alexandre Oliva
2023-12-09  2:08                                 ` [PATCH] strub: add note on attribute access Alexandre Oliva
2023-12-11  7:26                                   ` Richard Biener
2023-12-12 14:21                                   ` Jan Hubicka
2023-12-11  8:40                             ` [PATCH] testsuite: Disable -fstack-protector* for some strub tests Jakub Jelinek
2023-12-11  8:59                               ` Richard Biener
2023-12-20  8:15                           ` [PATCH FYI] www: new AdaCore-contributed hardening features in gcc 13 and 14 Alexandre Oliva
2023-11-30  5:04                       ` [PATCH v4] Introduce strub: machine-independent stack scrubbing Alexandre Oliva
2023-11-30 11:56                         ` Richard Biener

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=CAFiYyc3vw5EQGgXUq3hUyG-MocrSVjGrdCh+pp6UQ-x5ER5A3g@mail.gmail.com \
    --to=richard.guenther@gmail.com \
    --cc=craig.blackmore@embecosm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=graham.markall@embecosm.com \
    --cc=hubicka@ucw.cz \
    --cc=jakub@redhat.com \
    --cc=jeffreyalaw@gmail.com \
    --cc=jeremy.bennett@embecosm.com \
    --cc=mjambor@suse.cz \
    --cc=oliva@adacore.com \
    --cc=tdevries@suse.de \
    --cc=thomas@codesourcery.com \
    --cc=tobias@codesourcery.com \
    --cc=wilson@tuliptree.org \
    /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).