From 33be24d77d3d8f0c992eb344ce63f78e14cf753d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 19 Feb 2021 12:14:39 +0100 Subject: [PATCH] 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: [count: 0]: : S::~S (&s); and [count: 0]: : resx 1 where is landing pad and 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 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. (cherry picked from commit 37bde2f87267908a93c07856317a28827f8284f7) --- gcc/testsuite/g++.dg/opt/pr99034.C | 23 +++++++++++++++++++++++ gcc/tree-cfg.c | 12 +++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr99034.C diff --git a/gcc/testsuite/g++.dg/opt/pr99034.C b/gcc/testsuite/g++.dg/opt/pr99034.C new file mode 100644 index 000000000000..d791a14b136a --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr99034.C @@ -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); +} diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index f2f2e4803303..1af59fc6fe9a 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -2133,7 +2133,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 (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) -- 2.47.2