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

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.

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.
This commit is contained in:
Jakub Jelinek 2021-02-19 12:14:39 +01:00
parent 9d449189ee
commit 37bde2f872
2 changed files with 34 additions and 1 deletions

View File

@ -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);
}

View File

@ -2124,7 +2124,17 @@ gimple_merge_blocks (basic_block a, basic_block b)
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)