re PR tree-optimization/44182 (-fcompare-debug failure (length) with -O1)
authorJakub Jelinek <jakub@redhat.com>
Mon, 31 May 2010 15:38:35 +0000 (17:38 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 31 May 2010 15:38:35 +0000 (17:38 +0200)
PR tree-optimization/44182
* tree-inline.c (copy_edges_for_bb): Don't split bb if a stmt that
newly needs to end a bb is followed by debug stmts, instead return
true from the function at the end.
(maybe_move_debug_stmts_to_successors): New function.
(copy_cfg_body): Call it if copy_edges_for_bb returned true.

* g++.dg/debug/pr44182.C: New test.

From-SVN: r160074

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/debug/pr44182.C [new file with mode: 0644]
gcc/tree-inline.c

index 21e45300f0cde338a7f68e3c51e6b346911be296..30fe267e3bb8fb330298e65e9880728c3746d0f0 100644 (file)
@@ -1,3 +1,12 @@
+2010-05-31  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/44182
+       * tree-inline.c (copy_edges_for_bb): Don't split bb if a stmt that
+       newly needs to end a bb is followed by debug stmts, instead return
+       true from the function at the end.
+       (maybe_move_debug_stmts_to_successors): New function.
+       (copy_cfg_body): Call it if copy_edges_for_bb returned true.
+
 2010-05-31  Kai Tietz  <kai.tietz@onevision.com>
 
        PR target/44161
index 69808cd39dddf9e9b4c40f6c430f25da5b9c2077..4dc9a4158a391654b486767a38219a3c429ec8f2 100644 (file)
@@ -1,3 +1,8 @@
+2010-05-31  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/44182
+       * g++.dg/debug/pr44182.C: New test.
+
 2010-05-31  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.dg/nested-func-7.c: New test.
diff --git a/gcc/testsuite/g++.dg/debug/pr44182.C b/gcc/testsuite/g++.dg/debug/pr44182.C
new file mode 100644 (file)
index 0000000..3e062a3
--- /dev/null
@@ -0,0 +1,26 @@
+// PR tree-optimization/44182
+// { dg-do compile }
+// { dg-options "-fcompare-debug" }
+
+struct S
+{
+  int i;
+  S ();
+  ~S ();
+  void f1 ();
+  void f2 (S s)
+  {
+    f3 (s.i);
+    for (int j = 0; j < s.i; j++) f1 ();
+  }
+  void f3 (int j)
+  {
+    if (j > i) f1 ();
+  }
+};
+
+void
+f (S *x)
+{
+  x->f2 (S ());
+}
index e42e81c60a17de0d9983a47da6ebfeb6a7dd41d8..3055b5797fb4be8be6d6338ededa4592081c8d47 100644 (file)
@@ -1834,9 +1834,10 @@ update_ssa_across_abnormal_edges (basic_block bb, basic_block ret_bb,
 
 /* Copy edges from BB into its copy constructed earlier, scale profile
    accordingly.  Edges will be taken care of later.  Assume aux
-   pointers to point to the copies of each BB.  */
+   pointers to point to the copies of each BB.  Return true if any
+   debug stmts are left after a statement that must end the basic block.  */
 
-static void
+static bool
 copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb)
 {
   basic_block new_bb = (basic_block) bb->aux;
@@ -1844,6 +1845,7 @@ copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb)
   edge old_edge;
   gimple_stmt_iterator si;
   int flags;
+  bool need_debug_cleanup = false;
 
   /* Use the indices from the original blocks to create edges for the
      new ones.  */
@@ -1864,7 +1866,7 @@ copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb)
       }
 
   if (bb->index == ENTRY_BLOCK || bb->index == EXIT_BLOCK)
-    return;
+    return false;
 
   for (si = gsi_start_bb (new_bb); !gsi_end_p (si);)
     {
@@ -1898,6 +1900,13 @@ copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb)
 
       if (can_throw || nonlocal_goto)
        {
+         if (!gsi_end_p (si))
+           {
+             while (!gsi_end_p (si) && is_gimple_debug (gsi_stmt (si)))
+               gsi_next (&si);
+             if (gsi_end_p (si))
+               need_debug_cleanup = true;
+           }
          if (!gsi_end_p (si))
            /* Note that bb's predecessor edges aren't necessarily
               right at this point; split_block doesn't care.  */
@@ -1923,6 +1932,7 @@ copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb)
        update_ssa_across_abnormal_edges (gimple_bb (copy_stmt), ret_bb,
                                          can_throw, nonlocal_goto);
     }
