diff options
author | Jakub Jelinek <jakub@redhat.com> | 2010-05-31 17:38:35 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2010-05-31 17:38:35 +0200 |
commit | 90a7788bbc9890f681aa8434a861d88c3a9eb815 (patch) | |
tree | df14b009ae81deca2b86203a098a50621e0bf602 | |
parent | 1e2c0906eeaf6050034a17d06c9d40c16a3f29cd (diff) | |
download | gcc-90a7788bbc9890f681aa8434a861d88c3a9eb815.zip gcc-90a7788bbc9890f681aa8434a861d88c3a9eb815.tar.gz gcc-90a7788bbc9890f681aa8434a861d88c3a9eb815.tar.bz2 |
re PR tree-optimization/44182 (-fcompare-debug failure (length) with -O1)
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
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/debug/pr44182.C | 26 | ||||
-rw-r--r-- | gcc/tree-inline.c | 86 |
4 files changed, 121 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 21e4530..30fe267e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 69808cd..4dc9a41 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..3e062a3 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/pr44182.C @@ -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 ()); +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index e42e81c..3055b57 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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);) { @@ -1899,6 +1901,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; |