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  <ja...@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

Reply via email to