diff mbox

Fix -fcompare-debug issue in tree-cfgcleanup (PR tree-optimization/66688)

Message ID 20151214201139.GF18720@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Dec. 14, 2015, 8:11 p.m. UTC
Hi!

As the testcase used to show on ppc64le with slightly older trunk,
cleanup_control_flow_bb can be called on a bb with newly noreturn
call followed by debug stmts.  With -g0, cleanup_control_flow_bb
removes the fallthru edge, so we need to do it even if followed by debug
stmts.

This patch is one possible way to fix this, another one is attached to the
PR.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2015-12-14  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/66688
	* tree-cfgcleanup.c (cleanup_control_flow_bb): Handle
	noreturn call followed only by debug stmts by removing
	the debug stmts and handling it the same as if the noreturn
	call is the last stmt.

	* gcc.dg/pr66688.c: New test.


	Jakub

Comments

Richard Biener Dec. 14, 2015, 8:26 p.m. UTC | #1
On December 14, 2015 9:11:39 PM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>As the testcase used to show on ppc64le with slightly older trunk,
>cleanup_control_flow_bb can be called on a bb with newly noreturn
>call followed by debug stmts.  With -g0, cleanup_control_flow_bb
>removes the fallthru edge, so we need to do it even if followed by
>debug
>stmts.
>
>This patch is one possible way to fix this, another one is attached to
>the
>PR.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Thanks,
Richard.

>2015-12-14  Jakub Jelinek  <jakub@redhat.com>
>
>	PR tree-optimization/66688
>	* tree-cfgcleanup.c (cleanup_control_flow_bb): Handle
>	noreturn call followed only by debug stmts by removing
>	the debug stmts and handling it the same as if the noreturn
>	call is the last stmt.
>
>	* gcc.dg/pr66688.c: New test.
>
>--- gcc/tree-cfgcleanup.c.jj	2015-12-02 20:26:59.000000000 +0100
>+++ gcc/tree-cfgcleanup.c	2015-12-14 17:34:10.748487811 +0100
>@@ -186,7 +186,7 @@ cleanup_control_flow_bb (basic_block bb)
>      we need to prune cfg.  */
>   retval |= gimple_purge_dead_eh_edges (bb);
> 
>-  gsi = gsi_last_bb (bb);
>+  gsi = gsi_last_nondebug_bb (bb);
>   if (gsi_end_p (gsi))
>     return retval;
> 
>@@ -197,7 +197,10 @@ cleanup_control_flow_bb (basic_block bb)
> 
>   if (gimple_code (stmt) == GIMPLE_COND
>       || gimple_code (stmt) == GIMPLE_SWITCH)
>-    retval |= cleanup_control_expr_graph (bb, gsi);
>+    {
>+      gcc_checking_assert (gsi_stmt (gsi_last_bb (bb)) == stmt);
>+      retval |= cleanup_control_expr_graph (bb, gsi);
>+    }
>   else if (gimple_code (stmt) == GIMPLE_GOTO
> 	   && TREE_CODE (gimple_goto_dest (stmt)) == ADDR_EXPR
> 	   && (TREE_CODE (TREE_OPERAND (gimple_goto_dest (stmt), 0))
>@@ -210,6 +213,7 @@ cleanup_control_flow_bb (basic_block bb)
>       edge_iterator ei;
>       basic_block target_block;
> 
>+      gcc_checking_assert (gsi_stmt (gsi_last_bb (bb)) == stmt);
>       /* First look at all the outgoing edges.  Delete any outgoing
> 	 edges which do not go to the right block.  For the one
> 	 edge which goes to the right block, fix up its flags.  */
>@@ -242,9 +246,15 @@ cleanup_control_flow_bb (basic_block bb)
>   /* Check for indirect calls that have been turned into
>      noreturn calls.  */
>   else if (is_gimple_call (stmt)
>-           && gimple_call_noreturn_p (stmt)
>-           && remove_fallthru_edge (bb->succs))
>-    retval = true;
>+	   && gimple_call_noreturn_p (stmt))
>+    {
>+      /* If there are debug stmts after the noreturn call, remove them
>+	 now, they should be all unreachable anyway.  */
>+      for (gsi_next (&gsi); !gsi_end_p (gsi); )
>+	gsi_remove (&gsi, true);
>+      if (remove_fallthru_edge (bb->succs))
>+	retval = true;
>+    }
> 
>   return retval;
> }
>--- gcc/testsuite/gcc.dg/pr66688.c.jj	2015-12-14 14:51:43.652481658
>+0100
>+++ gcc/testsuite/gcc.dg/pr66688.c	2015-12-14 14:51:05.000000000 +0100
>@@ -0,0 +1,39 @@
>+/* PR tree-optimization/66688 */
>+/* { dg-do compile } */
>+/* { dg-options "-O2 -fno-reorder-blocks -fcompare-debug" } */
>+
>+struct fdt_header { unsigned magic; } *a;
>+
>+int d;
>+
>+int
>+__fswab32 (int p1)
>+{
>+  return __builtin_bswap32 (p1);
>+}
>+
>+void
>+fdt_set_magic (int p1)
>+{
>+  struct fdt_header *b = a;
>+  b->magic = __builtin_constant_p (p1) ? : __fswab32 (p1);
>+}
>+
>+int
>+_fdt_sw_check_header ()
>+{
>+  int c = ((struct fdt_header *) 1)->magic;
>+  if (c)
>+    return 1;
>+  return 0;
>+}
>+
>+int
>+fdt_finish ()
>+{
>+  if (_fdt_sw_check_header ())
>+    if (d)
>+      return 0;
>+  fdt_set_magic (0);
>+  return 0;
>+}
>
>	Jakub
diff mbox

