diff mbox series

tree-cfg: Fix up gimple_merge_blocks FORCED_LABEL handling [PR99034]

Message ID 20210219100445.GO4020736@tucnak
State New
Headers show
Series tree-cfg: Fix up gimple_merge_blocks FORCED_LABEL handling [PR99034] | expand

Commit Message

Jakub Jelinek Feb. 19, 2021, 10:04 a.m. UTC
Hi!

The verifiers require that DECL_NONLOCAL or EH_LANDING_PAD_NR
labels are always the first label if there is more than one label.

When merging blocks, we don't honor that though.
On the following testcase, we try to merge blocks:
<bb 13> [count: 0]:
<L2>:
S::~S (&s);

and
<bb 15> [count: 0]:
<L0>:
resx 1

where <L2> is landing pad and <L0> is FORCED_LABEL.  And the code puts
the FORCED_LABEL before the landing pad label, violating the verification
requirements.

The following patch fixes it by moving the FORCED_LABEL after the
DECL_NONLOCAL or EH_LANDING_PAD_NR label if it is the first label.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2021-02-19  Jakub Jelinek  <jakub@redhat.com>

	PR ipa/99034
	* tree-cfg.c (gimple_merge_blocks): If bb a starts with eh landing
	pad or non-local label, put FORCED_LABELs from bb b after that label
	rather than before it.

	* g++.dg/opt/pr99034.C: New test.


	Jakub

Comments

Richard Biener Feb. 19, 2021, 10:49 a.m. UTC | #1
On Fri, 19 Feb 2021, Jakub Jelinek wrote:

> Hi!
> 
> The verifiers require that DECL_NONLOCAL or EH_LANDING_PAD_NR
> labels are always the first label if there is more than one label.
> 
> When merging blocks, we don't honor that though.
> On the following testcase, we try to merge blocks:
> <bb 13> [count: 0]:
> <L2>:
> S::~S (&s);
> 
> and
> <bb 15> [count: 0]:
> <L0>:
> resx 1
> 
> where <L2> is landing pad and <L0> is FORCED_LABEL.  And the code puts
> the FORCED_LABEL before the landing pad label, violating the verification
> requirements.
> 
> The following patch fixes it by moving the FORCED_LABEL after the
> DECL_NONLOCAL or EH_LANDING_PAD_NR label if it is the first label.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Huh, wasn't aware of such.  OK.

Richard.

> 2021-02-19  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR ipa/99034
> 	* tree-cfg.c (gimple_merge_blocks): If bb a starts with eh landing
> 	pad or non-local label, put FORCED_LABELs from bb b after that label
> 	rather than before it.
> 
> 	* g++.dg/opt/pr99034.C: New test.
> 
> --- gcc/tree-cfg.c.jj	2021-02-18 16:20:57.053826485 +0100
> +++ gcc/tree-cfg.c	2021-02-18 19:15:48.436526437 +0100
> @@ -2124,7 +2124,17 @@ gimple_merge_blocks (basic_block a, basi
>  	  if (FORCED_LABEL (label))
>  	    {
>  	      gimple_stmt_iterator dest_gsi = gsi_start_bb (a);
> -	      gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT);
> +	      tree first_label = NULL_TREE;
> +	      if (!gsi_end_p (dest_gsi))
> +		if (glabel *first_label_stmt
> +		    = dyn_cast <glabel *> (gsi_stmt (dest_gsi)))
> +		  first_label = gimple_label_label (first_label_stmt);
> +	      if (first_label
> +		  && (DECL_NONLOCAL (first_label)
> +		      || EH_LANDING_PAD_NR (first_label) != 0))
> +		gsi_insert_after (&dest_gsi, stmt, GSI_NEW_STMT);
> +	      else
> +		gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT);
>  	    }
>  	  /* Other user labels keep around in a form of a debug stmt.  */
>  	  else if (!DECL_ARTIFICIAL (label) && MAY_HAVE_DEBUG_BIND_STMTS)
> --- gcc/testsuite/g++.dg/opt/pr99034.C.jj	2021-02-18 19:05:27.205347304 +0100
> +++ gcc/testsuite/g++.dg/opt/pr99034.C	2021-02-18 19:07:32.352973196 +0100
> @@ -0,0 +1,23 @@
> +// PR ipa/99034
> +// { dg-do compile }
> +// { dg-options "-O2" }
> +
> +void *b[5];
> +void foo (void);
> +struct S { ~S (); };
> +
> +static inline void
> +__attribute__((always_inline))
> +bar (int d)
> +{
> +  S s;
> +  while (d)
> +    foo ();
> +}
> +
> +void
> +baz (void)
> +{
> +  bar (2);
> +  __builtin_setjmp (b);
> +}
> 
> 	Jakub
> 
>
diff mbox series

Patch

--- gcc/tree-cfg.c.jj	2021-02-18 16:20:57.053826485 +0100
+++ gcc/tree-cfg.c	2021-02-18 19:15:48.436526437 +0100
@@ -2124,7 +2124,17 @@  gimple_merge_blocks (basic_block a, basi
 	  if (FORCED_LABEL (label))
 	    {
 	      gimple_stmt_iterator dest_gsi = gsi_start_bb (a);
-	      gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT);
+	      tree first_label = NULL_TREE;
+	      if (!gsi_end_p (dest_gsi))
+		if (glabel *first_label_stmt
+		    = dyn_cast <glabel *> (gsi_stmt (dest_gsi)))
+		  first_label = gimple_label_label (first_label_stmt);
+	      if (first_label
+		  && (DECL_NONLOCAL (first_label)
+		      || EH_LANDING_PAD_NR (first_label) != 0))
+		gsi_insert_after (&dest_gsi, stmt, GSI_NEW_STMT);
+	      else
+		gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT);
 	    }
 	  /* Other user labels keep around in a form of a debug stmt.  */
 	  else if (!DECL_ARTIFICIAL (label) && MAY_HAVE_DEBUG_BIND_STMTS)
--- gcc/testsuite/g++.dg/opt/pr99034.C.jj	2021-02-18 19:05:27.205347304 +0100
+++ gcc/testsuite/g++.dg/opt/pr99034.C	2021-02-18 19:07:32.352973196 +0100
@@ -0,0 +1,23 @@ 
+// PR ipa/99034
+// { dg-do compile }
+// { dg-options "-O2" }
+
+void *b[5];
+void foo (void);
+struct S { ~S (); };
+
+static inline void
+__attribute__((always_inline))
+bar (int d)
+{
+  S s;
+  while (d)
+    foo ();
+}
+
+void
+baz (void)
+{
+  bar (2);
+  __builtin_setjmp (b);
+}