From 90a7788bbc9890f681aa8434a861d88c3a9eb815 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 31 May 2010 17:38:35 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 +++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/debug/pr44182.C | 26 +++++++++ gcc/tree-inline.c | 86 ++++++++++++++++++++++++++-- 4 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/debug/pr44182.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 21e45300f0c..30fe267e3bb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2010-05-31 Jakub Jelinek + + 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 PR target/44161 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 69808cd39dd..4dc9a4158a3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-05-31 Jakub Jelinek + + PR tree-optimization/44182 + * g++.dg/debug/pr44182.C: New test. + 2010-05-31 Eric Botcazou * 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 00000000000..3e062a3fe84 --- /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 e42e81c60a1..3055b5797fb 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);) { @@ -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; -- 2.30.2