From cea5721fb67381cf902de1b15f1063c03887660a Mon Sep 17 00:00:00 2001 From: rth Date: Sat, 15 Feb 2003 21:22:56 +0000 Subject: [PATCH] * bb-reorder.c (find_traces_1_round): Don't connect easy to copy successors with multiple predecessors. (connect_traces): Try harder to copy traces of length 1. * function.h (struct function): Add computed_goto_common_label, computed_goto_common_reg. * function.c (free_after_compilation): Zap them. * stmt.c (expand_computed_goto): Use them to produce one indirect branch per function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@62944 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 12 ++++++++++++ gcc/bb-reorder.c | 38 +++++++++++++++++++++++++++++++------- gcc/function.c | 2 ++ gcc/function.h | 4 ++++ gcc/stmt.c | 19 ++++++++++++++++--- 5 files changed, 65 insertions(+), 10 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index adb0f787b97..0942b3ab6fa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -40,6 +40,18 @@ 2003-02-15 Richard Henderson + * bb-reorder.c (find_traces_1_round): Don't connect easy to copy + successors with multiple predecessors. + (connect_traces): Try harder to copy traces of length 1. + + * function.h (struct function): Add computed_goto_common_label, + computed_goto_common_reg. + * function.c (free_after_compilation): Zap them. + * stmt.c (expand_computed_goto): Use them to produce one + indirect branch per function. + +2003-02-15 Richard Henderson + * cfgcleanup.c: Include params.h. (try_crossjump_bb): Use PARAM_MAX_CROSSJUMP_EDGES. Fix test for too many outgoing edges from a block. diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index 0711f18670e..49889ee2ba3 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -448,6 +448,12 @@ find_traces_1_round (branch_th, exec_th, count_th, traces, n_traces, round, || prob < branch_th || freq < exec_th || e->count < count_th) continue; + /* If the destination has multiple precessesors, and can be + duplicated cheaper than a jump, don't allow it to be added + to a trace. We'll duplicate it when connecting traces. */ + if (e->dest->pred->pred_next && copy_bb_p (e->dest, 0)) + continue; + if (better_edge_p (bb, e, prob, freq, best_prob, best_freq)) { best_edge = e; @@ -905,19 +911,27 @@ connect_traces (n_traces, traces) /* Try to connect the traces by duplication of 1 block. */ edge e2; basic_block next_bb = NULL; + bool try_copy = false; for (e = traces[t].last->succ; e; e = e->succ_next) if (e->dest != EXIT_BLOCK_PTR && (e->flags & EDGE_CAN_FALLTHRU) && !(e->flags & EDGE_COMPLEX) - && (EDGE_FREQUENCY (e) >= freq_threshold) - && (e->count >= count_threshold) - && (!best - || e->probability > best->probability)) + && (!best || e->probability > best->probability)) { edge best2 = NULL; int best2_len = 0; + /* If the destination trace is only one block + long, then no need to search the successor + blocks of the trace. Accept it. */ + if (traces[bbd[e->dest->index].start_of_trace].length == 1) + { + best = e; + try_copy = true; + continue; + } + for (e2 = e->dest->succ; e2; e2 = e2->succ_next) { int di = e2->dest->index; @@ -942,10 +956,18 @@ connect_traces (n_traces, traces) else best2_len = INT_MAX; next_bb = e2->dest; + try_copy = true; } } } - if (best && next_bb && copy_bb_p (best->dest, !optimize_size)) + + /* Copy tiny blocks always; copy larger blocks only when the + edge is traversed frequently enough. */ + if (try_copy + && copy_bb_p (best->dest, + !optimize_size + && EDGE_FREQUENCY (best) >= freq_threshold + && best->count >= count_threshold)) { basic_block new_bb; @@ -953,7 +975,9 @@ connect_traces (n_traces, traces) { fprintf (rtl_dump_file, "Connection: %d %d ", traces[t].last->index, best->dest->index); - if (next_bb == EXIT_BLOCK_PTR) + if (!next_bb) + fputc ('\n', rtl_dump_file); + else if (next_bb == EXIT_BLOCK_PTR) fprintf (rtl_dump_file, "exit\n"); else fprintf (rtl_dump_file, "%d\n", next_bb->index); @@ -961,7 +985,7 @@ connect_traces (n_traces, traces) new_bb = copy_bb (best->dest, best, traces[t].last, t); traces[t].last = new_bb; - if (next_bb != EXIT_BLOCK_PTR) + if (next_bb && next_bb != EXIT_BLOCK_PTR) { t = bbd[next_bb->index].start_of_trace; RBI (traces[last_trace].last)->next = traces[t].first; diff --git a/gcc/function.c b/gcc/function.c index cb5cf64f4be..b20d41f784b 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -452,6 +452,8 @@ free_after_compilation (f) f->x_nonlocal_goto_stack_level = NULL; f->x_cleanup_label = NULL; f->x_return_label = NULL; + f->computed_goto_common_label = NULL; + f->computed_goto_common_reg = NULL; f->x_save_expr_regs = NULL; f->x_stack_slot_list = NULL; f->x_rtl_expr_chain = NULL; diff --git a/gcc/function.h b/gcc/function.h index d92b8152963..5d4258ffe5b 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -268,6 +268,10 @@ struct function GTY(()) on machines which require execution of the epilogue on all returns. */ rtx x_return_label; + /* Label and register for unswitching computed gotos. */ + rtx computed_goto_common_label; + rtx computed_goto_common_reg; + /* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs. So we can mark them all live at the end of the function, if nonopt. */ rtx x_save_expr_regs; diff --git a/gcc/stmt.c b/gcc/stmt.c index f9680126969..bc7cc28a7c1 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -539,10 +539,23 @@ expand_computed_goto (exp) #endif emit_queue (); - do_pending_stack_adjust (); - emit_indirect_jump (x); - current_function_has_computed_jump = 1; + if (! cfun->computed_goto_common_label) + { + cfun->computed_goto_common_reg = copy_to_mode_reg (Pmode, x); + cfun->computed_goto_common_label = gen_label_rtx (); + emit_label (cfun->computed_goto_common_label); + + do_pending_stack_adjust (); + emit_indirect_jump (cfun->computed_goto_common_reg); + + current_function_has_computed_jump = 1; + } + else + { + emit_move_insn (cfun->computed_goto_common_reg, x); + emit_jump (cfun->computed_goto_common_label); + } } /* Handle goto statements and the labels that they can go to. */ -- 2.11.0