[3/3] tree-cfg: check placement of returns_twice calls

Message ID 20220114182047.6270-4-amonakov@ispras.ru
State New
Headers show
Series
  • [1/3] tree-ssa-sink: do not sink to in front of setjmp
Related show

Commit Message

Jason Merrill via Gcc-patches Jan. 14, 2022, 6:20 p.m.
When a returns_twice call has an associated abnormal edge, the edge
corresponds to the "second return" from the call. It wouldn't make sense
if any executable statements appeared between the call and the
destination of the edge (they wouldn't be re-executed upon the "second
return"), so verify that.

gcc/ChangeLog:

	* tree-cfg.c (gimple_verify_flow_info): Check placement of
	returns_twice calls.
---
 gcc/tree-cfg.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

-- 
2.33.1

Comments

Jason Merrill via Gcc-patches Jan. 17, 2022, 8:12 a.m. | #1
On Fri, Jan 14, 2022 at 7:21 PM Alexander Monakov <amonakov@ispras.ru> wrote:
>

> When a returns_twice call has an associated abnormal edge, the edge

> corresponds to the "second return" from the call. It wouldn't make sense

> if any executable statements appeared between the call and the

> destination of the edge (they wouldn't be re-executed upon the "second

> return"), so verify that.


OK for next stage1.

Thanks,
Richard.

> gcc/ChangeLog:

>

>         * tree-cfg.c (gimple_verify_flow_info): Check placement of

>         returns_twice calls.

> ---

>  gcc/tree-cfg.c | 33 +++++++++++++++++++++++++++++++++

>  1 file changed, 33 insertions(+)

>

> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c

> index a99f1acb4..70bd31d3d 100644

> --- a/gcc/tree-cfg.c

> +++ b/gcc/tree-cfg.c

> @@ -5644,6 +5644,7 @@ gimple_verify_flow_info (void)

>         }

>

>        /* Verify that body of basic block BB is free of control flow.  */

> +      bool seen_nondebug_stmt = false;

>        for (; !gsi_end_p (gsi); gsi_next (&gsi))

>         {

>           gimple *stmt = gsi_stmt (gsi);

> @@ -5664,6 +5665,38 @@ gimple_verify_flow_info (void)

>                      gimple_label_label (label_stmt), bb->index);

>               err = 1;

>             }

> +

> +         /* Check that no statements appear between a returns_twice call

> +            and its associated abnormal edge.  */

> +         if (gimple_code (stmt) == GIMPLE_CALL

> +             && gimple_call_flags (stmt) & ECF_RETURNS_TWICE)

> +           {

> +             const char *misplaced = NULL;

> +             /* TM is an exception: it points abnormal edges just after the

> +                call that starts a transaction, i.e. it must end the BB.  */

> +             if (gimple_call_builtin_p (stmt, BUILT_IN_TM_START))

> +               {

> +                 if (single_succ_p (bb)

> +                     && bb_has_abnormal_pred (single_succ (bb))

> +                     && !gsi_one_nondebug_before_end_p (gsi))

> +                   misplaced = "not last";

> +               }

> +             else

> +               {

> +                 if (seen_nondebug_stmt

> +                     && bb_has_abnormal_pred (bb))

> +                   misplaced = "not first";

> +               }

> +             if (misplaced)

> +               {

> +                 error ("returns_twice call is %s in basic block %d",

> +                        misplaced, bb->index);

> +                 print_gimple_stmt (stderr, stmt, 0, TDF_SLIM);

> +                 err = 1;

> +               }

> +           }

> +         if (!is_gimple_debug (stmt))

> +           seen_nondebug_stmt = true;

>         }

>

>        gsi = gsi_last_nondebug_bb (bb);

> --

> 2.33.1

>

Patch

diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index a99f1acb4..70bd31d3d 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -5644,6 +5644,7 @@  gimple_verify_flow_info (void)
 	}
 
       /* Verify that body of basic block BB is free of control flow.  */
+      bool seen_nondebug_stmt = false;
       for (; !gsi_end_p (gsi); gsi_next (&gsi))
 	{
 	  gimple *stmt = gsi_stmt (gsi);
@@ -5664,6 +5665,38 @@  gimple_verify_flow_info (void)
 		     gimple_label_label (label_stmt), bb->index);
 	      err = 1;
 	    }
+
+	  /* Check that no statements appear between a returns_twice call
+	     and its associated abnormal edge.  */
+	  if (gimple_code (stmt) == GIMPLE_CALL
+	      && gimple_call_flags (stmt) & ECF_RETURNS_TWICE)
+	    {
+	      const char *misplaced = NULL;
+	      /* TM is an exception: it points abnormal edges just after the
+		 call that starts a transaction, i.e. it must end the BB.  */
+	      if (gimple_call_builtin_p (stmt, BUILT_IN_TM_START))
+		{
+		  if (single_succ_p (bb)
+		      && bb_has_abnormal_pred (single_succ (bb))
+		      && !gsi_one_nondebug_before_end_p (gsi))
+		    misplaced = "not last";
+		}
+	      else
+		{
+		  if (seen_nondebug_stmt
+		      && bb_has_abnormal_pred (bb))
+		    misplaced = "not first";
+		}
+	      if (misplaced)
+		{
+		  error ("returns_twice call is %s in basic block %d",
+			 misplaced, bb->index);
+		  print_gimple_stmt (stderr, stmt, 0, TDF_SLIM);
+		  err = 1;
+		}
+	    }
+	  if (!is_gimple_debug (stmt))
+	    seen_nondebug_stmt = true;
 	}
 
       gsi = gsi_last_nondebug_bb (bb);