Patch

--- gcc/tree-cfgcleanup.c.jj	2015-12-02 20:26:59.000000000 +0100
+++ gcc/tree-cfgcleanup.c	2015-12-14 17:34:10.748487811 +0100
@@ -186,7 +186,7 @@  cleanup_control_flow_bb (basic_block bb)
      we need to prune cfg.  */
   retval |= gimple_purge_dead_eh_edges (bb);
 
-  gsi = gsi_last_bb (bb);
+  gsi = gsi_last_nondebug_bb (bb);
   if (gsi_end_p (gsi))
     return retval;
 
@@ -197,7 +197,10 @@  cleanup_control_flow_bb (basic_block bb)
 
   if (gimple_code (stmt) == GIMPLE_COND
       || gimple_code (stmt) == GIMPLE_SWITCH)
-    retval |= cleanup_control_expr_graph (bb, gsi);
+    {
+      gcc_checking_assert (gsi_stmt (gsi_last_bb (bb)) == stmt);
+      retval |= cleanup_control_expr_graph (bb, gsi);
+    }
   else if (gimple_code (stmt) == GIMPLE_GOTO
 	   && TREE_CODE (gimple_goto_dest (stmt)) == ADDR_EXPR
 	   && (TREE_CODE (TREE_OPERAND (gimple_goto_dest (stmt), 0))
@@ -210,6 +213,7 @@  cleanup_control_flow_bb (basic_block bb)
       edge_iterator ei;
       basic_block target_block;
 
+      gcc_checking_assert (gsi_stmt (gsi_last_bb (bb)) == stmt);
       /* First look at all the outgoing edges.  Delete any outgoing
 	 edges which do not go to the right block.  For the one
 	 edge which goes to the right block, fix up its flags.  */
@@ -242,9 +246,15 @@  cleanup_control_flow_bb (basic_block bb)
   /* Check for indirect calls that have been turned into
      noreturn calls.  */
   else if (is_gimple_call (stmt)
-           && gimple_call_noreturn_p (stmt)
-           && remove_fallthru_edge (bb->succs))
-    retval = true;
+	   && gimple_call_noreturn_p (stmt))
+    {
+      /* If there are debug stmts after the noreturn call, remove them
+	 now, they should be all unreachable anyway.  */
+      for (gsi_next (&gsi); !gsi_end_p (gsi); )
+	gsi_remove (&gsi, true);
+      if (remove_fallthru_edge (bb->succs))
+	retval = true;
+    }
 
   return retval;
 }
--- gcc/testsuite/gcc.dg/pr66688.c.jj	2015-12-14 14:51:43.652481658 +0100
+++ gcc/testsuite/gcc.dg/pr66688.c	2015-12-14 14:51:05.000000000 +0100
@@ -0,0 +1,39 @@ 
+/* PR tree-optimization/66688 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-reorder-blocks -fcompare-debug" } */
+
+struct fdt_header { unsigned magic; } *a;
+
+int d;
+
+int
+__fswab32 (int p1)
+{
+  return __builtin_bswap32 (p1);
+}
+
+void
+fdt_set_magic (int p1)
+{
+  struct fdt_header *b = a;
+  b->magic = __builtin_constant_p (p1) ? : __fswab32 (p1);
+}
+
+int
+_fdt_sw_check_header ()
+{
+  int c = ((struct fdt_header *) 1)->magic;
+  if (c)
+    return 1;
+  return 0;
+}
+
+int
+fdt_finish ()
+{
+  if (_fdt_sw_check_header ())
+    if (d)
+      return 0;
+  fdt_set_magic (0);
+  return 0;
+}