gimplify: Fix -fcompare-debug differences caused by gimplify_body [PR94281]
The following testcase FAILs, because gimplify_body adds a GIMPLE_NOP only when there are no statements in the function and with -g there is a DEBUG_BEGIN_STMT, so it doesn't add it and due to -fno-tree-dce that never gets removed afterwards. Similarly, if the body seq after gimplification contains some DEBUG_BEGIN_STMTs plus a single gbind, then we could behave differently between -g0 and -g, by using that gbind as the body in the -g0 case and not in the -g case. This patch fixes that by ignoring DEBUG_BEGIN_STMTs (other debug stmts can't appear at this point yet thankfully) during decisions and if we pick the single gbind and there are DEBUG_BEGIN_STMTs next to it, it moves them into the gbind. While debugging this, I found also a bug in the gimple_seq_last_nondebug_stmt function, for a seq that has a single non-DEBUG_BEGIN_STMT statement followed by one or more DEBUG_BEGIN_STMTs it would return NULL rather than the first statement. 2020-03-26 Jakub Jelinek <jakub@redhat.com> PR debug/94281 * gimple.h (gimple_seq_first_nondebug_stmt): New function. (gimple_seq_last_nondebug_stmt): Don't return NULL if seq contains a single non-debug stmt followed by one or more debug stmts. * gimplify.c (gimplify_body): Use gimple_seq_first_nondebug_stmt instead of gimple_seq_first_stmt, use gimple_seq_first_nondebug_stmt and gimple_seq_last_nondebug_stmt instead of gimple_seq_first and gimple_seq_last to check if outer_stmt gbind could be reused and if yes and it is surrounded by any debug stmts, move them into the gbind body. * g++.dg/debug/pr94281.C: New test.
This commit is contained in:
parent
dab932d151
commit
10ea09ee84
5 changed files with 70 additions and 4 deletions
|
@ -1,5 +1,16 @@
|
|||
2020-03-26 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR debug/94281
|
||||
* gimple.h (gimple_seq_first_nondebug_stmt): New function.
|
||||
(gimple_seq_last_nondebug_stmt): Don't return NULL if seq contains
|
||||
a single non-debug stmt followed by one or more debug stmts.
|
||||
* gimplify.c (gimplify_body): Use gimple_seq_first_nondebug_stmt
|
||||
instead of gimple_seq_first_stmt, use gimple_seq_first_nondebug_stmt
|
||||
and gimple_seq_last_nondebug_stmt instead of gimple_seq_first and
|
||||
gimple_seq_last to check if outer_stmt gbind could be reused and
|
||||
if yes and it is surrounded by any debug stmts, move them into the
|
||||
gbind body.
|
||||
|
||||
PR rtl-optimization/92264
|
||||
* var-tracking.c (add_stores): Call cselib_set_value_sp_based even
|
||||
for sp based values in !frame_pointer_needed
|
||||
|
|
14
gcc/gimple.h
14
gcc/gimple.h
|
@ -4728,6 +4728,18 @@ is_gimple_debug (const gimple *gs)
|
|||
}
|
||||
|
||||
|
||||
/* Return the first nondebug statement in GIMPLE sequence S. */
|
||||
|
||||
static inline gimple *
|
||||
gimple_seq_first_nondebug_stmt (gimple_seq s)
|
||||
{
|
||||
gimple_seq_node n = gimple_seq_first (s);
|
||||
while (n && is_gimple_debug (n))
|
||||
n = n->next;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/* Return the last nondebug statement in GIMPLE sequence S. */
|
||||
|
||||
static inline gimple *
|
||||
|
@ -4737,7 +4749,7 @@ gimple_seq_last_nondebug_stmt (gimple_seq s)
|
|||
for (n = gimple_seq_last (s);
|
||||
n && is_gimple_debug (n);
|
||||
n = n->prev)
|
||||
if (n->prev == s)
|
||||
if (n == s)
|
||||
return NULL;
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -14849,7 +14849,7 @@ gimplify_body (tree fndecl, bool do_parms)
|
|||
/* Gimplify the function's body. */
|
||||
seq = NULL;
|
||||
gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
|
||||
outer_stmt = gimple_seq_first_stmt (seq);
|
||||
outer_stmt = gimple_seq_first_nondebug_stmt (seq);
|
||||
if (!outer_stmt)
|
||||
{
|
||||
outer_stmt = gimple_build_nop ();
|
||||
|
@ -14859,8 +14859,37 @@ gimplify_body (tree fndecl, bool do_parms)
|
|||
/* The body must contain exactly one statement, a GIMPLE_BIND. If this is
|
||||
not the case, wrap everything in a GIMPLE_BIND to make it so. */
|
||||
if (gimple_code (outer_stmt) == GIMPLE_BIND
|
||||
&& gimple_seq_first (seq) == gimple_seq_last (seq))
|
||||
outer_bind = as_a <gbind *> (outer_stmt);
|
||||
&& (gimple_seq_first_nondebug_stmt (seq)
|
||||
== gimple_seq_last_nondebug_stmt (seq)))
|
||||
{
|
||||
outer_bind = as_a <gbind *> (outer_stmt);
|
||||
if (gimple_seq_first_stmt (seq) != outer_stmt
|
||||
|| gimple_seq_last_stmt (seq) != outer_stmt)
|
||||
{
|
||||
/* If there are debug stmts before or after outer_stmt, move them
|
||||
inside of outer_bind body. */
|
||||
gimple_stmt_iterator gsi = gsi_for_stmt (outer_stmt, &seq);
|
||||
gimple_seq second_seq = NULL;
|
||||
if (gimple_seq_first_stmt (seq) != outer_stmt
|
||||
&& gimple_seq_last_stmt (seq) != outer_stmt)
|
||||
{
|
||||
second_seq = gsi_split_seq_after (gsi);
|
||||
gsi_remove (&gsi, false);
|
||||
}
|
||||
else if (gimple_seq_first_stmt (seq) != outer_stmt)
|
||||
gsi_remove (&gsi, false);
|
||||
else
|
||||
{
|
||||
gsi_remove (&gsi, false);
|
||||
second_seq = seq;
|
||||
seq = NULL;
|
||||
}
|
||||
gimple_seq_add_seq_without_update (&seq,
|
||||
gimple_bind_body (outer_bind));
|
||||
gimple_seq_add_seq_without_update (&seq, second_seq);
|
||||
gimple_bind_set_body (outer_bind, seq);
|
||||
}
|
||||
}
|
||||
else
|
||||
outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
2020-03-26 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR debug/94281
|
||||
* g++.dg/debug/pr94281.C: New test.
|
||||
|
||||
PR c++/81349
|
||||
* g++.dg/cpp1z/pr81349.C: New test.
|
||||
|
||||
|
|
11
gcc/testsuite/g++.dg/debug/pr94281.C
Normal file
11
gcc/testsuite/g++.dg/debug/pr94281.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// PR debug/94281
|
||||
// { dg-do compile }
|
||||
// { dg-options "-O1 -fno-tree-dce -fipa-icf -fno-tree-forwprop -fcompare-debug" }
|
||||
|
||||
void fn1()
|
||||
{
|
||||
}
|
||||
void fn2()
|
||||
{
|
||||
;
|
||||
}
|
Loading…
Add table
Reference in a new issue