Add fnspec attributes to cxa_* functions

Message ID YrRxxpA7WpvC+aPP@kam.mff.cuni.cz
State New
Headers
Series Add fnspec attributes to cxa_* functions |

Commit Message

Jan Hubicka June 23, 2022, 1:59 p.m. UTC
  Hi,
this patch adds fnspecs for cxa_* functions in except.cc.  Main goal is to make
modref to see proper side-effects of functions which may throw. So in general
we get
 - cxa_allocate_exception
    which gets the same annotations as malloc (since it is kind of same thing)
 - cxa_free_exception
    which gets the same annotations as free
 - cxa_throw which is marked as const except for first parameter which is believed
    that it makes it escape (which is necessary) and modify (which is not necessary
    but it would matter inly if we would like to do constant propagation across
    EH edges.

Honza
 
gcc/cp/ChangeLog:

2022-06-23  Jan Hubicka  <hubicka@ucw.cz>

	* except.cc (declare_library_fn_1): Add fnspec parameter.
	(declare_library_fn): Add fnspec parameter.
	(do_allocate_exception): Declare fnspecs.
	(do_free_exception): Declare fnspecs.
	(build_throw): Declare fnspecs.

gcc/testsuite/ChangeLog:

2022-06-23  Jan Hubicka  <hubicka@ucw.cz>

	* g++.dg/opt/eh6.C: New test.
	* g++.dg/tree-ssa/kill.C: New test.
  

Comments

Richard Biener June 24, 2022, 8:33 a.m. UTC | #1
> Am 23.06.2022 um 16:00 schrieb Jan Hubicka via Gcc-patches <gcc-patches@gcc.gnu.org>:
> 
> Hi,
> this patch adds fnspecs for cxa_* functions in except.cc.  Main goal is to make
> modref to see proper side-effects of functions which may throw. So in general
> we get
> - cxa_allocate_exception
>    which gets the same annotations as malloc (since it is kind of same thing)
> - cxa_free_exception
>    which gets the same annotations as free
> - cxa_throw which is marked as const except for first parameter which is believed
>    that it makes it escape (which is necessary) and modify (which is not necessary
>    but it would matter inly if we would like to do constant propagation across
>    EH edges.
> 

Looks OK to me, let’s see if Jason has any comments though.

Richard 

> Honza
> 
> gcc/cp/ChangeLog:
> 
> 2022-06-23  Jan Hubicka  <hubicka@ucw.cz>
> 
>    * except.cc (declare_library_fn_1): Add fnspec parameter.
>    (declare_library_fn): Add fnspec parameter.
>    (do_allocate_exception): Declare fnspecs.
>    (do_free_exception): Declare fnspecs.
>    (build_throw): Declare fnspecs.
> 
> gcc/testsuite/ChangeLog:
> 
> 2022-06-23  Jan Hubicka  <hubicka@ucw.cz>
> 
>    * g++.dg/opt/eh6.C: New test.
>    * g++.dg/tree-ssa/kill.C: New test.
> 
> diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
> index da0a65c613d..bb9a5aee6da 100644
> --- a/gcc/cp/except.cc
> +++ b/gcc/cp/except.cc
> @@ -133,13 +133,14 @@ build_exc_ptr (void)
> }
> 
> /* Declare an exception ABI entry point called NAME.
> -   ECF are the library flags, RTYPE the return type and ARGS[NARGS]
> +   ECF are the library flags, FNSPEC is the attr "fn spec" string (or NULL),
> +   RTYPE the return type and ARGS[NARGS]
>    the parameter types.  We return the DECL -- which might be one
>    found via the symbol table pushing, if the user already declared
>    it.  If we pushed a new decl, the user will see it.  */
> 
> static tree
> -declare_library_fn_1 (const char *name, int ecf,
> +declare_library_fn_1 (const char *name, int ecf, const char *fnspec,
>              tree rtype, int nargs, tree args[])
> {
>   tree ident = get_identifier (name);
> @@ -150,6 +151,14 @@ declare_library_fn_1 (const char *name, int ecf,
>   for (unsigned ix = nargs; ix--;)
>     arg_list = tree_cons (NULL_TREE, args[ix], arg_list);
>   tree fntype = build_function_type (rtype, arg_list);
> +  if (fnspec)
> +    {
> +      tree attr_args = build_tree_list (NULL_TREE,
> +                    build_string (strlen (fnspec), fnspec));
> +      tree attrs = tree_cons (get_identifier ("fn spec"),
> +                  attr_args, TYPE_ATTRIBUTES (fntype));
> +      fntype = build_type_attribute_variant (fntype, attrs);
> +    }
>   tree res = push_library_fn (ident, fntype, except, ecf);
> 
>   return res;
> @@ -157,7 +166,8 @@ declare_library_fn_1 (const char *name, int ecf,
> 
> /* Find or declare a function NAME, returning RTYPE, taking a single
>    parameter PTYPE, with an empty exception specification. ECF are the
> -   library fn flags.  If TM_ECF is non-zero, also find or create a
> +   library fn flags.  FNSPEC is the attr "fn spec" string (or NULL).
> +   If TM_ECF is non-zero, also find or create a
>    transaction variant and record it as a replacement, when flag_tm is
>    in effect.
> 
> @@ -167,9 +177,10 @@ declare_library_fn_1 (const char *name, int ecf,
> 
> static tree
> declare_library_fn (const char *name, tree rtype, tree ptype,
> -            int ecf, int tm_ecf)
> +            int ecf, int tm_ecf, const char *fnspec = NULL)
> {
> -  tree res = declare_library_fn_1 (name, ecf, rtype, ptype ? 1 : 0, &ptype);
> +  tree res = declare_library_fn_1 (name, ecf, fnspec,
> +                   rtype, ptype ? 1 : 0, &ptype);
>   if (res == error_mark_node)
>     return res;
> 
> @@ -177,7 +188,7 @@ declare_library_fn (const char *name, tree rtype, tree ptype,
>     {
>       char *tm_name = concat ("_ITM_", name + 2, NULL_TREE);
> 
> -      tree tm_fn = declare_library_fn_1 (tm_name, ecf | tm_ecf, rtype,
> +      tree tm_fn = declare_library_fn_1 (tm_name, ecf | tm_ecf, fnspec, rtype,
>                     ptype ? 1 : 0, &ptype);
>       free (tm_name);
>       if (tm_fn != error_mark_node)
> @@ -547,7 +558,8 @@ do_allocate_exception (tree type)
>     allocate_exception_fn
>       = declare_library_fn ("__cxa_allocate_exception",
>                ptr_type_node, size_type_node,
> -                ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE);
> +                ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE,
> +                "mc");
> 
>   return cp_build_function_call_nary (allocate_exception_fn,
>                      tf_warning_or_error,
> @@ -565,7 +577,8 @@ do_free_exception (tree ptr)
>     free_exception_fn
>       = declare_library_fn ("__cxa_free_exception",
>                void_type_node, ptr_type_node,
> -                ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE);
> +                ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE,
> +                ".co ");
> 
>   return cp_build_function_call_nary (free_exception_fn,
>                      tf_warning_or_error, ptr, NULL_TREE);
> @@ -653,11 +666,13 @@ build_throw (location_t loc, tree exp)
> 
>      throw_fn = declare_library_fn_1 ("__cxa_throw",
>                       ECF_NORETURN | ECF_COLD,
> +                       ".c. X X ",
>                       void_type_node, 3, args);
>      if (flag_tm && throw_fn != error_mark_node)
>        {
>          tree itm_fn = declare_library_fn_1 ("_ITM_cxa_throw",
>                          ECF_NORETURN | ECF_COLD,
> +                          ".c. X X ",
>                          void_type_node, 3, args);
>          if (itm_fn != error_mark_node)
>        {
> @@ -804,6 +819,7 @@ build_throw (location_t loc, tree exp)
>    {
>      rethrow_fn = declare_library_fn_1 ("__cxa_rethrow",
>                         ECF_NORETURN | ECF_COLD,
> +                         ".c",
>                         void_type_node, 0, NULL);
>      if (flag_tm && rethrow_fn != error_mark_node)
>        apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure"));
> diff --git a/gcc/testsuite/g++.dg/opt/eh6.C b/gcc/testsuite/g++.dg/opt/eh6.C
> new file mode 100644
> index 00000000000..fa891fb2559
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/opt/eh6.C
> @@ -0,0 +1,34 @@
> +// PR middle-end/106057
> +// { dg-do run }
> +// { dg-options "-O2" }
> +struct a {int a; int b;} a;
> +int b;
> +
> +__attribute__((noinline))
> +struct a maybethrow(int b)
> +{
> +        if (!b)
> +                throw(0);
> +        return {0,0};
> +}
> +
> +void
> +test(int b)
> +{
> +        a={1,1};
> +        a=maybethrow(b);
> +        a={0,0};
> +}
> +int
> +main()
> +{
> +        try {
> +                test(b);
> +        }
> +        catch(int) {
> +                if (!a.a)
> +                        __builtin_abort ();
> +        }
> +        return 0;
> +}
> +
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/kill.C b/gcc/testsuite/g++.dg/tree-ssa/kill.C
> new file mode 100644
> index 00000000000..bee58cd91fe
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/tree-ssa/kill.C
> @@ -0,0 +1,20 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -fdump-tree-modref1" } */
> +__attribute__ ((noinline))
> +void test(int a)
> +{
> +    if (a)
> +        throw (1);
> +}
> +int mem;
> +void link_error ();
> +int
> +main()
> +{
> +    mem = 0;
> +    test (0);
> +    if (mem)
> +        link_error ();
> +    return 0;
> +}
> +// { dg-final { scan-tree-dump-not "modref done with result: tracked." "modref1" } }
  
Jason Merrill June 24, 2022, 2:21 p.m. UTC | #2
On 6/23/22 09:59, Jan Hubicka via Gcc-patches wrote:

Note that your email subject line is missing "[PATCH]" and a component 
tag like "c++:".

> this patch adds fnspecs for cxa_* functions in except.cc.  Main goal is to make
> modref to see proper side-effects of functions which may throw. So in general
> we get
>   - cxa_allocate_exception
>      which gets the same annotations as malloc (since it is kind of same thing)
>   - cxa_free_exception
>      which gets the same annotations as free
>   - cxa_throw which is marked as const except for first parameter which is believed
>      that it makes it escape (which is necessary) and modify (which is not necessary
>      but it would matter inly if we would like to do constant propagation across
>      EH edges.

Makes sense.

> gcc/cp/ChangeLog:
> 
> 2022-06-23  Jan Hubicka  <hubicka@ucw.cz>
> 
> 	* except.cc (declare_library_fn_1): Add fnspec parameter.
> 	(declare_library_fn): Add fnspec parameter.
> 	(do_allocate_exception): Declare fnspecs.
> 	(do_free_exception): Declare fnspecs.
> 	(build_throw): Declare fnspecs.
> 
> gcc/testsuite/ChangeLog:
> 
> 2022-06-23  Jan Hubicka  <hubicka@ucw.cz>
> 
> 	* g++.dg/opt/eh6.C: New test.
> 	* g++.dg/tree-ssa/kill.C: New test.
> 
> diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
> index da0a65c613d..bb9a5aee6da 100644
> --- a/gcc/cp/except.cc
> +++ b/gcc/cp/except.cc
> @@ -133,13 +133,14 @@ build_exc_ptr (void)
>   }
>   
>   /* Declare an exception ABI entry point called NAME.
> -   ECF are the library flags, RTYPE the return type and ARGS[NARGS]
> +   ECF are the library flags, FNSPEC is the attr "fn spec" string (or NULL),

It might be helpful to refer to attr_fnspec or attr-fnspec.h, since 
that's where I found the documentation for that string?  OK either way.

> +   RTYPE the return type and ARGS[NARGS]
>      the parameter types.  We return the DECL -- which might be one
>      found via the symbol table pushing, if the user already declared
>      it.  If we pushed a new decl, the user will see it.  */
>   
>   static tree
> -declare_library_fn_1 (const char *name, int ecf,
> +declare_library_fn_1 (const char *name, int ecf, const char *fnspec,
>   		      tree rtype, int nargs, tree args[])
>   {
>     tree ident = get_identifier (name);
> @@ -150,6 +151,14 @@ declare_library_fn_1 (const char *name, int ecf,
>     for (unsigned ix = nargs; ix--;)
>       arg_list = tree_cons (NULL_TREE, args[ix], arg_list);
>     tree fntype = build_function_type (rtype, arg_list);
> +  if (fnspec)
> +    {
> +      tree attr_args = build_tree_list (NULL_TREE,
> +					build_string (strlen (fnspec), fnspec));
> +      tree attrs = tree_cons (get_identifier ("fn spec"),
> +			      attr_args, TYPE_ATTRIBUTES (fntype));
> +      fntype = build_type_attribute_variant (fntype, attrs);
> +    }
>     tree res = push_library_fn (ident, fntype, except, ecf);
>   
>     return res;
> @@ -157,7 +166,8 @@ declare_library_fn_1 (const char *name, int ecf,
>   
>   /* Find or declare a function NAME, returning RTYPE, taking a single
>      parameter PTYPE, with an empty exception specification. ECF are the
> -   library fn flags.  If TM_ECF is non-zero, also find or create a
> +   library fn flags.  FNSPEC is the attr "fn spec" string (or NULL).
> +   If TM_ECF is non-zero, also find or create a
>      transaction variant and record it as a replacement, when flag_tm is
>      in effect.
>   
> @@ -167,9 +177,10 @@ declare_library_fn_1 (const char *name, int ecf,
>   
>   static tree
>   declare_library_fn (const char *name, tree rtype, tree ptype,
> -		    int ecf, int tm_ecf)
> +		    int ecf, int tm_ecf, const char *fnspec = NULL)
>   {
> -  tree res = declare_library_fn_1 (name, ecf, rtype, ptype ? 1 : 0, &ptype);
> +  tree res = declare_library_fn_1 (name, ecf, fnspec,
> +				   rtype, ptype ? 1 : 0, &ptype);
>     if (res == error_mark_node)
>       return res;
>   
> @@ -177,7 +188,7 @@ declare_library_fn (const char *name, tree rtype, tree ptype,
>       {
>         char *tm_name = concat ("_ITM_", name + 2, NULL_TREE);
>   
> -      tree tm_fn = declare_library_fn_1 (tm_name, ecf | tm_ecf, rtype,
> +      tree tm_fn = declare_library_fn_1 (tm_name, ecf | tm_ecf, fnspec, rtype,
>   					 ptype ? 1 : 0, &ptype);
>         free (tm_name);
>         if (tm_fn != error_mark_node)
> @@ -547,7 +558,8 @@ do_allocate_exception (tree type)
>       allocate_exception_fn
>         = declare_library_fn ("__cxa_allocate_exception",
>   			    ptr_type_node, size_type_node,
> -			    ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE);
> +			    ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE,
> +			    "mc");
>   
>     return cp_build_function_call_nary (allocate_exception_fn,
>   				      tf_warning_or_error,
> @@ -565,7 +577,8 @@ do_free_exception (tree ptr)
>       free_exception_fn
>         = declare_library_fn ("__cxa_free_exception",
>   			    void_type_node, ptr_type_node,
> -			    ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE);
> +			    ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE,
> +			    ".co ");
>   
>     return cp_build_function_call_nary (free_exception_fn,
>   				      tf_warning_or_error, ptr, NULL_TREE);
> @@ -653,11 +666,13 @@ build_throw (location_t loc, tree exp)
>   
>   	  throw_fn = declare_library_fn_1 ("__cxa_throw",
>   					   ECF_NORETURN | ECF_COLD,
> +					   ".c. X X ",
>   					   void_type_node, 3, args);
>   	  if (flag_tm && throw_fn != error_mark_node)
>   	    {
>   	      tree itm_fn = declare_library_fn_1 ("_ITM_cxa_throw",
>   						  ECF_NORETURN | ECF_COLD,
> +						  ".c. X X ",
>   						  void_type_node, 3, args);
>   	      if (itm_fn != error_mark_node)
>   		{
> @@ -804,6 +819,7 @@ build_throw (location_t loc, tree exp)
>   	{
>   	  rethrow_fn = declare_library_fn_1 ("__cxa_rethrow",
>   					     ECF_NORETURN | ECF_COLD,
> +					     ".c",
>   					     void_type_node, 0, NULL);
>   	  if (flag_tm && rethrow_fn != error_mark_node)
>   	    apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure"));
> diff --git a/gcc/testsuite/g++.dg/opt/eh6.C b/gcc/testsuite/g++.dg/opt/eh6.C
> new file mode 100644
> index 00000000000..fa891fb2559
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/opt/eh6.C
> @@ -0,0 +1,34 @@
> +// PR middle-end/106057
> +// { dg-do run }
> +// { dg-options "-O2" }
> +struct a {int a; int b;} a;
> +int b;
> +
> +__attribute__((noinline))
> +struct a maybethrow(int b)
> +{
> +        if (!b)
> +                throw(0);
> +        return {0,0};
> +}
> +
> +void
> +test(int b)
> +{
> +        a={1,1};
> +        a=maybethrow(b);
> +        a={0,0};
> +}
> +int
> +main()
> +{
> +        try {
> +                test(b);
> +        }
> +        catch(int) {
> +                if (!a.a)
> +                        __builtin_abort ();
> +        }
> +        return 0;
> +}
> +
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/kill.C b/gcc/testsuite/g++.dg/tree-ssa/kill.C
> new file mode 100644
> index 00000000000..bee58cd91fe
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/tree-ssa/kill.C
> @@ -0,0 +1,20 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -fdump-tree-modref1" } */
> +__attribute__ ((noinline))
> +void test(int a)
> +{
> +	if (a)
> +		throw (1);
> +}
> +int mem;
> +void link_error ();
> +int
> +main()
> +{
> +	mem = 0;
> +	test (0);
> +	if (mem)
> +		link_error ();
> +	return 0;
> +}
> +// { dg-final { scan-tree-dump-not "modref done with result: tracked." "modref1" } }
>
  

Patch

diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
index da0a65c613d..bb9a5aee6da 100644
--- a/gcc/cp/except.cc
+++ b/gcc/cp/except.cc
@@ -133,13 +133,14 @@  build_exc_ptr (void)
 }
 
 /* Declare an exception ABI entry point called NAME.
-   ECF are the library flags, RTYPE the return type and ARGS[NARGS]
+   ECF are the library flags, FNSPEC is the attr "fn spec" string (or NULL),
+   RTYPE the return type and ARGS[NARGS]
    the parameter types.  We return the DECL -- which might be one
    found via the symbol table pushing, if the user already declared
    it.  If we pushed a new decl, the user will see it.  */
 
 static tree
-declare_library_fn_1 (const char *name, int ecf,
+declare_library_fn_1 (const char *name, int ecf, const char *fnspec,
 		      tree rtype, int nargs, tree args[])
 {
   tree ident = get_identifier (name);
@@ -150,6 +151,14 @@  declare_library_fn_1 (const char *name, int ecf,
   for (unsigned ix = nargs; ix--;)
     arg_list = tree_cons (NULL_TREE, args[ix], arg_list);
   tree fntype = build_function_type (rtype, arg_list);
+  if (fnspec)
+    {
+      tree attr_args = build_tree_list (NULL_TREE,
+					build_string (strlen (fnspec), fnspec));
+      tree attrs = tree_cons (get_identifier ("fn spec"),
+			      attr_args, TYPE_ATTRIBUTES (fntype));
+      fntype = build_type_attribute_variant (fntype, attrs);
+    }
   tree res = push_library_fn (ident, fntype, except, ecf);
 
   return res;
@@ -157,7 +166,8 @@  declare_library_fn_1 (const char *name, int ecf,
 
 /* Find or declare a function NAME, returning RTYPE, taking a single
    parameter PTYPE, with an empty exception specification. ECF are the
-   library fn flags.  If TM_ECF is non-zero, also find or create a
+   library fn flags.  FNSPEC is the attr "fn spec" string (or NULL).
+   If TM_ECF is non-zero, also find or create a
    transaction variant and record it as a replacement, when flag_tm is
    in effect.
 
@@ -167,9 +177,10 @@  declare_library_fn_1 (const char *name, int ecf,
 
 static tree
 declare_library_fn (const char *name, tree rtype, tree ptype,
-		    int ecf, int tm_ecf)
+		    int ecf, int tm_ecf, const char *fnspec = NULL)
 {
-  tree res = declare_library_fn_1 (name, ecf, rtype, ptype ? 1 : 0, &ptype);
+  tree res = declare_library_fn_1 (name, ecf, fnspec,
+				   rtype, ptype ? 1 : 0, &ptype);
   if (res == error_mark_node)
     return res;
 
@@ -177,7 +188,7 @@  declare_library_fn (const char *name, tree rtype, tree ptype,
     {
       char *tm_name = concat ("_ITM_", name + 2, NULL_TREE);
 
-      tree tm_fn = declare_library_fn_1 (tm_name, ecf | tm_ecf, rtype,
+      tree tm_fn = declare_library_fn_1 (tm_name, ecf | tm_ecf, fnspec, rtype,
 					 ptype ? 1 : 0, &ptype);
       free (tm_name);
       if (tm_fn != error_mark_node)
@@ -547,7 +558,8 @@  do_allocate_exception (tree type)
     allocate_exception_fn
       = declare_library_fn ("__cxa_allocate_exception",
 			    ptr_type_node, size_type_node,
-			    ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE);
+			    ECF_NOTHROW | ECF_MALLOC | ECF_COLD, ECF_TM_PURE,
+			    "mc");
 
   return cp_build_function_call_nary (allocate_exception_fn,
 				      tf_warning_or_error,
@@ -565,7 +577,8 @@  do_free_exception (tree ptr)
     free_exception_fn
       = declare_library_fn ("__cxa_free_exception",
 			    void_type_node, ptr_type_node,
-			    ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE);
+			    ECF_NOTHROW | ECF_LEAF, ECF_TM_PURE,
+			    ".co ");
 
   return cp_build_function_call_nary (free_exception_fn,
 				      tf_warning_or_error, ptr, NULL_TREE);
@@ -653,11 +666,13 @@  build_throw (location_t loc, tree exp)
 
 	  throw_fn = declare_library_fn_1 ("__cxa_throw",
 					   ECF_NORETURN | ECF_COLD,
+					   ".c. X X ",
 					   void_type_node, 3, args);
 	  if (flag_tm && throw_fn != error_mark_node)
 	    {
 	      tree itm_fn = declare_library_fn_1 ("_ITM_cxa_throw",
 						  ECF_NORETURN | ECF_COLD,
+						  ".c. X X ",
 						  void_type_node, 3, args);
 	      if (itm_fn != error_mark_node)
 		{
@@ -804,6 +819,7 @@  build_throw (location_t loc, tree exp)
 	{
 	  rethrow_fn = declare_library_fn_1 ("__cxa_rethrow",
 					     ECF_NORETURN | ECF_COLD,
+					     ".c",
 					     void_type_node, 0, NULL);
 	  if (flag_tm && rethrow_fn != error_mark_node)
 	    apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure"));
diff --git a/gcc/testsuite/g++.dg/opt/eh6.C b/gcc/testsuite/g++.dg/opt/eh6.C
new file mode 100644
index 00000000000..fa891fb2559
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/eh6.C
@@ -0,0 +1,34 @@ 
+// PR middle-end/106057
+// { dg-do run }
+// { dg-options "-O2" }
+struct a {int a; int b;} a;
+int b;
+
+__attribute__((noinline))
+struct a maybethrow(int b)
+{
+        if (!b)
+                throw(0);
+        return {0,0};
+}
+
+void
+test(int b)
+{
+        a={1,1};
+        a=maybethrow(b);
+        a={0,0};
+}
+int
+main()
+{
+        try {
+                test(b);
+        }
+        catch(int) {
+                if (!a.a)
+                        __builtin_abort ();
+        }
+        return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/tree-ssa/kill.C b/gcc/testsuite/g++.dg/tree-ssa/kill.C
new file mode 100644
index 00000000000..bee58cd91fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/kill.C
@@ -0,0 +1,20 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-modref1" } */
+__attribute__ ((noinline))
+void test(int a)
+{
+	if (a)
+		throw (1);
+}
+int mem;
+void link_error ();
+int
+main()
+{
+	mem = 0;
+	test (0);
+	if (mem)
+		link_error ();
+	return 0;
+}
+// { dg-final { scan-tree-dump-not "modref done with result: tracked." "modref1" } }