[gcc(refs/vendors/redhat/heads/gcc-10-branch)] gimplify: Fix -fcompare-debug differences caused by gimplify_body [PR94281]

Jakub Jelinek jakub@gcc.gnu.org
Sat Mar 28 09:40:57 GMT 2020


https://gcc.gnu.org/g:10ea09ee846eaa345161a3a3f519b3780d6101fa

commit 10ea09ee846eaa345161a3a3f519b3780d6101fa
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Mar 26 10:10:21 2020 +0100

    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.

Diff:
---
 gcc/ChangeLog                        | 11 +++++++++++
 gcc/gimple.h                         | 14 +++++++++++++-
 gcc/gimplify.c                       | 35 ++++++++++++++++++++++++++++++++---
 gcc/testsuite/ChangeLog              |  3 +++
 gcc/testsuite/g++.dg/debug/pr94281.C | 11 +++++++++++
 5 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 180c92f76f7..8005e1a91f7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 0420d6d2251..305d98f5438 100644
--- a/gcc/gimple.h
+++ b/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;
 }
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index ef531f3fd7b..787435c38cd 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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);
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6091bcc1f05..ea31955bbe2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
 
diff --git a/gcc/testsuite/g++.dg/debug/pr94281.C b/gcc/testsuite/g++.dg/debug/pr94281.C
new file mode 100644
index 00000000000..06386917423
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/pr94281.C
@@ -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()
+{
+  ;
+}


More information about the Gcc-cvs mailing list