diff options
author | Robert Kidd <rkidd@gcc.gnu.org> | 2007-09-10 12:49:46 +0000 |
---|---|---|
committer | Robert Kidd <rkidd@gcc.gnu.org> | 2007-09-10 12:49:46 +0000 |
commit | 232abc3ff8954a9b040ea11dd8e3291759a159c6 (patch) | |
tree | beede6b03e0a31fcf7974e27cc39df96abf78663 /gcc | |
parent | 281b604e6b81db532a717590a6fc58b13d087cd0 (diff) | |
download | gcc-232abc3ff8954a9b040ea11dd8e3291759a159c6.zip gcc-232abc3ff8954a9b040ea11dd8e3291759a159c6.tar.gz gcc-232abc3ff8954a9b040ea11dd8e3291759a159c6.tar.bz2 |
bb-reorder.c (rest_of_handler_reorder_blocks): Removed call to RTL level tracer pass.
2007-09-10 Robert Kidd <rkidd@crhc.uiuc.edu>
* bb-reorder.c (rest_of_handler_reorder_blocks): Removed call to
RTL level tracer pass.
* passes.c (init_optimization_passes): Move pass_tracer from
after pass_rtl_ifcvt to after pass_dce.
* tracer.c: Update copyright.
(layout_superblocks): Remove function.
(mark_bb_seen): New.
(bb_seen_p): New.
(count_insns): Change to estimate instructions in a Tree-SSA
statement.
(find_trace): Use bb_seen_p.
(tail_duplicate): Use bb_seen_p. Call add_phi_args_after_copy
after duplicate_block.
(tracer): Change prototype to match that of a pass execute
callback.
(gate_tracer): Rename from gate_handle_tracer.
(rest_of_handle_tracer): Remove function.
* rtl.h: Remove prototype for tracer.
* testsuite/gcc.dg/tree-prof/tracer-1.c: New.
From-SVN: r128341
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/bb-reorder.c | 13 | ||||
-rw-r--r-- | gcc/passes.c | 2 | ||||
-rw-r--r-- | gcc/rtl.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-prof/tracer-1.c | 18 | ||||
-rw-r--r-- | gcc/tracer.c | 162 |
5 files changed, 94 insertions, 103 deletions
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index 8f20f87..0b70771 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -2198,19 +2198,12 @@ rest_of_handle_reorder_blocks (void) splitting possibly introduced more crossjumping opportunities. */ cfg_layout_initialize (CLEANUP_EXPENSIVE); - if (flag_sched2_use_traces && flag_schedule_insns_after_reload) + if (flag_reorder_blocks || flag_reorder_blocks_and_partition) { - timevar_push (TV_TRACER); - tracer (); - timevar_pop (TV_TRACER); + reorder_basic_blocks (); + cleanup_cfg (CLEANUP_EXPENSIVE); } - if (flag_reorder_blocks || flag_reorder_blocks_and_partition) - reorder_basic_blocks (); - if (flag_reorder_blocks || flag_reorder_blocks_and_partition - || (flag_sched2_use_traces && flag_schedule_insns_after_reload)) - cleanup_cfg (CLEANUP_EXPENSIVE); - FOR_EACH_BB (bb) if (bb->next_bb != EXIT_BLOCK_PTR) bb->aux = bb->next_bb; diff --git a/gcc/passes.c b/gcc/passes.c index 7f44842..48f4af0 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -648,6 +648,7 @@ init_optimization_passes (void) NEXT_PASS (pass_phi_only_cprop); NEXT_PASS (pass_cd_dce); + NEXT_PASS (pass_tracer); /* FIXME: If DCE is not run before checking for uninitialized uses, we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c). @@ -692,7 +693,6 @@ init_optimization_passes (void) NEXT_PASS (pass_rtl_fwprop); NEXT_PASS (pass_gcse); NEXT_PASS (pass_rtl_ifcvt); - NEXT_PASS (pass_tracer); /* Perform loop optimizations. It might be better to do them a bit sooner, but we want the profile feedback to work more efficiently. */ @@ -2269,8 +2269,6 @@ extern void invert_br_probabilities (rtx); extern bool expensive_function_p (int); /* In cfgexpand.c */ extern void add_reg_br_prob_note (rtx last, int probability); -/* In tracer.c */ -extern void tracer (void); /* In var-tracking.c */ extern unsigned int variable_tracking_main (void); diff --git a/gcc/testsuite/gcc.dg/tree-prof/tracer-1.c b/gcc/testsuite/gcc.dg/tree-prof/tracer-1.c new file mode 100644 index 0000000..1eac6e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-prof/tracer-1.c @@ -0,0 +1,18 @@ +/* { dg-options "-O2 -ftracer -fdump-tree-tracer" } */ +main () +{ + int i; + int a, b, c; + for (i = 0; i < 1000; i++) + { + if (i % 17) + a++; + else + b++; + c++; + } + return 0; +} +/* Superblock formation should produce two copies of the increment of c */ +/* { dg-final-generate { scan-tree-dump-times "goto <bb 6>;" 2 "tracer" } } */ +/* { dg-final-generate { cleanup-tree-dump "tracer" } } */ diff --git a/gcc/tracer.c b/gcc/tracer.c index 44a2e50..ca50549 100644 --- a/gcc/tracer.c +++ b/gcc/tracer.c @@ -1,5 +1,6 @@ /* The tracer pass for the GNU compiler. Contributed by Jan Hubicka, SuSE Labs. + Adapted to work on GIMPLE instead of RTL by Robert Kidd, UIUC. Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. @@ -49,24 +50,41 @@ #include "params.h" #include "coverage.h" #include "tree-pass.h" +#include "tree-flow.h" +#include "tree-inline.h" -static int count_insns (const_basic_block); +static int count_insns (basic_block); static bool ignore_bb_p (const_basic_block); static bool better_p (const_edge, const_edge); static edge find_best_successor (basic_block); static edge find_best_predecessor (basic_block); static int find_trace (basic_block, basic_block *); static void tail_duplicate (void); -static void layout_superblocks (void); /* Minimal outgoing edge probability considered for superblock formation. */ static int probability_cutoff; static int branch_ratio_cutoff; -/* Return true if BB has been seen - it is connected to some trace - already. */ +/* A bit BB->index is set if BB has already been seen, i.e. it is + connected to some trace already. */ +sbitmap bb_seen; -#define seen(bb) (bb->il.rtl->visited || bb->aux) +static inline void +mark_bb_seen (basic_block bb) +{ + unsigned int size = SBITMAP_SIZE_BYTES (bb_seen) * 8; + + if ((unsigned int)bb->index >= size) + bb_seen = sbitmap_resize (bb_seen, size * 2, 0); + + SET_BIT (bb_seen, bb->index); +} + +static inline bool +bb_seen_p (basic_block bb) +{ + return TEST_BIT (bb_seen, bb->index); +} /* Return true if we should ignore the basic block for purposes of tracing. */ static bool @@ -82,16 +100,17 @@ ignore_bb_p (const_basic_block bb) /* Return number of instructions in the block. */ static int -count_insns (const_basic_block bb) +count_insns (basic_block bb) { - const_rtx insn; + block_stmt_iterator bsi; + tree stmt; int n = 0; - for (insn = BB_HEAD (bb); - insn != NEXT_INSN (BB_END (bb)); - insn = NEXT_INSN (insn)) - if (active_insn_p (insn)) - n++; + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + { + stmt = bsi_stmt (bsi); + n += estimate_num_insns (stmt, &eni_size_weights); + } return n; } @@ -166,7 +185,7 @@ find_trace (basic_block bb, basic_block *trace) while ((e = find_best_predecessor (bb)) != NULL) { basic_block bb2 = e->src; - if (seen (bb2) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX)) + if (bb_seen_p (bb2) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX)) || find_best_successor (bb2) != e) break; if (dump_file) @@ -181,7 +200,7 @@ find_trace (basic_block bb, basic_block *trace) while ((e = find_best_successor (bb)) != NULL) { bb = e->dest; - if (seen (bb) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX)) + if (bb_seen_p (bb) || (e->flags & (EDGE_DFS_BACK | EDGE_COMPLEX)) || find_best_predecessor (bb) != e) break; if (dump_file) @@ -209,6 +228,12 @@ tail_duplicate (void) int max_dup_insns; basic_block bb; + /* Create an oversized sbitmap to reduce the chance that we need to + resize it. */ + bb_seen = sbitmap_alloc (last_basic_block * 2); + sbitmap_zero (bb_seen); + initialize_original_copy_tables (); + if (profile_info && flag_branch_probabilities) probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK); else @@ -250,7 +275,7 @@ tail_duplicate (void) if (ignore_bb_p (bb)) continue; - gcc_assert (!seen (bb)); + gcc_assert (!bb_seen_p (bb)); n = find_trace (bb, trace); @@ -276,25 +301,30 @@ tail_duplicate (void) && can_duplicate_block_p (bb2)) { edge e; - basic_block old = bb2; + basic_block copy; + + nduplicated += counts [bb2->index]; e = find_edge (bb, bb2); + + copy = duplicate_block (bb2, e, bb); + flush_pending_stmts (e); - nduplicated += counts [bb2->index]; - bb2 = duplicate_block (bb2, e, bb); + add_phi_args_after_copy (©, 1); /* Reconsider the original copy of block we've duplicated. Removing the most common predecessor may make it to be head. */ - blocks[old->index] = - fibheap_insert (heap, -old->frequency, old); + blocks[bb2->index] = + fibheap_insert (heap, -bb2->frequency, bb2); if (dump_file) fprintf (dump_file, "Duplicated %i as %i [%i]\n", - old->index, bb2->index, bb2->frequency); + bb2->index, copy->index, copy->frequency); + + bb2 = copy; } - bb->aux = bb2; - bb2->il.rtl->visited = 1; + mark_bb_seen (bb2); bb = bb2; /* In case the trace became infrequent, stop duplicating. */ if (ignore_bb_p (bb)) @@ -308,100 +338,51 @@ tail_duplicate (void) fprintf (dump_file, "Duplicated %i insns (%i%%)\n", nduplicated, nduplicated * 100 / ninsns); + free_original_copy_tables (); + sbitmap_free (bb_seen); free (blocks); free (trace); free (counts); fibheap_delete (heap); } -/* Connect the superblocks into linear sequence. At the moment we attempt to keep - the original order as much as possible, but the algorithm may be made smarter - later if needed. BB reordering pass should void most of the benefits of such - change though. */ - -static void -layout_superblocks (void) -{ - basic_block end = single_succ (ENTRY_BLOCK_PTR); - basic_block bb = end->next_bb; - - while (bb != EXIT_BLOCK_PTR) - { - edge_iterator ei; - edge e, best = NULL; - while (end->aux) - end = end->aux; - - FOR_EACH_EDGE (e, ei, end->succs) - if (e->dest != EXIT_BLOCK_PTR - && e->dest != single_succ (ENTRY_BLOCK_PTR) - && !e->dest->il.rtl->visited - && (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best))) - best = e; - - if (best) - { - end->aux = best->dest; - best->dest->il.rtl->visited = 1; - } - else - for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb) - { - if (!bb->il.rtl->visited) - { - end->aux = bb; - bb->il.rtl->visited = 1; - break; - } - } - } -} - /* Main entry point to this file. */ -void +static unsigned int tracer (void) { - gcc_assert (current_ir_type () == IR_RTL_CFGLAYOUT); + gcc_assert (current_ir_type () == IR_GIMPLE); if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1) - return; + return 0; mark_dfs_back_edges (); if (dump_file) dump_flow_info (dump_file, dump_flags); + + /* Trace formation is done on the fly inside tail_duplicate */ tail_duplicate (); - layout_superblocks (); - relink_block_chain (/*stay_in_cfglayout_mode=*/true); - + + /* FIXME: We really only need to do this when we know tail duplication + has altered the CFG. */ + free_dominance_info (CDI_DOMINATORS); if (dump_file) dump_flow_info (dump_file, dump_flags); - /* Merge basic blocks in duplicated traces. */ - cleanup_cfg (0); + return 0; } static bool -gate_handle_tracer (void) +gate_tracer (void) { - return (optimize > 0 && flag_tracer); -} - -/* Run tracer. */ -static unsigned int -rest_of_handle_tracer (void) -{ - if (dump_file) - dump_flow_info (dump_file, dump_flags); - tracer (); - return 0; + return (optimize > 0 && flag_tracer && flag_reorder_blocks); } struct tree_opt_pass pass_tracer = { "tracer", /* name */ - gate_handle_tracer, /* gate */ - rest_of_handle_tracer, /* execute */ + gate_tracer, /* gate */ + tracer, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ @@ -410,7 +391,8 @@ struct tree_opt_pass pass_tracer = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_dump_func | TODO_verify_rtl_sharing, /* todo_flags_finish */ + TODO_dump_func + | TODO_update_ssa + | TODO_verify_ssa, /* todo_flags_finish */ 'T' /* letter */ }; - |