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
}
+/* 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 *
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;
}
/* 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 ();
/* 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);