summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2003-02-15 21:22:56 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2003-02-15 21:22:56 +0000
commitcea5721fb67381cf902de1b15f1063c03887660a (patch)
tree33f670d96dd4073de4b68f4ac4f97dfe221c8034 /gcc
parenta0b983228dda070bf8b24ab3701542bf9bdbeba0 (diff)
downloadgcc-cea5721fb67381cf902de1b15f1063c03887660a.tar.gz
* 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/bb-reorder.c38
-rw-r--r--gcc/function.c2
-rw-r--r--gcc/function.h4
-rw-r--r--gcc/stmt.c19
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 <rth@redhat.com>
+ * 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 <rth@redhat.com>
+
* 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. */