+  return need_debug_cleanup;
 }
 
 /* Copy the PHIs.  All blocks and edges are copied, some blocks
@@ -2059,6 +2069,63 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
   pop_cfun ();
 }
 
+/* Helper function for copy_cfg_body.  Move debug stmts from the end
+   of NEW_BB to the beginning of successor basic blocks when needed.  If the
+   successor has multiple predecessors, reset them, otherwise keep
+   their value.  */
+
+static void
+maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb)
+{
+  edge e;
+  edge_iterator ei;
+  gimple_stmt_iterator si = gsi_last_nondebug_bb (new_bb);
+
+  if (gsi_end_p (si)
+      || gsi_one_before_end_p (si)
+      || !(stmt_can_throw_internal (gsi_stmt (si))
+          || stmt_can_make_abnormal_goto (gsi_stmt (si))))
+    return;
+
+  FOR_EACH_EDGE (e, ei, new_bb->succs)
+    {
+      gimple_stmt_iterator ssi = gsi_last_bb (new_bb);
+      gimple_stmt_iterator dsi = gsi_after_labels (e->dest);
+      while (is_gimple_debug (gsi_stmt (ssi)))
+       {
+         gimple stmt = gsi_stmt (ssi), new_stmt;
+         tree var;
+         tree value;
+
+         /* For the last edge move the debug stmts instead of copying
+            them.  */
+         if (ei_one_before_end_p (ei))
+           {
+             si = ssi;
+             gsi_prev (&ssi);
+             if (!single_pred_p (e->dest))
+               gimple_debug_bind_reset_value (stmt);
+             gsi_remove (&si, false);
+             gsi_insert_before (&dsi, stmt, GSI_SAME_STMT);
+             continue;
+           }
+
+         var = gimple_debug_bind_get_var (stmt);
+         if (single_pred_p (e->dest))
+           {
+             value = gimple_debug_bind_get_value (stmt);
+             value = unshare_expr (value);
+           }
+         else
+           value = NULL_TREE;
+         new_stmt = gimple_build_debug_bind (var, value, stmt);
+         gsi_insert_before (&dsi, new_stmt, GSI_SAME_STMT);
+         VEC_safe_push (gimple, heap, id->debug_stmts, new_stmt);
+         gsi_prev (&ssi);
+       }
+    }
+}
+
 /* Make a copy of the body of FN so that it can be inserted inline in
    another function.  Walks FN via CFG, returns new fndecl.  */
 
@@ -2072,6 +2139,7 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
   struct function *cfun_to_copy;
   basic_block bb;
   tree new_fndecl = NULL;
+  bool need_debug_cleanup = false;
   gcov_type count_scale;
   int last;
 
@@ -2112,7 +2180,7 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
 
   /* Now that we've duplicated the blocks, duplicate their edges.  */
   FOR_ALL_BB_FN (bb, cfun_to_copy)
-    copy_edges_for_bb (bb, count_scale, exit_block_map);
+    need_debug_cleanup |= copy_edges_for_bb (bb, count_scale, exit_block_map);
 
   if (gimple_in_ssa_p (cfun))
     FOR_ALL_BB_FN (bb, cfun_to_copy)
@@ -2120,6 +2188,10 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
 
   FOR_ALL_BB_FN (bb, cfun_to_copy)
     {
+      if (need_debug_cleanup
+         && bb->index != ENTRY_BLOCK
+         && bb->index != EXIT_BLOCK)
+       maybe_move_debug_stmts_to_successors (id, (basic_block) bb->aux);
       ((basic_block)bb->aux)->aux = NULL;
       bb->aux = NULL;
     }
@@ -2127,7 +2199,11 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
   /* Zero out AUX fields of newly created block during EH edge
      insertion. */
   for (; last < last_basic_block; last++)
-    BASIC_BLOCK (last)->aux = NULL;
+    {
+      if (need_debug_cleanup)
+       maybe_move_debug_stmts_to_successors (id, BASIC_BLOCK (last));
+      BASIC_BLOCK (last)->aux = NULL;
+    }
   entry_block_map->aux = NULL;
   exit_block_map->aux = NULL;