Commit bc35512f by Jan Hubicka Committed by Jan Hubicka

basic-block.h (create_basic_block, [...]): Kill.

	* basic-block.h (create_basic_block, merge_blocks_nomove): Kill.
	* cfgcleanup.c (merge_blocks): Rename to merge_blocks_move.
	(merge_blocks_move_predecessor_nojumps,
	 merge_blocks_move_successor_nojumps): Use merge_blocks.
	(try_optimize_cfg): Use merge_blocks_move.
	* cfgrtl.c (create_basic_block): Rename to rtl_create_basic_block.
	(merge_blocks_nomove): Rename to rtl_merge_blocks.
	(cfg_layout_create_basic_block): New.
	(rtl_can_merge_blocks): New.
	(cfg_layout_split_block): Do not alloc aux by hand.
	* cfghooks.h (cfg_hooks): Add create_basic_block, can_merge_blocks_p,
	merge_blocks.
	(create_basic_block, can_merge_blocks_p, merge_blocks): New macros.
	* cfglayout.c (cfg_layout_duplicate_bb): Do not allocate aux by hand.
	* cfgloopmanip.c (loop_split_edge_with): Likewise.
	* ifcvt.c (merge_if_block): Use merge_blocks_nomove.

	* basic-block.h (basic_block_def): Add field 'rbi'.
	* bb-reorder.c (find_traces, rotate_loop, mark_bb_visited,
	find_traces_1_round, copy_bb, connect_traces): Update use of rbi.
	* cfg.c (entry_exit_blocks): Add new field.
	* cfglayout.c: Include alloc-pool.h;
	(cfg_layout_pool): New.
	(record_effective_endpoints, fixup_reorder_chain,
	fixup_fallthru_exit_predecessor, cfg_layout_duplicate_bb): Update use
	of rbi.
	(cfg_layout_initialize_rbi): New function.
	(cfg_layout_initialize): Use it.
	(cfg_layout_finalize): Clear rbi fields.
	* cfglayout.h (RBI): Kill.
	(cfg_layout_initialize_rbi): Declare.
	* cfgloopmanip.c (copy_bbs): Use rbi.
	(record_exit_edges): Likewise.
	(duplicate_loop_to_header_edge): Likewise.
	* cfgrtl.c (cfg_layout_create_basic_block): Use
	cfg_layout_initialize_rbi.
	(cfg_layout_split_block): Use rbi.
	(cfg_layout_delete_block): Likewise.
	* loop-init.c (loop_optimizer_finalize): Likewise.
	* loop-unswitch.c (unswitch_loop): Likewise.
	* tracer.c (seen, tail_duplicate, layout_superblocks): Likewise.

	* cfgrtl.c: Update comments.
	(try_redirect_by_replacing_jump): New argument.
	(redirect_branch_edge): Break out from ...
	(rtl_redirect_edge_and_branch): ... this one.
	(update_cfg_after_block_merging): Break out from ...
	(rtl_merge_blocks): ... this one.
	(cfg_layout_split_edge): New.
	(cfg_layout_merge_blocks): New.
	(cfg_layout_can_merge_blocks_p): New.
	(cfg_layout_redirect_edge_and_branch): Reorganize.
	(cfg_layout_rtl_cfg_hooks): Fill in.
	(cfg_layout_delete_block): Kill barriers.
	* cfganal.c (can_fallthru): Deal with exit blocks
	* cfglayout.c (cfg_layout_function_header): New function
	(record_effective_endpoints): Record function header.
	(fixup_reorder_chain): Fixup dead jumptables; place header

	* basic-block.h (CLEANUP_CFGLAYOUT): New flag.
	* bb-reorder.c (cfg_layout_initialize): Update call.
	* cfgcleanup.c (try_optimize_cfg): Supress optimizations of fallthru
	edges in cfglayout mode.
	* cfglayout.c (cleanup_unconditional_jumps): Kill.
	(cfg_layout_initialize): Kill agrument loops; use cfgcleanup.
	* cfglayout.h (cfg_layout_initialize): Update prototype.
	* cfgloop.h (CP_INSIDE_CFGLAYOUT): Kill.
	* cfgloopmanip.c (loop_split_edge_with): Use split_edge.
	* flow.c (propagate_block): Do not crash when basic block ends
	by first insn in the chain.
	* loop-init.c (loop_optimizer_init):  First enter cfglayout mode; later
	do loop discovery.
	* tracer.c (tracer): Update call of cfg_layout_initialize.

From-SVN: r68899
parent 9b269fc7
Thu Jul 3 20:36:47 CEST 2003 Jan Hubicka <jh@suse.cz>
* basic-block.h (create_basic_block, merge_blocks_nomove): Kill.
* cfgcleanup.c (merge_blocks): Rename to merge_blocks_move.
(merge_blocks_move_predecessor_nojumps,
merge_blocks_move_successor_nojumps): Use merge_blocks.
(try_optimize_cfg): Use merge_blocks_move.
* cfgrtl.c (create_basic_block): Rename to rtl_create_basic_block.
(merge_blocks_nomove): Rename to rtl_merge_blocks.
(cfg_layout_create_basic_block): New.
(rtl_can_merge_blocks): New.
(cfg_layout_split_block): Do not alloc aux by hand.
* cfghooks.h (cfg_hooks): Add create_basic_block, can_merge_blocks_p,
merge_blocks.
(create_basic_block, can_merge_blocks_p, merge_blocks): New macros.
* cfglayout.c (cfg_layout_duplicate_bb): Do not allocate aux by hand.
* cfgloopmanip.c (loop_split_edge_with): Likewise.
* ifcvt.c (merge_if_block): Use merge_blocks_nomove.
* basic-block.h (basic_block_def): Add field 'rbi'.
* bb-reorder.c (find_traces, rotate_loop, mark_bb_visited,
find_traces_1_round, copy_bb, connect_traces): Update use of rbi.
* cfg.c (entry_exit_blocks): Add new field.
* cfglayout.c: Include alloc-pool.h;
(cfg_layout_pool): New.
(record_effective_endpoints, fixup_reorder_chain,
fixup_fallthru_exit_predecessor, cfg_layout_duplicate_bb): Update use
of rbi.
(cfg_layout_initialize_rbi): New function.
(cfg_layout_initialize): Use it.
(cfg_layout_finalize): Clear rbi fields.
* cfglayout.h (RBI): Kill.
(cfg_layout_initialize_rbi): Declare.
* cfgloopmanip.c (copy_bbs): Use rbi.
(record_exit_edges): Likewise.
(duplicate_loop_to_header_edge): Likewise.
* cfgrtl.c (cfg_layout_create_basic_block): Use
cfg_layout_initialize_rbi.
(cfg_layout_split_block): Use rbi.
(cfg_layout_delete_block): Likewise.
* loop-init.c (loop_optimizer_finalize): Likewise.
* loop-unswitch.c (unswitch_loop): Likewise.
* tracer.c (seen, tail_duplicate, layout_superblocks): Likewise.
* cfgrtl.c: Update comments.
(try_redirect_by_replacing_jump): New argument.
(redirect_branch_edge): Break out from ...
(rtl_redirect_edge_and_branch): ... this one.
(update_cfg_after_block_merging): Break out from ...
(rtl_merge_blocks): ... this one.
(cfg_layout_split_edge): New.
(cfg_layout_merge_blocks): New.
(cfg_layout_can_merge_blocks_p): New.
(cfg_layout_redirect_edge_and_branch): Reorganize.
(cfg_layout_rtl_cfg_hooks): Fill in.
(cfg_layout_delete_block): Kill barriers.
* cfganal.c (can_fallthru): Deal with exit blocks
* cfglayout.c (cfg_layout_function_header): New function
(record_effective_endpoints): Record function header.
(fixup_reorder_chain): Fixup dead jumptables; place header
* basic-block.h (CLEANUP_CFGLAYOUT): New flag.
* bb-reorder.c (cfg_layout_initialize): Update call.
* cfgcleanup.c (try_optimize_cfg): Supress optimizations of fallthru
edges in cfglayout mode.
* cfglayout.c (cleanup_unconditional_jumps): Kill.
(cfg_layout_initialize): Kill agrument loops; use cfgcleanup.
* cfglayout.h (cfg_layout_initialize): Update prototype.
* cfgloop.h (CP_INSIDE_CFGLAYOUT): Kill.
* cfgloopmanip.c (loop_split_edge_with): Use split_edge.
* flow.c (propagate_block): Do not crash when basic block ends
by first insn in the chain.
* loop-init.c (loop_optimizer_init): First enter cfglayout mode; later
do loop discovery.
* tracer.c (tracer): Update call of cfg_layout_initialize.
2003-07-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2003-07-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* Makefile.in: Use dependency variables in lieu of explicit * Makefile.in: Use dependency variables in lieu of explicit
......
...@@ -241,6 +241,9 @@ typedef struct basic_block_def { ...@@ -241,6 +241,9 @@ typedef struct basic_block_def {
/* Various flags. See BB_* below. */ /* Various flags. See BB_* below. */
int flags; int flags;
/* Additional data maintained by cfg_layout routines. */
struct reorder_block_def *rbi;
} *basic_block; } *basic_block;
#define BB_FREQ_MAX 10000 #define BB_FREQ_MAX 10000
...@@ -362,9 +365,7 @@ extern void redirect_edge_succ PARAMS ((edge, basic_block)); ...@@ -362,9 +365,7 @@ extern void redirect_edge_succ PARAMS ((edge, basic_block));
extern edge redirect_edge_succ_nodup PARAMS ((edge, basic_block)); extern edge redirect_edge_succ_nodup PARAMS ((edge, basic_block));
extern void redirect_edge_pred PARAMS ((edge, basic_block)); extern void redirect_edge_pred PARAMS ((edge, basic_block));
extern basic_block create_basic_block_structure PARAMS ((rtx, rtx, rtx, basic_block)); extern basic_block create_basic_block_structure PARAMS ((rtx, rtx, rtx, basic_block));
extern basic_block create_basic_block PARAMS ((rtx, rtx, basic_block));
extern void clear_bb_flags PARAMS ((void)); extern void clear_bb_flags PARAMS ((void));
extern void merge_blocks_nomove PARAMS ((basic_block, basic_block));
extern void tidy_fallthru_edge PARAMS ((edge, basic_block, extern void tidy_fallthru_edge PARAMS ((edge, basic_block,
basic_block)); basic_block));
extern void tidy_fallthru_edges PARAMS ((void)); extern void tidy_fallthru_edges PARAMS ((void));
...@@ -500,6 +501,7 @@ enum update_life_extent ...@@ -500,6 +501,7 @@ enum update_life_extent
#define CLEANUP_THREADING 64 /* Do jump threading. */ #define CLEANUP_THREADING 64 /* Do jump threading. */
#define CLEANUP_NO_INSN_DEL 128 /* Do not try to delete trivially dead #define CLEANUP_NO_INSN_DEL 128 /* Do not try to delete trivially dead
insns. */ insns. */
#define CLEANUP_CFGLAYOUT 256 /* Do cleanup in cfglayout mode. */
extern void life_analysis PARAMS ((rtx, FILE *, int)); extern void life_analysis PARAMS ((rtx, FILE *, int));
extern int update_life_info PARAMS ((sbitmap, enum update_life_extent, extern int update_life_info PARAMS ((sbitmap, enum update_life_extent,
int)); int));
......
...@@ -205,7 +205,7 @@ find_traces (int *n_traces, struct trace *traces) ...@@ -205,7 +205,7 @@ find_traces (int *n_traces, struct trace *traces)
basic_block bb; basic_block bb;
fprintf (rtl_dump_file, "Trace %d (round %d): ", i + 1, fprintf (rtl_dump_file, "Trace %d (round %d): ", i + 1,
traces[i].round + 1); traces[i].round + 1);
for (bb = traces[i].first; bb != traces[i].last; bb = RBI (bb)->next) for (bb = traces[i].first; bb != traces[i].last; bb = bb->rbi->next)
fprintf (rtl_dump_file, "%d [%d] ", bb->index, bb->frequency); fprintf (rtl_dump_file, "%d [%d] ", bb->index, bb->frequency);
fprintf (rtl_dump_file, "%d [%d]\n", bb->index, bb->frequency); fprintf (rtl_dump_file, "%d [%d]\n", bb->index, bb->frequency);
} }
...@@ -237,14 +237,14 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) ...@@ -237,14 +237,14 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n)
edge e; edge e;
for (e = bb->succ; e; e = e->succ_next) for (e = bb->succ; e; e = e->succ_next)
if (e->dest != EXIT_BLOCK_PTR if (e->dest != EXIT_BLOCK_PTR
&& RBI (e->dest)->visited != trace_n && e->dest->rbi->visited != trace_n
&& (e->flags & EDGE_CAN_FALLTHRU) && (e->flags & EDGE_CAN_FALLTHRU)
&& !(e->flags & EDGE_COMPLEX)) && !(e->flags & EDGE_COMPLEX))
{ {
if (is_preferred) if (is_preferred)
{ {
/* The best edge is preferred. */ /* The best edge is preferred. */
if (!RBI (e->dest)->visited if (!e->dest->rbi->visited
|| bbd[e->dest->index].start_of_trace >= 0) || bbd[e->dest->index].start_of_trace >= 0)
{ {
/* The current edge E is also preferred. */ /* The current edge E is also preferred. */
...@@ -260,7 +260,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) ...@@ -260,7 +260,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n)
} }
else else
{ {
if (!RBI (e->dest)->visited if (!e->dest->rbi->visited
|| bbd[e->dest->index].start_of_trace >= 0) || bbd[e->dest->index].start_of_trace >= 0)
{ {
/* The current edge E is preferred. */ /* The current edge E is preferred. */
...@@ -283,7 +283,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) ...@@ -283,7 +283,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n)
} }
} }
} }
bb = RBI (bb)->next; bb = bb->rbi->next;
} }
while (bb != back_edge->dest); while (bb != back_edge->dest);
...@@ -293,17 +293,17 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) ...@@ -293,17 +293,17 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n)
the trace. */ the trace. */
if (back_edge->dest == trace->first) if (back_edge->dest == trace->first)
{ {
trace->first = RBI (best_bb)->next; trace->first = best_bb->rbi->next;
} }
else else
{ {
basic_block prev_bb; basic_block prev_bb;
for (prev_bb = trace->first; for (prev_bb = trace->first;
RBI (prev_bb)->next != back_edge->dest; prev_bb->rbi->next != back_edge->dest;
prev_bb = RBI (prev_bb)->next) prev_bb = prev_bb->rbi->next)
; ;
RBI (prev_bb)->next = RBI (best_bb)->next; prev_bb->rbi->next = best_bb->rbi->next;
/* Try to get rid of uncond jump to cond jump. */ /* Try to get rid of uncond jump to cond jump. */
if (prev_bb->succ && !prev_bb->succ->succ_next) if (prev_bb->succ && !prev_bb->succ->succ_next)
...@@ -324,7 +324,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) ...@@ -324,7 +324,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n)
/* We have not found suitable loop tail so do no rotation. */ /* We have not found suitable loop tail so do no rotation. */
best_bb = back_edge->src; best_bb = back_edge->src;
} }
RBI (best_bb)->next = NULL; best_bb->rbi->next = NULL;
return best_bb; return best_bb;
} }
...@@ -333,7 +333,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) ...@@ -333,7 +333,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n)
static void static void
mark_bb_visited (basic_block bb, int trace) mark_bb_visited (basic_block bb, int trace)
{ {
RBI (bb)->visited = trace; bb->rbi->visited = trace;
if (bbd[bb->index].heap) if (bbd[bb->index].heap)
{ {
fibheap_delete_node (bbd[bb->index].heap, bbd[bb->index].node); fibheap_delete_node (bbd[bb->index].heap, bbd[bb->index].node);
...@@ -420,8 +420,8 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, ...@@ -420,8 +420,8 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
if (e->dest == EXIT_BLOCK_PTR) if (e->dest == EXIT_BLOCK_PTR)
continue; continue;
if (RBI (e->dest)->visited if (e->dest->rbi->visited
&& RBI (e->dest)->visited != *n_traces) && e->dest->rbi->visited != *n_traces)
continue; continue;
prob = e->probability; prob = e->probability;
...@@ -453,7 +453,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, ...@@ -453,7 +453,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
{ {
if (e == best_edge if (e == best_edge
|| e->dest == EXIT_BLOCK_PTR || e->dest == EXIT_BLOCK_PTR
|| RBI (e->dest)->visited) || e->dest->rbi->visited)
continue; continue;
key = bb_to_key (e->dest); key = bb_to_key (e->dest);
...@@ -508,7 +508,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, ...@@ -508,7 +508,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
if (best_edge) /* Suitable successor was found. */ if (best_edge) /* Suitable successor was found. */
{ {
if (RBI (best_edge->dest)->visited == *n_traces) if (best_edge->dest->rbi->visited == *n_traces)
{ {
/* We do nothing with one basic block loops. */ /* We do nothing with one basic block loops. */
if (best_edge->dest != bb) if (best_edge->dest != bb)
...@@ -528,7 +528,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, ...@@ -528,7 +528,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
"Rotating loop %d - %d\n", "Rotating loop %d - %d\n",
best_edge->dest->index, bb->index); best_edge->dest->index, bb->index);
} }
RBI (bb)->next = best_edge->dest; bb->rbi->next = best_edge->dest;
bb = rotate_loop (best_edge, trace, *n_traces); bb = rotate_loop (best_edge, trace, *n_traces);
} }
} }
...@@ -583,7 +583,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, ...@@ -583,7 +583,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
if (e != best_edge if (e != best_edge
&& (e->flags & EDGE_CAN_FALLTHRU) && (e->flags & EDGE_CAN_FALLTHRU)
&& !(e->flags & EDGE_COMPLEX) && !(e->flags & EDGE_COMPLEX)
&& !RBI (e->dest)->visited && !e->dest->rbi->visited
&& !e->dest->pred->pred_next && !e->dest->pred->pred_next
&& e->dest->succ && e->dest->succ
&& (e->dest->succ->flags & EDGE_CAN_FALLTHRU) && (e->dest->succ->flags & EDGE_CAN_FALLTHRU)
...@@ -599,7 +599,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, ...@@ -599,7 +599,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
break; break;
} }
RBI (bb)->next = best_edge->dest; bb->rbi->next = best_edge->dest;
bb = best_edge->dest; bb = best_edge->dest;
} }
} }
...@@ -615,7 +615,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, ...@@ -615,7 +615,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th,
for (e = bb->succ; e; e = e->succ_next) for (e = bb->succ; e; e = e->succ_next)
{ {
if (e->dest == EXIT_BLOCK_PTR if (e->dest == EXIT_BLOCK_PTR
|| RBI (e->dest)->visited) || e->dest->rbi->visited)
continue; continue;
if (bbd[e->dest->index].heap) if (bbd[e->dest->index].heap)
...@@ -656,15 +656,15 @@ copy_bb (basic_block old_bb, edge e, basic_block bb, int trace) ...@@ -656,15 +656,15 @@ copy_bb (basic_block old_bb, edge e, basic_block bb, int trace)
new_bb = cfg_layout_duplicate_bb (old_bb, e); new_bb = cfg_layout_duplicate_bb (old_bb, e);
if (e->dest != new_bb) if (e->dest != new_bb)
abort (); abort ();
if (RBI (e->dest)->visited) if (e->dest->rbi->visited)
abort (); abort ();
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, fprintf (rtl_dump_file,
"Duplicated bb %d (created bb %d)\n", "Duplicated bb %d (created bb %d)\n",
old_bb->index, new_bb->index); old_bb->index, new_bb->index);
RBI (new_bb)->visited = trace; new_bb->rbi->visited = trace;
RBI (new_bb)->next = RBI (bb)->next; new_bb->rbi->next = bb->rbi->next;
RBI (bb)->next = new_bb; bb->rbi->next = new_bb;
if (new_bb->index >= array_size || last_basic_block > array_size) if (new_bb->index >= array_size || last_basic_block > array_size)
{ {
...@@ -826,7 +826,7 @@ connect_traces (int n_traces, struct trace *traces) ...@@ -826,7 +826,7 @@ connect_traces (int n_traces, struct trace *traces)
} }
if (best) if (best)
{ {
RBI (best->src)->next = best->dest; best->src->rbi->next = best->dest;
t2 = bbd[best->src->index].end_of_trace; t2 = bbd[best->src->index].end_of_trace;
connected[t2] = true; connected[t2] = true;
if (rtl_dump_file) if (rtl_dump_file)
...@@ -840,7 +840,7 @@ connect_traces (int n_traces, struct trace *traces) ...@@ -840,7 +840,7 @@ connect_traces (int n_traces, struct trace *traces)
} }
if (last_trace >= 0) if (last_trace >= 0)
RBI (traces[last_trace].last)->next = traces[t2].first; traces[last_trace].last->rbi->next = traces[t2].first;
last_trace = t; last_trace = t;
/* Find the successor traces. */ /* Find the successor traces. */
...@@ -876,7 +876,7 @@ connect_traces (int n_traces, struct trace *traces) ...@@ -876,7 +876,7 @@ connect_traces (int n_traces, struct trace *traces)
best->src->index, best->dest->index); best->src->index, best->dest->index);
} }
t = bbd[best->dest->index].start_of_trace; t = bbd[best->dest->index].start_of_trace;
RBI (traces[last_trace].last)->next = traces[t].first; traces[last_trace].last->rbi->next = traces[t].first;
connected[t] = true; connected[t] = true;
last_trace = t; last_trace = t;
} }
...@@ -964,7 +964,7 @@ connect_traces (int n_traces, struct trace *traces) ...@@ -964,7 +964,7 @@ connect_traces (int n_traces, struct trace *traces)
if (next_bb && next_bb != EXIT_BLOCK_PTR) if (next_bb && next_bb != EXIT_BLOCK_PTR)
{ {
t = bbd[next_bb->index].start_of_trace; t = bbd[next_bb->index].start_of_trace;
RBI (traces[last_trace].last)->next = traces[t].first; traces[last_trace].last->rbi->next = traces[t].first;
connected[t] = true; connected[t] = true;
last_trace = t; last_trace = t;
} }
...@@ -982,7 +982,7 @@ connect_traces (int n_traces, struct trace *traces) ...@@ -982,7 +982,7 @@ connect_traces (int n_traces, struct trace *traces)
basic_block bb; basic_block bb;
fprintf (rtl_dump_file, "Final order:\n"); fprintf (rtl_dump_file, "Final order:\n");
for (bb = traces[0].first; bb; bb = RBI (bb)->next) for (bb = traces[0].first; bb; bb = bb->rbi->next)
fprintf (rtl_dump_file, "%d ", bb->index); fprintf (rtl_dump_file, "%d ", bb->index);
fprintf (rtl_dump_file, "\n"); fprintf (rtl_dump_file, "\n");
fflush (rtl_dump_file); fflush (rtl_dump_file);
...@@ -1064,7 +1064,7 @@ reorder_basic_blocks (void) ...@@ -1064,7 +1064,7 @@ reorder_basic_blocks (void)
if ((* targetm.cannot_modify_jumps_p) ()) if ((* targetm.cannot_modify_jumps_p) ())
return; return;
cfg_layout_initialize (NULL); cfg_layout_initialize ();
set_edge_can_fallthru_flag (); set_edge_can_fallthru_flag ();
mark_dfs_back_edges (); mark_dfs_back_edges ();
......
...@@ -113,7 +113,8 @@ struct basic_block_def entry_exit_blocks[2] ...@@ -113,7 +113,8 @@ struct basic_block_def entry_exit_blocks[2]
NULL, /* loop_father */ NULL, /* loop_father */
0, /* count */ 0, /* count */
0, /* frequency */ 0, /* frequency */
0 /* flags */ 0, /* flags */
NULL /* rbi */
}, },
{ {
NULL, /* head */ NULL, /* head */
...@@ -134,7 +135,8 @@ struct basic_block_def entry_exit_blocks[2] ...@@ -134,7 +135,8 @@ struct basic_block_def entry_exit_blocks[2]
NULL, /* loop_father */ NULL, /* loop_father */
0, /* count */ 0, /* count */
0, /* frequency */ 0, /* frequency */
0 /* flags */ 0, /* flags */
NULL /* rbi */
} }
}; };
......
...@@ -104,12 +104,12 @@ bool ...@@ -104,12 +104,12 @@ bool
can_fallthru (basic_block src, basic_block target) can_fallthru (basic_block src, basic_block target)
{ {
rtx insn = src->end; rtx insn = src->end;
rtx insn2 = target->head; rtx insn2 = target == EXIT_BLOCK_PTR ? NULL : target->head;
if (src->next_bb != target) if (src->next_bb != target)
return 0; return 0;
if (!active_insn_p (insn2)) if (insn2 && !active_insn_p (insn2))
insn2 = next_active_insn (insn2); insn2 = next_active_insn (insn2);
/* ??? Later we may add code to move jump tables offline. */ /* ??? Later we may add code to move jump tables offline. */
......
...@@ -77,7 +77,6 @@ static bool label_is_jump_target_p (rtx, rtx); ...@@ -77,7 +77,6 @@ static bool label_is_jump_target_p (rtx, rtx);
static bool tail_recursion_label_p (rtx); static bool tail_recursion_label_p (rtx);
static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block); static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block);
static void merge_blocks_move_successor_nojumps (basic_block, basic_block); static void merge_blocks_move_successor_nojumps (basic_block, basic_block);
static basic_block merge_blocks (edge,basic_block,basic_block, int);
static bool try_optimize_cfg (int); static bool try_optimize_cfg (int);
static bool try_simplify_condjump (basic_block); static bool try_simplify_condjump (basic_block);
static bool try_forward_edges (int, basic_block); static bool try_forward_edges (int, basic_block);
...@@ -704,7 +703,7 @@ merge_blocks_move_predecessor_nojumps (basic_block a, basic_block b) ...@@ -704,7 +703,7 @@ merge_blocks_move_predecessor_nojumps (basic_block a, basic_block b)
link_block (a, b->prev_bb); link_block (a, b->prev_bb);
/* Now blocks A and B are contiguous. Merge them. */ /* Now blocks A and B are contiguous. Merge them. */
merge_blocks_nomove (a, b); merge_blocks (a, b);
} }
/* Blocks A and B are to be merged into a single block. B has no outgoing /* Blocks A and B are to be merged into a single block. B has no outgoing
...@@ -758,7 +757,7 @@ merge_blocks_move_successor_nojumps (basic_block a, basic_block b) ...@@ -758,7 +757,7 @@ merge_blocks_move_successor_nojumps (basic_block a, basic_block b)
b->index, a->index); b->index, a->index);
/* Now blocks A and B are contiguous. Merge them. */ /* Now blocks A and B are contiguous. Merge them. */
merge_blocks_nomove (a, b); merge_blocks (a, b);
} }
/* Attempt to merge basic blocks that are potentially non-adjacent. /* Attempt to merge basic blocks that are potentially non-adjacent.
...@@ -774,7 +773,7 @@ merge_blocks_move_successor_nojumps (basic_block a, basic_block b) ...@@ -774,7 +773,7 @@ merge_blocks_move_successor_nojumps (basic_block a, basic_block b)
relative ordering of these two. Hopefully it is not too common. */ relative ordering of these two. Hopefully it is not too common. */
static basic_block static basic_block
merge_blocks (edge e, basic_block b, basic_block c, int mode) merge_blocks_move (edge e, basic_block b, basic_block c, int mode)
{ {
basic_block next; basic_block next;
/* If C has a tail recursion label, do not merge. There is no /* If C has a tail recursion label, do not merge. There is no
...@@ -790,7 +789,7 @@ merge_blocks (edge e, basic_block b, basic_block c, int mode) ...@@ -790,7 +789,7 @@ merge_blocks (edge e, basic_block b, basic_block c, int mode)
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
{ {
int b_index = b->index, c_index = c->index; int b_index = b->index, c_index = c->index;
merge_blocks_nomove (b, c); merge_blocks (b, c);
update_forwarder_flag (b); update_forwarder_flag (b);
if (rtl_dump_file) if (rtl_dump_file)
...@@ -1686,7 +1685,8 @@ try_optimize_cfg (int mode) ...@@ -1686,7 +1685,8 @@ try_optimize_cfg (int mode)
b->index); b->index);
delete_block (b); delete_block (b);
changed = true; if (!(mode & CLEANUP_CFGLAYOUT))
changed = true;
b = c; b = c;
} }
...@@ -1712,15 +1712,24 @@ try_optimize_cfg (int mode) ...@@ -1712,15 +1712,24 @@ try_optimize_cfg (int mode)
{ {
rtx label = b->head; rtx label = b->head;
b->head = NEXT_INSN (b->head);
delete_insn_chain (label, label); delete_insn_chain (label, label);
/* In the case label is undeletable, move it after the
BASIC_BLOCK note. */
if (NOTE_LINE_NUMBER (b->head) == NOTE_INSN_DELETED_LABEL)
{
rtx bb_note = NEXT_INSN (b->head);
reorder_insns_nobb (label, label, bb_note);
b->head = bb_note;
}
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "Deleted label in block %i.\n", fprintf (rtl_dump_file, "Deleted label in block %i.\n",
b->index); b->index);
} }
/* If we fall through an empty block, we can remove it. */ /* If we fall through an empty block, we can remove it. */
if (b->pred->pred_next == NULL if (!(mode & CLEANUP_CFGLAYOUT)
&& b->pred->pred_next == NULL
&& (b->pred->flags & EDGE_FALLTHRU) && (b->pred->flags & EDGE_FALLTHRU)
&& GET_CODE (b->head) != CODE_LABEL && GET_CODE (b->head) != CODE_LABEL
&& FORWARDER_BLOCK_P (b) && FORWARDER_BLOCK_P (b)
...@@ -1746,21 +1755,39 @@ try_optimize_cfg (int mode) ...@@ -1746,21 +1755,39 @@ try_optimize_cfg (int mode)
&& !(s->flags & EDGE_COMPLEX) && !(s->flags & EDGE_COMPLEX)
&& (c = s->dest) != EXIT_BLOCK_PTR && (c = s->dest) != EXIT_BLOCK_PTR
&& c->pred->pred_next == NULL && c->pred->pred_next == NULL
&& b != c && b != c)
/* If the jump insn has side effects, {
we can't kill the edge. */ /* When not in cfg_layout mode use code aware of reordering
&& (GET_CODE (b->end) != JUMP_INSN INSN. This code possibly creates new basic blocks so it
|| (flow2_completed does not fit merge_blocks interface and is kept here in
? simplejump_p (b->end) hope that it will become useless once more of compiler
: onlyjump_p (b->end))) is transformed to use cfg_layout mode. */
&& (next = merge_blocks (s, b, c, mode)))
{ if ((mode & CLEANUP_CFGLAYOUT)
b = next; && can_merge_blocks_p (b, c))
changed_here = true; {
merge_blocks (b, c);
update_forwarder_flag (b);
changed_here = true;
}
else if (!(mode & CLEANUP_CFGLAYOUT)
/* If the jump insn has side effects,
we can't kill the edge. */
&& (GET_CODE (b->end) != JUMP_INSN
|| (flow2_completed
? simplejump_p (b->end)
: onlyjump_p (b->end)))
&& (next = merge_blocks_move (s, b, c, mode)))
{
b = next;
changed_here = true;
}
} }
/* Simplify branch over branch. */ /* Simplify branch over branch. */
if ((mode & CLEANUP_EXPENSIVE) && try_simplify_condjump (b)) if ((mode & CLEANUP_EXPENSIVE)
&& !(mode & CLEANUP_CFGLAYOUT)
&& try_simplify_condjump (b))
changed_here = true; changed_here = true;
/* If B has a single outgoing edge, but uses a /* If B has a single outgoing edge, but uses a
......
...@@ -31,6 +31,9 @@ struct cfg_hooks ...@@ -31,6 +31,9 @@ struct cfg_hooks
/* Basic CFG manipulation. */ /* Basic CFG manipulation. */
/* Return new basic block */
basic_block (*create_basic_block) PARAMS ((void *head, void *end, basic_block after));
/* Redirect edge E to the given basic block B and update underlying program /* Redirect edge E to the given basic block B and update underlying program
representation. Returns false when edge is not easily redirectable for representation. Returns false when edge is not easily redirectable for
whatever reason. */ whatever reason. */
...@@ -47,6 +50,12 @@ struct cfg_hooks ...@@ -47,6 +50,12 @@ struct cfg_hooks
/* Split basic block B after specified instruction I. */ /* Split basic block B after specified instruction I. */
edge (*split_block) (basic_block b, void * i); edge (*split_block) (basic_block b, void * i);
/* Return true when blocks A and B can be merged into single basic block. */
bool (*can_merge_blocks_p) PARAMS ((basic_block a, basic_block b));
/* Merge blocks A and B. */
void (*merge_blocks) PARAMS ((basic_block a, basic_block b));
/* Higher level functions representable by primitive operations above if /* Higher level functions representable by primitive operations above if
we didn't have some oddities in RTL and Tree representations. */ we didn't have some oddities in RTL and Tree representations. */
basic_block (*cfgh_split_edge) (edge); basic_block (*cfgh_split_edge) (edge);
...@@ -57,6 +66,9 @@ struct cfg_hooks ...@@ -57,6 +66,9 @@ struct cfg_hooks
#define split_block(e,i) cfg_hooks->split_block (e,i) #define split_block(e,i) cfg_hooks->split_block (e,i)
#define delete_block(b) cfg_hooks->delete_block (b) #define delete_block(b) cfg_hooks->delete_block (b)
#define split_edge(e) cfg_hooks->cfgh_split_edge (e) #define split_edge(e) cfg_hooks->cfgh_split_edge (e)
#define create_basic_block(h,e,a) cfg_hooks->create_basic_block (h,e,a)
#define can_merge_blocks_p(a,b) cfg_hooks->can_merge_blocks_p (a,b)
#define merge_blocks(a,b) cfg_hooks->merge_blocks (a,b)
/* Hooks containers. */ /* Hooks containers. */
extern struct cfg_hooks rtl_cfg_hooks; extern struct cfg_hooks rtl_cfg_hooks;
......
...@@ -34,13 +34,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -34,13 +34,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "cfgloop.h" #include "cfgloop.h"
#include "target.h" #include "target.h"
#include "ggc.h" #include "ggc.h"
#include "alloc-pool.h"
/* The contents of the current function definition are allocated /* The contents of the current function definition are allocated
in this obstack, and all are freed at the end of the function. */ in this obstack, and all are freed at the end of the function. */
extern struct obstack flow_obstack; extern struct obstack flow_obstack;
alloc_pool cfg_layout_pool;
/* Holds the interesting trailing notes for the function. */ /* Holds the interesting trailing notes for the function. */
rtx cfg_layout_function_footer; rtx cfg_layout_function_footer, cfg_layout_function_header;
static rtx skip_insns_after_block (basic_block); static rtx skip_insns_after_block (basic_block);
static void record_effective_endpoints (void); static void record_effective_endpoints (void);
...@@ -51,7 +54,6 @@ static void set_block_levels (tree, int); ...@@ -51,7 +54,6 @@ static void set_block_levels (tree, int);
static void change_scope (rtx, tree, tree); static void change_scope (rtx, tree, tree);
void verify_insn_chain (void); void verify_insn_chain (void);
static void cleanup_unconditional_jumps (struct loops *);
static void fixup_fallthru_exit_predecessor (void); static void fixup_fallthru_exit_predecessor (void);
static rtx duplicate_insn_chain (rtx, rtx); static rtx duplicate_insn_chain (rtx, rtx);
static void break_superblocks (void); static void break_superblocks (void);
...@@ -189,19 +191,38 @@ label_for_bb (basic_block bb) ...@@ -189,19 +191,38 @@ label_for_bb (basic_block bb)
static void static void
record_effective_endpoints (void) record_effective_endpoints (void)
{ {
rtx next_insn = get_insns (); rtx next_insn;
basic_block bb; basic_block bb;
rtx insn;
for (insn = get_insns ();
NEXT_INSN (insn) && GET_CODE (insn) == NOTE;
insn = NEXT_INSN (insn))
{
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
{
insn = NULL;
break;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
break;
}
if (insn)
cfg_layout_function_header = unlink_insn_chain (get_insns (), insn);
else
cfg_layout_function_header = NULL_RTX;
next_insn = get_insns ();
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
{ {
rtx end; rtx end;
if (PREV_INSN (bb->head) && next_insn != bb->head) if (PREV_INSN (bb->head) && next_insn != bb->head)
RBI (bb)->header = unlink_insn_chain (next_insn, bb->rbi->header = unlink_insn_chain (next_insn,
PREV_INSN (bb->head)); PREV_INSN (bb->head));
end = skip_insns_after_block (bb); end = skip_insns_after_block (bb);
if (NEXT_INSN (bb->end) && bb->end != end) if (NEXT_INSN (bb->end) && bb->end != end)
RBI (bb)->footer = unlink_insn_chain (NEXT_INSN (bb->end), end); bb->rbi->footer = unlink_insn_chain (NEXT_INSN (bb->end), end);
next_insn = NEXT_INSN (bb->end); next_insn = NEXT_INSN (bb->end);
} }
...@@ -529,21 +550,29 @@ fixup_reorder_chain (void) ...@@ -529,21 +550,29 @@ fixup_reorder_chain (void)
int index; int index;
rtx insn = NULL; rtx insn = NULL;
if (cfg_layout_function_header)
{
set_first_insn (cfg_layout_function_header);
insn = cfg_layout_function_header;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
}
/* First do the bulk reordering -- rechain the blocks without regard to /* First do the bulk reordering -- rechain the blocks without regard to
the needed changes to jumps and labels. */ the needed changes to jumps and labels. */
for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0; for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
bb != 0; bb != 0;
bb = RBI (bb)->next, index++) bb = bb->rbi->next, index++)
{ {
if (RBI (bb)->header) if (bb->rbi->header)
{ {
if (insn) if (insn)
NEXT_INSN (insn) = RBI (bb)->header; NEXT_INSN (insn) = bb->rbi->header;
else else
set_first_insn (RBI (bb)->header); set_first_insn (bb->rbi->header);
PREV_INSN (RBI (bb)->header) = insn; PREV_INSN (bb->rbi->header) = insn;
insn = RBI (bb)->header; insn = bb->rbi->header;
while (NEXT_INSN (insn)) while (NEXT_INSN (insn))
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
} }
...@@ -553,10 +582,10 @@ fixup_reorder_chain (void) ...@@ -553,10 +582,10 @@ fixup_reorder_chain (void)
set_first_insn (bb->head); set_first_insn (bb->head);
PREV_INSN (bb->head) = insn; PREV_INSN (bb->head) = insn;
insn = bb->end; insn = bb->end;
if (RBI (bb)->footer) if (bb->rbi->footer)
{ {
NEXT_INSN (insn) = RBI (bb)->footer; NEXT_INSN (insn) = bb->rbi->footer;
PREV_INSN (RBI (bb)->footer) = insn; PREV_INSN (bb->rbi->footer) = insn;
while (NEXT_INSN (insn)) while (NEXT_INSN (insn))
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
} }
...@@ -580,7 +609,7 @@ fixup_reorder_chain (void) ...@@ -580,7 +609,7 @@ fixup_reorder_chain (void)
/* Now add jumps and labels as needed to match the blocks new /* Now add jumps and labels as needed to match the blocks new
outgoing edges. */ outgoing edges. */
for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = RBI (bb)->next) for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = bb->rbi->next)
{ {
edge e_fall, e_taken, e; edge e_fall, e_taken, e;
rtx bb_end_insn; rtx bb_end_insn;
...@@ -604,8 +633,8 @@ fixup_reorder_chain (void) ...@@ -604,8 +633,8 @@ fixup_reorder_chain (void)
if (any_condjump_p (bb_end_insn)) if (any_condjump_p (bb_end_insn))
{ {
/* If the old fallthru is still next, nothing to do. */ /* If the old fallthru is still next, nothing to do. */
if (RBI (bb)->next == e_fall->dest if (bb->rbi->next == e_fall->dest
|| (!RBI (bb)->next || (!bb->rbi->next
&& e_fall->dest == EXIT_BLOCK_PTR)) && e_fall->dest == EXIT_BLOCK_PTR))
continue; continue;
...@@ -645,7 +674,7 @@ fixup_reorder_chain (void) ...@@ -645,7 +674,7 @@ fixup_reorder_chain (void)
such as happens at the very end of a function, then we'll such as happens at the very end of a function, then we'll
need to add a new unconditional jump. Choose the taken need to add a new unconditional jump. Choose the taken
edge based on known or assumed probability. */ edge based on known or assumed probability. */
else if (RBI (bb)->next != e_taken->dest) else if (bb->rbi->next != e_taken->dest)
{ {
rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0); rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
...@@ -684,7 +713,7 @@ fixup_reorder_chain (void) ...@@ -684,7 +713,7 @@ fixup_reorder_chain (void)
#ifdef CASE_DROPS_THROUGH #ifdef CASE_DROPS_THROUGH
/* Except for VAX. Since we didn't have predication for the /* Except for VAX. Since we didn't have predication for the
tablejump, the fallthru block should not have moved. */ tablejump, the fallthru block should not have moved. */
if (RBI (bb)->next == e_fall->dest) if (bb->rbi->next == e_fall->dest)
continue; continue;
bb_end_insn = skip_insns_after_block (bb); bb_end_insn = skip_insns_after_block (bb);
#else #else
...@@ -701,11 +730,11 @@ fixup_reorder_chain (void) ...@@ -701,11 +730,11 @@ fixup_reorder_chain (void)
continue; continue;
/* If the fallthru block is still next, nothing to do. */ /* If the fallthru block is still next, nothing to do. */
if (RBI (bb)->next == e_fall->dest) if (bb->rbi->next == e_fall->dest)
continue; continue;
/* A fallthru to exit block. */ /* A fallthru to exit block. */
if (!RBI (bb)->next && e_fall->dest == EXIT_BLOCK_PTR) if (!bb->rbi->next && e_fall->dest == EXIT_BLOCK_PTR)
continue; continue;
} }
...@@ -713,10 +742,10 @@ fixup_reorder_chain (void) ...@@ -713,10 +742,10 @@ fixup_reorder_chain (void)
nb = force_nonfallthru (e_fall); nb = force_nonfallthru (e_fall);
if (nb) if (nb)
{ {
alloc_aux_for_block (nb, sizeof (struct reorder_block_def)); cfg_layout_initialize_rbi (nb);
RBI (nb)->visited = 1; nb->rbi->visited = 1;
RBI (nb)->next = RBI (bb)->next; nb->rbi->next = bb->rbi->next;
RBI (bb)->next = nb; bb->rbi->next = nb;
/* Don't process this new block. */ /* Don't process this new block. */
bb = nb; bb = nb;
} }
...@@ -727,12 +756,12 @@ fixup_reorder_chain (void) ...@@ -727,12 +756,12 @@ fixup_reorder_chain (void)
if (rtl_dump_file) if (rtl_dump_file)
{ {
fprintf (rtl_dump_file, "Reordered sequence:\n"); fprintf (rtl_dump_file, "Reordered sequence:\n");
for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0; bb; bb = RBI (bb)->next, index ++) for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0; bb; bb = bb->rbi->next, index ++)
{ {
fprintf (rtl_dump_file, " %i ", index); fprintf (rtl_dump_file, " %i ", index);
if (RBI (bb)->original) if (bb->rbi->original)
fprintf (rtl_dump_file, "duplicate of %i ", fprintf (rtl_dump_file, "duplicate of %i ",
RBI (bb)->original->index); bb->rbi->original->index);
else if (forwarder_block_p (bb) && GET_CODE (bb->head) != CODE_LABEL) else if (forwarder_block_p (bb) && GET_CODE (bb->head) != CODE_LABEL)
fprintf (rtl_dump_file, "compensation "); fprintf (rtl_dump_file, "compensation ");
else else
...@@ -745,7 +774,7 @@ fixup_reorder_chain (void) ...@@ -745,7 +774,7 @@ fixup_reorder_chain (void)
bb = ENTRY_BLOCK_PTR->next_bb; bb = ENTRY_BLOCK_PTR->next_bb;
index = 0; index = 0;
for (; bb; prev_bb = bb, bb = RBI (bb)->next, index ++) for (; bb; prev_bb = bb, bb = bb->rbi->next, index ++)
{ {
bb->index = index; bb->index = index;
BASIC_BLOCK (index) = bb; BASIC_BLOCK (index) = bb;
...@@ -755,6 +784,16 @@ fixup_reorder_chain (void) ...@@ -755,6 +784,16 @@ fixup_reorder_chain (void)
} }
prev_bb->next_bb = EXIT_BLOCK_PTR; prev_bb->next_bb = EXIT_BLOCK_PTR;
EXIT_BLOCK_PTR->prev_bb = prev_bb; EXIT_BLOCK_PTR->prev_bb = prev_bb;
/* Anoying special case - jump around dead jumptables left in the code. */
FOR_EACH_BB (bb)
{
edge e;
for (e = bb->succ; e && !(e->flags & EDGE_FALLTHRU); e = e->succ_next)
continue;
if (e && !can_fallthru (e->src, e->dest))
force_nonfallthru (e);
}
} }
/* Perform sanity checks on the insn chain. /* Perform sanity checks on the insn chain.
...@@ -788,87 +827,6 @@ verify_insn_chain (void) ...@@ -788,87 +827,6 @@ verify_insn_chain (void)
abort (); abort ();
} }
/* Remove any unconditional jumps and forwarder block creating fallthru
edges instead. During BB reordering, fallthru edges are not required
to target next basic block in the linear CFG layout, so the unconditional
jumps are not needed. If LOOPS is not null, also update loop structure &
dominators. */
static void
cleanup_unconditional_jumps (struct loops *loops)
{
basic_block bb;
FOR_EACH_BB (bb)
{
if (!bb->succ)
continue;
if (bb->succ->flags & EDGE_FALLTHRU)
continue;
if (!bb->succ->succ_next)
{
rtx insn;
if (GET_CODE (bb->head) != CODE_LABEL && forwarder_block_p (bb)
&& bb->prev_bb != ENTRY_BLOCK_PTR)
{
basic_block prev = bb->prev_bb;
if (rtl_dump_file)
fprintf (rtl_dump_file, "Removing forwarder BB %i\n",
bb->index);
if (loops)
{
/* bb cannot be loop header, as it only has one entry
edge. It could be a loop latch. */
if (bb->loop_father->header == bb)
abort ();
if (bb->loop_father->latch == bb)
bb->loop_father->latch = bb->pred->src;
if (get_immediate_dominator
(loops->cfg.dom, bb->succ->dest) == bb)
set_immediate_dominator
(loops->cfg.dom, bb->succ->dest, bb->pred->src);
remove_bb_from_loops (bb);
delete_from_dominance_info (loops->cfg.dom, bb);
}
redirect_edge_succ_nodup (bb->pred, bb->succ->dest);
delete_block (bb);
bb = prev;
}
else if (simplejump_p (bb->end))
{
rtx jump = bb->end;
if (rtl_dump_file)
fprintf (rtl_dump_file, "Removing jump %i in BB %i\n",
INSN_UID (jump), bb->index);
delete_insn (jump);
bb->succ->flags |= EDGE_FALLTHRU;
}
else
continue;
insn = NEXT_INSN (bb->end);
while (insn
&& (GET_CODE (insn) != NOTE
|| NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK))
{
rtx next = NEXT_INSN (insn);
if (GET_CODE (insn) == BARRIER)
delete_barrier (insn);
insn = next;
}
}
}
}
/* The block falling through to exit must be the last one in the /* The block falling through to exit must be the last one in the
reordered chain. Ensure that this condition is met. */ reordered chain. Ensure that this condition is met. */
static void static void
...@@ -881,19 +839,19 @@ fixup_fallthru_exit_predecessor (void) ...@@ -881,19 +839,19 @@ fixup_fallthru_exit_predecessor (void)
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
bb = e->src; bb = e->src;
if (bb && RBI (bb)->next) if (bb && bb->rbi->next)
{ {
basic_block c = ENTRY_BLOCK_PTR->next_bb; basic_block c = ENTRY_BLOCK_PTR->next_bb;
while (RBI (c)->next != bb) while (c->rbi->next != bb)
c = RBI (c)->next; c = c->rbi->next;
RBI (c)->next = RBI (bb)->next; c->rbi->next = bb->rbi->next;
while (RBI (c)->next) while (c->rbi->next)
c = RBI (c)->next; c = c->rbi->next;
RBI (c)->next = bb; c->rbi->next = bb;
RBI (bb)->next = NULL; bb->rbi->next = NULL;
} }
} }
...@@ -1050,26 +1008,25 @@ cfg_layout_duplicate_bb (basic_block bb, edge e) ...@@ -1050,26 +1008,25 @@ cfg_layout_duplicate_bb (basic_block bb, edge e)
new_bb = create_basic_block (insn, new_bb = create_basic_block (insn,
insn ? get_last_insn () : NULL, insn ? get_last_insn () : NULL,
EXIT_BLOCK_PTR->prev_bb); EXIT_BLOCK_PTR->prev_bb);
alloc_aux_for_block (new_bb, sizeof (struct reorder_block_def));
if (RBI (bb)->header) if (bb->rbi->header)
{ {
insn = RBI (bb)->header; insn = bb->rbi->header;
while (NEXT_INSN (insn)) while (NEXT_INSN (insn))
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
insn = duplicate_insn_chain (RBI (bb)->header, insn); insn = duplicate_insn_chain (bb->rbi->header, insn);
if (insn) if (insn)
RBI (new_bb)->header = unlink_insn_chain (insn, get_last_insn ()); new_bb->rbi->header = unlink_insn_chain (insn, get_last_insn ());
} }
if (RBI (bb)->footer) if (bb->rbi->footer)
{ {
insn = RBI (bb)->footer; insn = bb->rbi->footer;
while (NEXT_INSN (insn)) while (NEXT_INSN (insn))
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
insn = duplicate_insn_chain (RBI (bb)->footer, insn); insn = duplicate_insn_chain (bb->rbi->footer, insn);
if (insn) if (insn)
RBI (new_bb)->footer = unlink_insn_chain (insn, get_last_insn ()); new_bb->rbi->footer = unlink_insn_chain (insn, get_last_insn ());
} }
if (bb->global_live_at_start) if (bb->global_live_at_start)
...@@ -1113,25 +1070,42 @@ cfg_layout_duplicate_bb (basic_block bb, edge e) ...@@ -1113,25 +1070,42 @@ cfg_layout_duplicate_bb (basic_block bb, edge e)
if (bb->frequency < 0) if (bb->frequency < 0)
bb->frequency = 0; bb->frequency = 0;
RBI (new_bb)->original = bb; new_bb->rbi->original = bb;
RBI (bb)->copy = new_bb; bb->rbi->copy = new_bb;
return new_bb; return new_bb;
} }
void
cfg_layout_initialize_rbi (bb)
basic_block bb;
{
if (bb->rbi)
abort ();
bb->rbi = pool_alloc (cfg_layout_pool);
memset (bb->rbi, 0, sizeof (struct reorder_block_def));
}
/* Main entry point to this module - initialize the datastructures for /* Main entry point to this module - initialize the datastructures for
CFG layout changes. It keeps LOOPS up-to-date if not null. */ CFG layout changes. It keeps LOOPS up-to-date if not null. */
void void
cfg_layout_initialize (struct loops *loops) cfg_layout_initialize ()
{ {
basic_block bb;
/* Our algorithm depends on fact that there are now dead jumptables /* Our algorithm depends on fact that there are now dead jumptables
around the code. */ around the code. */
alloc_aux_for_blocks (sizeof (struct reorder_block_def)); cfg_layout_pool =
cfg_layout_rtl_register_cfg_hooks (); create_alloc_pool ("cfg layout pool", sizeof (struct reorder_block_def),
n_basic_blocks + 2);
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
cfg_layout_initialize_rbi (bb);
cleanup_unconditional_jumps (loops); cfg_layout_rtl_register_cfg_hooks ();
record_effective_endpoints (); record_effective_endpoints ();
cleanup_cfg (CLEANUP_CFGLAYOUT);
} }
/* Splits superblocks. */ /* Splits superblocks. */
...@@ -1169,6 +1143,8 @@ break_superblocks (void) ...@@ -1169,6 +1143,8 @@ break_superblocks (void)
void void
cfg_layout_finalize (void) cfg_layout_finalize (void)
{ {
basic_block bb;
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
verify_flow_info (); verify_flow_info ();
#endif #endif
...@@ -1180,7 +1156,9 @@ cfg_layout_finalize (void) ...@@ -1180,7 +1156,9 @@ cfg_layout_finalize (void)
verify_insn_chain (); verify_insn_chain ();
#endif #endif
free_aux_for_blocks (); free_alloc_pool (cfg_layout_pool);
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
bb->rbi = NULL;
break_superblocks (); break_superblocks ();
......
...@@ -33,13 +33,12 @@ typedef struct reorder_block_def ...@@ -33,13 +33,12 @@ typedef struct reorder_block_def
int visited; int visited;
} *reorder_block_def; } *reorder_block_def;
#define RBI(BB) ((reorder_block_def) (BB)->aux)
extern rtx cfg_layout_function_footer; extern rtx cfg_layout_function_footer;
extern void cfg_layout_initialize (struct loops *); extern void cfg_layout_initialize (void);
extern void cfg_layout_finalize (void); extern void cfg_layout_finalize (void);
extern bool cfg_layout_can_duplicate_bb_p (basic_block); extern bool cfg_layout_can_duplicate_bb_p (basic_block);
extern basic_block cfg_layout_duplicate_bb (basic_block, edge); extern basic_block cfg_layout_duplicate_bb (basic_block, edge);
extern void insn_locators_initialize (void); extern void insn_locators_initialize (void);
extern void reemit_insn_block_notes (void); extern void reemit_insn_block_notes (void);
extern void cfg_layout_initialize_rbi (basic_block);
...@@ -294,8 +294,7 @@ extern int fix_loop_placement (struct loop *); ...@@ -294,8 +294,7 @@ extern int fix_loop_placement (struct loop *);
enum enum
{ {
CP_SIMPLE_PREHEADERS = 1, CP_SIMPLE_PREHEADERS = 1
CP_INSIDE_CFGLAYOUT = 2
}; };
extern void create_preheaders (struct loops *, int); extern void create_preheaders (struct loops *, int);
......
...@@ -860,7 +860,7 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge, ...@@ -860,7 +860,7 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge,
/* Duplicate. */ /* Duplicate. */
bb = bbs[i]; bb = bbs[i];
new_bb = (*new_bbs)[i] = cfg_layout_duplicate_bb (bb, NULL); new_bb = (*new_bbs)[i] = cfg_layout_duplicate_bb (bb, NULL);
RBI (new_bb)->duplicated = 1; new_bb->rbi->duplicated = 1;
/* Add to loop. */ /* Add to loop. */
add_bb_to_loop (new_bb, bb->loop_father->copy); add_bb_to_loop (new_bb, bb->loop_father->copy);
add_to_dominance_info (loops->cfg.dom, new_bb); add_to_dominance_info (loops->cfg.dom, new_bb);
...@@ -886,7 +886,7 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge, ...@@ -886,7 +886,7 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge,
{ {
/* For anything else than loop header, just copy it. */ /* For anything else than loop header, just copy it. */
dom_bb = get_immediate_dominator (loops->cfg.dom, bb); dom_bb = get_immediate_dominator (loops->cfg.dom, bb);
dom_bb = RBI (dom_bb)->copy; dom_bb = dom_bb->rbi->copy;
} }
else else
{ {
...@@ -910,7 +910,7 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge, ...@@ -910,7 +910,7 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge,
e_pred = e->pred_next; e_pred = e->pred_next;
if (!RBI (src)->duplicated) if (!src->rbi->duplicated)
continue; continue;
/* Leads to copied loop and it is not latch edge, redirect it. */ /* Leads to copied loop and it is not latch edge, redirect it. */
...@@ -919,24 +919,24 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge, ...@@ -919,24 +919,24 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge,
if (add_irreducible_flag if (add_irreducible_flag
&& (bb->loop_father == header->loop_father && (bb->loop_father == header->loop_father
|| RBI (src)->original->loop_father == header->loop_father)) || src->rbi->original->loop_father == header->loop_father))
e->flags |= EDGE_IRREDUCIBLE_LOOP; e->flags |= EDGE_IRREDUCIBLE_LOOP;
} }
} }
/* Redirect header edge. */ /* Redirect header edge. */
bb = RBI (latch_edge->src)->copy; bb = latch_edge->src->rbi->copy;
for (e = bb->succ; e->dest != latch_edge->dest; e = e->succ_next); for (e = bb->succ; e->dest != latch_edge->dest; e = e->succ_next);
*header_edge = e; *header_edge = e;
loop_redirect_edge (*header_edge, header); loop_redirect_edge (*header_edge, header);
/* Redirect entry to copy of header. */ /* Redirect entry to copy of header. */
loop_redirect_edge (entry, RBI (header)->copy); loop_redirect_edge (entry, header->rbi->copy);
*copy_header_edge = entry; *copy_header_edge = entry;
/* Clear information about duplicates. */ /* Clear information about duplicates. */
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
RBI ((*new_bbs)[i])->duplicated = 0; (*new_bbs)[i]->rbi->duplicated = 0;
} }
/* Check whether LOOP's body can be duplicated. */ /* Check whether LOOP's body can be duplicated. */
...@@ -995,7 +995,7 @@ record_exit_edges (edge orig, basic_block *bbs, int nbbs, edge *to_remove, ...@@ -995,7 +995,7 @@ record_exit_edges (edge orig, basic_block *bbs, int nbbs, edge *to_remove,
return; return;
} }
for (e = RBI (orig->src)->copy->succ; e; e = e->succ_next) for (e = orig->src->rbi->copy->succ; e; e = e->succ_next)
if (e->dest == orig->dest) if (e->dest == orig->dest)
break; break;
if (!e) if (!e)
...@@ -1175,7 +1175,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, ...@@ -1175,7 +1175,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
copy_bbs (bbs, n, e, latch_edge, &new_bbs, loops, copy_bbs (bbs, n, e, latch_edge, &new_bbs, loops,
&e, &he, add_irreducible_flag); &e, &he, add_irreducible_flag);
if (is_latch) if (is_latch)
loop->latch = RBI (latch)->copy; loop->latch = latch->rbi->copy;
/* Record exit edges in this copy. */ /* Record exit edges in this copy. */
if (TEST_BIT (wont_exit, j + 1)) if (TEST_BIT (wont_exit, j + 1))
...@@ -1209,7 +1209,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, ...@@ -1209,7 +1209,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
if (!first_active_latch) if (!first_active_latch)
{ {
memcpy (first_active, new_bbs, n * sizeof (basic_block)); memcpy (first_active, new_bbs, n * sizeof (basic_block));
first_active_latch = RBI (latch)->copy; first_active_latch = latch->rbi->copy;
} }
free (new_bbs); free (new_bbs);
...@@ -1217,11 +1217,11 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, ...@@ -1217,11 +1217,11 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops,
/* Original loop header is dominated by latch copy /* Original loop header is dominated by latch copy
if we duplicated on its only entry edge. */ if we duplicated on its only entry edge. */
if (!is_latch && !header->pred->pred_next->pred_next) if (!is_latch && !header->pred->pred_next->pred_next)
set_immediate_dominator (loops->cfg.dom, header, RBI (latch)->copy); set_immediate_dominator (loops->cfg.dom, header, latch->rbi->copy);
if (is_latch && j == 0) if (is_latch && j == 0)
{ {
/* Update edge from latch. */ /* Update edge from latch. */
for (latch_edge = RBI (header)->copy->pred; for (latch_edge = header->rbi->copy->pred;
latch_edge->src != latch; latch_edge->src != latch;
latch_edge = latch_edge->pred_next); latch_edge = latch_edge->pred_next);
} }
...@@ -1409,33 +1409,20 @@ loop_split_edge_with (edge e, rtx insns, struct loops *loops) ...@@ -1409,33 +1409,20 @@ loop_split_edge_with (edge e, rtx insns, struct loops *loops)
/* Create basic block for it. */ /* Create basic block for it. */
new_bb = create_basic_block (NULL_RTX, NULL_RTX, EXIT_BLOCK_PTR->prev_bb); new_bb = split_edge (e);
add_to_dominance_info (loops->cfg.dom, new_bb); add_to_dominance_info (loops->cfg.dom, new_bb);
add_bb_to_loop (new_bb, loop_c); add_bb_to_loop (new_bb, loop_c);
new_bb->flags = insns ? BB_SUPERBLOCK : 0; new_bb->flags = insns ? BB_SUPERBLOCK : 0;
new_e = make_edge (new_bb, dest, EDGE_FALLTHRU); new_e = new_bb->succ;
new_e->probability = REG_BR_PROB_BASE;
new_e->count = e->count;
if (e->flags & EDGE_IRREDUCIBLE_LOOP) if (e->flags & EDGE_IRREDUCIBLE_LOOP)
{ {
new_bb->flags |= BB_IRREDUCIBLE_LOOP; new_bb->flags |= BB_IRREDUCIBLE_LOOP;
new_e->flags |= EDGE_IRREDUCIBLE_LOOP; new_e->flags |= EDGE_IRREDUCIBLE_LOOP;
} }
new_bb->count = e->count;
new_bb->frequency = EDGE_FREQUENCY (e);
redirect_edge_and_branch_force (e, new_bb);
alloc_aux_for_block (new_bb, sizeof (struct reorder_block_def));
if (insns) if (insns)
{ emit_insn_after (insns, new_bb->end);
start_sequence ();
emit_insn (insns);
insns = get_insns ();
end_sequence ();
emit_insn_after (insns, new_bb->end);
}
set_immediate_dominator (loops->cfg.dom, new_bb, src); set_immediate_dominator (loops->cfg.dom, new_bb, src);
set_immediate_dominator (loops->cfg.dom, dest, set_immediate_dominator (loops->cfg.dom, dest,
......
...@@ -23,20 +23,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -23,20 +23,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
that are aware of the RTL intermediate language. that are aware of the RTL intermediate language.
Available functionality: Available functionality:
- Basic CFG/RTL manipulation API documented in cfghooks.h
- CFG-aware instruction chain manipulation - CFG-aware instruction chain manipulation
delete_insn, delete_insn_chain delete_insn, delete_insn_chain
- Basic block manipulation - Edge splitting and committing to edges
create_basic_block, rtl_delete_block,rtl_split_block, insert_insn_on_edge, commit_edge_insertions
merge_blocks_nomove - CFG updating after insn simplification
purge_dead_edges, purge_all_dead_edges
Functions not supposed for generic use:
- Infrastructure to determine quickly basic block for insn - Infrastructure to determine quickly basic block for insn
compute_bb_for_insn, update_bb_for_insn, set_block_for_insn, compute_bb_for_insn, update_bb_for_insn, set_block_for_insn,
- Edge redirection with updating and optimizing of insn chain - Edge redirection with updating and optimizing of insn chain
block_label, redirect_edge_and_branch, block_label, tidy_fallthru_edge, force_nonfallthru */
redirect_edge_and_branch_force, tidy_fallthru_edge, force_nonfallthru
- Edge splitting and committing to edges
split_edge, insert_insn_on_edge, commit_edge_insertions
- CFG updating after constant propagation
purge_dead_edges, purge_all_dead_edges */
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
...@@ -73,7 +72,6 @@ rtx tail_recursion_label_list; ...@@ -73,7 +72,6 @@ rtx tail_recursion_label_list;
static int can_delete_note_p (rtx); static int can_delete_note_p (rtx);
static int can_delete_label_p (rtx); static int can_delete_label_p (rtx);
static void commit_one_edge_insertion (edge, int); static void commit_one_edge_insertion (edge, int);
static bool try_redirect_by_replacing_jump (edge, basic_block);
static rtx last_loop_beg_note (rtx); static rtx last_loop_beg_note (rtx);
static bool back_edge_of_syntactic_loop_p (basic_block, basic_block); static bool back_edge_of_syntactic_loop_p (basic_block, basic_block);
basic_block force_nonfallthru_and_redirect (edge, basic_block); basic_block force_nonfallthru_and_redirect (edge, basic_block);
...@@ -326,9 +324,10 @@ create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after) ...@@ -326,9 +324,10 @@ create_basic_block_structure (rtx head, rtx end, rtx bb_note, basic_block after)
create new empty basic block before HEAD. Both END and HEAD can be NULL to create new empty basic block before HEAD. Both END and HEAD can be NULL to
create basic block at the end of INSN chain. */ create basic block at the end of INSN chain. */
basic_block static basic_block
create_basic_block (rtx head, rtx end, basic_block after) rtl_create_basic_block (void *headp, void *endp, basic_block after)
{ {
rtx head = headp, end = endp;
basic_block bb; basic_block bb;
/* Place the new block just after the end. */ /* Place the new block just after the end. */
...@@ -340,6 +339,15 @@ create_basic_block (rtx head, rtx end, basic_block after) ...@@ -340,6 +339,15 @@ create_basic_block (rtx head, rtx end, basic_block after)
bb->aux = NULL; bb->aux = NULL;
return bb; return bb;
} }
static basic_block
cfg_layout_create_basic_block (void *head, void *end, basic_block after)
{
basic_block newbb = rtl_create_basic_block (head, end, after);
cfg_layout_initialize_rbi (newbb);
return newbb;
}
/* Delete the insns in a (non-live) block. We physically delete every /* Delete the insns in a (non-live) block. We physically delete every
non-deleted-note insn, and update the flow graph appropriately. non-deleted-note insn, and update the flow graph appropriately.
...@@ -517,16 +525,42 @@ rtl_split_block (basic_block bb, void *insnp) ...@@ -517,16 +525,42 @@ rtl_split_block (basic_block bb, void *insnp)
return new_edge; return new_edge;
} }
/* Assume that the code of basic block B has been merged into A.
Do corresponding CFG updates: redirect edges accordingly etc. */
static void
update_cfg_after_block_merging (basic_block a, basic_block b)
{
edge e;
/* Normally there should only be one successor of A and that is B, but
partway though the merge of blocks for conditional_execution we'll
be merging a TEST block with THEN and ELSE successors. Free the
whole lot of them and hope the caller knows what they're doing. */
while (a->succ)
remove_edge (a->succ);
/* Adjust the edges out of B for the new owner. */
for (e = b->succ; e; e = e->succ_next)
e->src = a;
a->succ = b->succ;
a->flags |= b->flags;
/* B hasn't quite yet ceased to exist. Attempt to prevent mishap. */
b->pred = b->succ = NULL;
a->global_live_at_end = b->global_live_at_end;
expunge_block (b);
}
/* Blocks A and B are to be merged into a single block A. The insns /* Blocks A and B are to be merged into a single block A. The insns
are already contiguous, hence `nomove'. */ are already contiguous. */
void static void
merge_blocks_nomove (basic_block a, basic_block b) rtl_merge_blocks (basic_block a, basic_block b)
{ {
rtx b_head = b->head, b_end = b->end, a_end = a->end; rtx b_head = b->head, b_end = b->end, a_end = a->end;
rtx del_first = NULL_RTX, del_last = NULL_RTX; rtx del_first = NULL_RTX, del_last = NULL_RTX;
int b_empty = 0; int b_empty = 0;
edge e;
/* If there was a CODE_LABEL beginning B, delete it. */ /* If there was a CODE_LABEL beginning B, delete it. */
if (GET_CODE (b_head) == CODE_LABEL) if (GET_CODE (b_head) == CODE_LABEL)
...@@ -585,24 +619,7 @@ merge_blocks_nomove (basic_block a, basic_block b) ...@@ -585,24 +619,7 @@ merge_blocks_nomove (basic_block a, basic_block b)
else if (GET_CODE (NEXT_INSN (a_end)) == BARRIER) else if (GET_CODE (NEXT_INSN (a_end)) == BARRIER)
del_first = NEXT_INSN (a_end); del_first = NEXT_INSN (a_end);
/* Normally there should only be one successor of A and that is B, but update_cfg_after_block_merging (a, b);
partway though the merge of blocks for conditional_execution we'll
be merging a TEST block with THEN and ELSE successors. Free the
whole lot of them and hope the caller knows what they're doing. */
while (a->succ)
remove_edge (a->succ);
/* Adjust the edges out of B for the new owner. */
for (e = b->succ; e; e = e->succ_next)
e->src = a;
a->succ = b->succ;
a->flags |= b->flags;
/* B hasn't quite yet ceased to exist. Attempt to prevent mishap. */
b->pred = b->succ = NULL;
a->global_live_at_end = b->global_live_at_end;
expunge_block (b);
/* Delete everything marked above as well as crap that might be /* Delete everything marked above as well as crap that might be
hanging out between the two blocks. */ hanging out between the two blocks. */
...@@ -623,6 +640,24 @@ merge_blocks_nomove (basic_block a, basic_block b) ...@@ -623,6 +640,24 @@ merge_blocks_nomove (basic_block a, basic_block b)
a->end = a_end; a->end = a_end;
} }
/* Return true when block A and B can be merged. */
static bool
rtl_can_merge_blocks (basic_block a,basic_block b)
{
/* There must be exactly one edge in between the blocks. */
return (a->succ && !a->succ->succ_next && a->succ->dest == b
&& !b->pred->pred_next && a != b
/* Must be simple edge. */
&& !(a->succ->flags & EDGE_COMPLEX)
&& a->next_bb == b
&& a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
/* If the jump insn has side effects,
we can't kill the edge. */
&& (GET_CODE (a->end) != JUMP_INSN
|| (flow2_completed
? simplejump_p (a->end) : onlyjump_p (a->end))));
}
/* Return the label in the head of basic block BLOCK. Create one if it doesn't /* Return the label in the head of basic block BLOCK. Create one if it doesn't
exist. */ exist. */
...@@ -647,7 +682,7 @@ block_label (basic_block block) ...@@ -647,7 +682,7 @@ block_label (basic_block block)
return values are equivalent to redirect_edge_and_branch. */ return values are equivalent to redirect_edge_and_branch. */
static bool static bool
try_redirect_by_replacing_jump (edge e, basic_block target) try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
{ {
basic_block src = e->src; basic_block src = e->src;
rtx insn = src->end, kill_from; rtx insn = src->end, kill_from;
...@@ -679,14 +714,38 @@ try_redirect_by_replacing_jump (edge e, basic_block target) ...@@ -679,14 +714,38 @@ try_redirect_by_replacing_jump (edge e, basic_block target)
#endif #endif
/* See if we can create the fallthru edge. */ /* See if we can create the fallthru edge. */
if (can_fallthru (src, target)) if (in_cfglayout || can_fallthru (src, target))
{ {
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "Removing jump %i.\n", INSN_UID (insn)); fprintf (rtl_dump_file, "Removing jump %i.\n", INSN_UID (insn));
fallthru = 1; fallthru = 1;
/* Selectively unlink whole insn chain. */ /* Selectively unlink whole insn chain. */
delete_insn_chain (kill_from, PREV_INSN (target->head)); if (in_cfglayout)
{
rtx insn = src->rbi->footer;
delete_insn_chain (kill_from, src->end);
/* Remove barriers but keep jumptables. */
while (insn)
{
if (GET_CODE (insn) == BARRIER)
{
if (PREV_INSN (insn))
NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
else
src->rbi->footer = NEXT_INSN (insn);
if (NEXT_INSN (insn))
PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
}
if (GET_CODE (insn) == CODE_LABEL)
break;
insn = NEXT_INSN (insn);
}
}
else
delete_insn_chain (kill_from, PREV_INSN (target->head));
} }
/* If this already is simplejump, redirect it. */ /* If this already is simplejump, redirect it. */
...@@ -782,36 +841,15 @@ last_loop_beg_note (rtx insn) ...@@ -782,36 +841,15 @@ last_loop_beg_note (rtx insn)
return last; return last;
} }
/* Attempt to change code to redirect edge E to TARGET. Don't do that on /* Redirect edge representing branch of (un)conditional jump or tablejump. */
expense of adding new instructions or reordering basic blocks.
Function can be also called with edge destination equivalent to the TARGET.
Then it should try the simplifications and do nothing if none is possible.
Return true if transformation succeeded. We still return false in case E
already destinated TARGET and we didn't managed to simplify instruction
stream. */
static bool static bool
rtl_redirect_edge_and_branch (edge e, basic_block target) redirect_branch_edge (edge e, basic_block target)
{ {
rtx tmp; rtx tmp;
rtx old_label = e->dest->head; rtx old_label = e->dest->head;
basic_block src = e->src; basic_block src = e->src;
rtx insn = src->end; rtx insn = src->end;
if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
return false;
if (try_redirect_by_replacing_jump (e, target))
return true;
/* Do this fast path late, as we want above code to simplify for cases
where called on single edge leaving basic block containing nontrivial
jump insn. */
else if (e->dest == target)
return false;
/* We can only redirect non-fallthru edges of jump insn. */ /* We can only redirect non-fallthru edges of jump insn. */
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
return false; return false;
...@@ -884,6 +922,37 @@ rtl_redirect_edge_and_branch (edge e, basic_block target) ...@@ -884,6 +922,37 @@ rtl_redirect_edge_and_branch (edge e, basic_block target)
if (e->dest != target) if (e->dest != target)
redirect_edge_succ_nodup (e, target); redirect_edge_succ_nodup (e, target);
return true;
}
/* Attempt to change code to redirect edge E to TARGET. Don't do that on
expense of adding new instructions or reordering basic blocks.
Function can be also called with edge destination equivalent to the TARGET.
Then it should try the simplifications and do nothing if none is possible.
Return true if transformation succeeded. We still return false in case E
already destinated TARGET and we didn't managed to simplify instruction
stream. */
static bool
rtl_redirect_edge_and_branch (e, target)
edge e;
basic_block target;
{
if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
return false;
if (try_redirect_by_replacing_jump (e, target, false))
return true;
/* Do this fast path late, as we want above code to simplify for cases
where called on single edge leaving basic block containing nontrivial
jump insn. */
else if (e->dest == target)
return false;
else if (!redirect_branch_edge (e, target))
return false;
return true; return true;
} }
...@@ -2323,9 +2392,8 @@ cfg_layout_split_block (basic_block bb, void *insnp) ...@@ -2323,9 +2392,8 @@ cfg_layout_split_block (basic_block bb, void *insnp)
edge fallthru = rtl_split_block (bb, insn); edge fallthru = rtl_split_block (bb, insn);
alloc_aux_for_block (fallthru->dest, sizeof (struct reorder_block_def)); fallthru->dest->rbi->footer = fallthru->src->rbi->footer;
RBI (fallthru->dest)->footer = RBI (fallthru->src)->footer; fallthru->src->rbi->footer = NULL;
RBI (fallthru->src)->footer = NULL;
return fallthru; return fallthru;
} }
...@@ -2335,14 +2403,33 @@ static bool ...@@ -2335,14 +2403,33 @@ static bool
cfg_layout_redirect_edge_and_branch (edge e, basic_block dest) cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
{ {
basic_block src = e->src; basic_block src = e->src;
basic_block old_next_bb = src->next_bb;
bool ret; bool ret;
if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
return false;
if (e->src != ENTRY_BLOCK_PTR
&& try_redirect_by_replacing_jump (e, dest, true))
return true;
if (e->dest == dest)
return true;
if (e->src == ENTRY_BLOCK_PTR
&& (e->flags & EDGE_FALLTHRU) && !(e->flags & EDGE_COMPLEX))
{
if (rtl_dump_file)
fprintf (rtl_dump_file, "Redirecting entry edge from bb %i to %i\n",
e->src->index, dest->index);
redirect_edge_succ (e, dest);
return true;
}
/* Redirect_edge_and_branch may decide to turn branch into fallthru edge /* Redirect_edge_and_branch may decide to turn branch into fallthru edge
in the case the basic block appears to be in sequence. Avoid this in the case the basic block appears to be in sequence. Avoid this
transformation. */ transformation. */
src->next_bb = NULL;
if (e->flags & EDGE_FALLTHRU) if (e->flags & EDGE_FALLTHRU)
{ {
/* Redirect any branch edges unified with the fallthru one. */ /* Redirect any branch edges unified with the fallthru one. */
...@@ -2364,20 +2451,18 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest) ...@@ -2364,20 +2451,18 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest)
delete_insn (src->end); delete_insn (src->end);
} }
redirect_edge_succ_nodup (e, dest); redirect_edge_succ_nodup (e, dest);
if (rtl_dump_file)
fprintf (rtl_dump_file, "Fallthru edge %i->%i redirected to %i\n",
e->src->index, e->dest->index, dest->index);
ret = true; ret = true;
} }
else else
ret = rtl_redirect_edge_and_branch (e, dest); ret = redirect_branch_edge (e, dest);
/* We don't want simplejumps in the insn stream during cfglayout. */ /* We don't want simplejumps in the insn stream during cfglayout. */
if (simplejump_p (src->end)) if (simplejump_p (src->end))
{ abort ();
delete_insn (src->end);
delete_barrier (NEXT_INSN (src->end));
src->succ->flags |= EDGE_FALLTHRU;
}
src->next_bb = old_next_bb;
return ret; return ret;
} }
...@@ -2397,36 +2482,55 @@ cfg_layout_delete_block (basic_block bb) ...@@ -2397,36 +2482,55 @@ cfg_layout_delete_block (basic_block bb)
{ {
rtx insn, next, prev = PREV_INSN (bb->head), *to, remaints; rtx insn, next, prev = PREV_INSN (bb->head), *to, remaints;
if (RBI (bb)->header) if (bb->rbi->header)
{ {
next = bb->head; next = bb->head;
if (prev) if (prev)
NEXT_INSN (prev) = RBI (bb)->header; NEXT_INSN (prev) = bb->rbi->header;
else else
set_first_insn (RBI (bb)->header); set_first_insn (bb->rbi->header);
PREV_INSN (RBI (bb)->header) = prev; PREV_INSN (bb->rbi->header) = prev;
insn = RBI (bb)->header; insn = bb->rbi->header;
while (NEXT_INSN (insn)) while (NEXT_INSN (insn))
insn = NEXT_INSN (insn); insn = NEXT_INSN (insn);
NEXT_INSN (insn) = next; NEXT_INSN (insn) = next;
PREV_INSN (next) = insn; PREV_INSN (next) = insn;
} }
next = NEXT_INSN (bb->end); next = NEXT_INSN (bb->end);
if (RBI (bb)->footer) if (bb->rbi->footer)
{ {
insn = bb->end; insn = bb->rbi->footer;
NEXT_INSN (insn) = RBI (bb)->footer; while (insn)
PREV_INSN (RBI (bb)->footer) = insn; {
while (NEXT_INSN (insn)) if (GET_CODE (insn) == BARRIER)
insn = NEXT_INSN (insn); {
NEXT_INSN (insn) = next; if (PREV_INSN (insn))
if (next) NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
PREV_INSN (next) = insn; else
else bb->rbi->footer = NEXT_INSN (insn);
set_last_insn (insn); if (NEXT_INSN (insn))
PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
}
if (GET_CODE (insn) == CODE_LABEL)
break;
insn = NEXT_INSN (insn);
}
if (bb->rbi->footer)
{
insn = bb->end;
NEXT_INSN (insn) = bb->rbi->footer;
PREV_INSN (bb->rbi->footer) = insn;
while (NEXT_INSN (insn))
insn = NEXT_INSN (insn);
NEXT_INSN (insn) = next;
if (next)
PREV_INSN (next) = insn;
else
set_last_insn (insn);
}
} }
if (bb->next_bb != EXIT_BLOCK_PTR) if (bb->next_bb != EXIT_BLOCK_PTR)
to = &RBI(bb->next_bb)->header; to = &bb->next_bb->rbi->header;
else else
to = &cfg_layout_function_footer; to = &cfg_layout_function_footer;
rtl_delete_block (bb); rtl_delete_block (bb);
...@@ -2453,14 +2557,141 @@ cfg_layout_delete_block (basic_block bb) ...@@ -2453,14 +2557,141 @@ cfg_layout_delete_block (basic_block bb)
} }
} }
/* return true when blocks A and B can be safely merged. */
static bool
cfg_layout_can_merge_blocks_p (basic_block a, basic_block b)
{
/* There must be exactly one edge in between the blocks. */
return (a->succ && !a->succ->succ_next && a->succ->dest == b
&& !b->pred->pred_next && a != b
/* Must be simple edge. */
&& !(a->succ->flags & EDGE_COMPLEX)
&& a != ENTRY_BLOCK_PTR && b != EXIT_BLOCK_PTR
/* If the jump insn has side effects,
we can't kill the edge. */
&& (GET_CODE (a->end) != JUMP_INSN
|| (flow2_completed
? simplejump_p (a->end) : onlyjump_p (a->end))));
}
/* Merge block A and B, abort when it is not possible. */
static void
cfg_layout_merge_blocks (basic_block a, basic_block b)
{
#ifdef ENABLE_CHECKING
if (!cfg_layout_can_merge_blocks_p (a, b))
abort ();
#endif
/* If there was a CODE_LABEL beginning B, delete it. */
if (GET_CODE (b->head) == CODE_LABEL)
delete_insn (b->head);
/* We should have fallthru edge in a, or we can do dummy redirection to get
it cleaned up. */
if (GET_CODE (a->end) == JUMP_INSN)
redirect_edge_and_branch (a->succ, b);
if (GET_CODE (a->end) == JUMP_INSN)
abort ();
/* Possible line number notes should appear in between. */
if (b->rbi->header)
{
rtx first = a->end, last;
last = emit_insn_after (b->rbi->header, a->end);
delete_insn_chain (NEXT_INSN (first), last);
b->rbi->header = NULL;
}
/* In the case basic blocks are not adjacent, move them around. */
if (NEXT_INSN (a->end) != b->head)
{
rtx first = unlink_insn_chain (b->head, b->end);
emit_insn_after (first, a->end);
/* Skip possible DELETED_LABEL insn. */
if (!NOTE_INSN_BASIC_BLOCK_P (first))
first = NEXT_INSN (first);
if (!NOTE_INSN_BASIC_BLOCK_P (first))
abort ();
b->head = NULL;
delete_insn (first);
}
/* Otherwise just re-associate the instructions. */
else
{
rtx insn;
for (insn = b->head; insn != NEXT_INSN (b->end); insn = NEXT_INSN (insn))
set_block_for_insn (insn, a);
insn = b->head;
/* Skip possible DELETED_LABEL insn. */
if (!NOTE_INSN_BASIC_BLOCK_P (insn))
insn = NEXT_INSN (insn);
if (!NOTE_INSN_BASIC_BLOCK_P (insn))
abort ();
b->head = NULL;
a->end = b->end;
delete_insn (insn);
}
/* Possible tablejumps and barriers should appear after the block. */
if (b->rbi->footer)
{
if (!a->rbi->footer)
a->rbi->footer = b->rbi->footer;
else
{
rtx last = a->rbi->footer;
while (NEXT_INSN (last))
last = NEXT_INSN (last);
NEXT_INSN (last) = b->rbi->footer;
PREV_INSN (b->rbi->footer) = last;
}
b->rbi->footer = NULL;
}
if (rtl_dump_file)
fprintf (rtl_dump_file, "Merged blocks %d and %d.\n",
a->index, b->index);
update_cfg_after_block_merging (a, b);
}
/* Split edge E. */
static basic_block
cfg_layout_split_edge (edge e)
{
edge new_e;
basic_block new_bb =
create_basic_block (e->src != ENTRY_BLOCK_PTR
? NEXT_INSN (e->src-> end) : get_insns (),
NULL_RTX, e->src);
new_bb->count = e->count;
new_bb->frequency = EDGE_FREQUENCY (e);
new_e = make_edge (new_bb, e->dest, EDGE_FALLTHRU);
new_e->probability = REG_BR_PROB_BASE;
new_e->count = e->count;
redirect_edge_and_branch_force (e, new_bb);
return new_bb;
}
/* Implementation of CFG manipulation for linearized RTL. */ /* Implementation of CFG manipulation for linearized RTL. */
struct cfg_hooks rtl_cfg_hooks = { struct cfg_hooks rtl_cfg_hooks = {
rtl_verify_flow_info, rtl_verify_flow_info,
rtl_dump_bb, rtl_dump_bb,
rtl_create_basic_block,
rtl_redirect_edge_and_branch, rtl_redirect_edge_and_branch,
rtl_redirect_edge_and_branch_force, rtl_redirect_edge_and_branch_force,
rtl_delete_block, rtl_delete_block,
rtl_split_block, rtl_split_block,
rtl_can_merge_blocks, /* can_merge_blocks_p */
rtl_merge_blocks,
rtl_split_edge rtl_split_edge
}; };
...@@ -2469,11 +2700,14 @@ struct cfg_hooks rtl_cfg_hooks = { ...@@ -2469,11 +2700,14 @@ struct cfg_hooks rtl_cfg_hooks = {
This representation will hopefully become the default one in future This representation will hopefully become the default one in future
version of the compiler. */ version of the compiler. */
struct cfg_hooks cfg_layout_rtl_cfg_hooks = { struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
rtl_verify_flow_info_1, /* verify_flow_info. */ rtl_verify_flow_info_1,
rtl_dump_bb, rtl_dump_bb,
cfg_layout_create_basic_block,
cfg_layout_redirect_edge_and_branch, cfg_layout_redirect_edge_and_branch,
cfg_layout_redirect_edge_and_branch_force, cfg_layout_redirect_edge_and_branch_force,
cfg_layout_delete_block, cfg_layout_delete_block,
cfg_layout_split_block, cfg_layout_split_block,
NULL /* split_edge. */ cfg_layout_can_merge_blocks_p,
cfg_layout_merge_blocks,
cfg_layout_split_edge
}; };
...@@ -2063,7 +2063,10 @@ propagate_block (basic_block bb, regset live, regset local_set, ...@@ -2063,7 +2063,10 @@ propagate_block (basic_block bb, regset live, regset local_set,
IOR_REG_SET (regs_live_at_setjmp, pbi->reg_live); IOR_REG_SET (regs_live_at_setjmp, pbi->reg_live);
prev = propagate_one_insn (pbi, insn); prev = propagate_one_insn (pbi, insn);
changed |= NEXT_INSN (prev) != insn; if (!prev)
changed |= insn != get_insns ();
else
changed |= NEXT_INSN (prev) != insn;
if (insn == bb->head) if (insn == bb->head)
break; break;
......
...@@ -2016,7 +2016,7 @@ merge_if_block (ce_info) ...@@ -2016,7 +2016,7 @@ merge_if_block (ce_info)
fallthru = block_fallthru (bb); fallthru = block_fallthru (bb);
if (post_dominators) if (post_dominators)
delete_from_dominance_info (post_dominators, bb); delete_from_dominance_info (post_dominators, bb);
merge_blocks_nomove (combo_bb, bb); merge_blocks (combo_bb, bb);
num_removed_blocks++; num_removed_blocks++;
} }
while (bb != last_test_bb); while (bb != last_test_bb);
...@@ -2033,7 +2033,7 @@ merge_if_block (ce_info) ...@@ -2033,7 +2033,7 @@ merge_if_block (ce_info)
then_bb->global_live_at_end); then_bb->global_live_at_end);
if (post_dominators) if (post_dominators)
delete_from_dominance_info (post_dominators, then_bb); delete_from_dominance_info (post_dominators, then_bb);
merge_blocks_nomove (combo_bb, then_bb); merge_blocks (combo_bb, then_bb);
num_removed_blocks++; num_removed_blocks++;
} }
...@@ -2044,7 +2044,7 @@ merge_if_block (ce_info) ...@@ -2044,7 +2044,7 @@ merge_if_block (ce_info)
{ {
if (post_dominators) if (post_dominators)
delete_from_dominance_info (post_dominators, else_bb); delete_from_dominance_info (post_dominators, else_bb);
merge_blocks_nomove (combo_bb, else_bb); merge_blocks (combo_bb, else_bb);
num_removed_blocks++; num_removed_blocks++;
} }
...@@ -2101,7 +2101,7 @@ merge_if_block (ce_info) ...@@ -2101,7 +2101,7 @@ merge_if_block (ce_info)
if (post_dominators) if (post_dominators)
delete_from_dominance_info (post_dominators, join_bb); delete_from_dominance_info (post_dominators, join_bb);
merge_blocks_nomove (combo_bb, join_bb); merge_blocks (combo_bb, join_bb);
num_removed_blocks++; num_removed_blocks++;
} }
else else
...@@ -3129,7 +3129,7 @@ if_convert (x_life_data_ok) ...@@ -3129,7 +3129,7 @@ if_convert (x_life_data_ok)
life_data_ok = (x_life_data_ok != 0); life_data_ok = (x_life_data_ok != 0);
/* Free up basic_block_for_insn so that we don't have to keep it /* Free up basic_block_for_insn so that we don't have to keep it
up to date, either here or in merge_blocks_nomove. */ up to date, either here or in merge_blocks. */
free_basic_block_vars (1); free_basic_block_vars (1);
/* Compute postdominators if we think we'll use them. */ /* Compute postdominators if we think we'll use them. */
......
...@@ -37,6 +37,9 @@ loop_optimizer_init (dumpfile) ...@@ -37,6 +37,9 @@ loop_optimizer_init (dumpfile)
struct loops *loops = xcalloc (1, sizeof (struct loops)); struct loops *loops = xcalloc (1, sizeof (struct loops));
edge e; edge e;
/* Initialize structures for layout changes. */
cfg_layout_initialize ();
/* Avoid annoying special cases of edges going to exit /* Avoid annoying special cases of edges going to exit
block. */ block. */
for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next) for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
...@@ -47,9 +50,16 @@ loop_optimizer_init (dumpfile) ...@@ -47,9 +50,16 @@ loop_optimizer_init (dumpfile)
if (flow_loops_find (loops, LOOP_TREE) <= 1) if (flow_loops_find (loops, LOOP_TREE) <= 1)
{ {
basic_block bb;
/* No loops. */ /* No loops. */
flow_loops_free (loops); flow_loops_free (loops);
free (loops); free (loops);
/* Make chain. */
FOR_EACH_BB (bb)
if (bb->next_bb != EXIT_BLOCK_PTR)
bb->rbi->next = bb->next_bb;
cfg_layout_finalize ();
return NULL; return NULL;
} }
...@@ -59,11 +69,8 @@ loop_optimizer_init (dumpfile) ...@@ -59,11 +69,8 @@ loop_optimizer_init (dumpfile)
free (loops->cfg.dfs_order); free (loops->cfg.dfs_order);
loops->cfg.dfs_order = NULL; loops->cfg.dfs_order = NULL;
/* Initialize structures for layout changes. */
cfg_layout_initialize (loops);
/* Create pre-headers. */ /* Create pre-headers. */
create_preheaders (loops, CP_SIMPLE_PREHEADERS | CP_INSIDE_CFGLAYOUT); create_preheaders (loops, CP_SIMPLE_PREHEADERS);
/* Force all latches to have only single successor. */ /* Force all latches to have only single successor. */
force_single_succ_latches (loops); force_single_succ_latches (loops);
...@@ -94,7 +101,7 @@ loop_optimizer_finalize (loops, dumpfile) ...@@ -94,7 +101,7 @@ loop_optimizer_finalize (loops, dumpfile)
/* Make chain. */ /* Make chain. */
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
if (bb->next_bb != EXIT_BLOCK_PTR) if (bb->next_bb != EXIT_BLOCK_PTR)
RBI (bb)->next = bb->next_bb; bb->rbi->next = bb->next_bb;
/* Another dump. */ /* Another dump. */
flow_loops_dump (loops, dumpfile, NULL, 1); flow_loops_dump (loops, dumpfile, NULL, 1);
......
...@@ -377,7 +377,7 @@ unswitch_loop (loops, loop, unswitch_on) ...@@ -377,7 +377,7 @@ unswitch_loop (loops, loop, unswitch_on)
entry->flags |= irred_flag; entry->flags |= irred_flag;
/* Record the block with condition we unswitch on. */ /* Record the block with condition we unswitch on. */
unswitch_on_alt = RBI (unswitch_on)->copy; unswitch_on_alt = unswitch_on->rbi->copy;
/* Make a copy of the block containing the condition; we will use /* Make a copy of the block containing the condition; we will use
it as switch to decide which loop we want to use. */ it as switch to decide which loop we want to use. */
...@@ -395,14 +395,14 @@ unswitch_loop (loops, loop, unswitch_on) ...@@ -395,14 +395,14 @@ unswitch_loop (loops, loop, unswitch_on)
switch_bb->succ->succ_next->flags &= ~EDGE_IRREDUCIBLE_LOOP; switch_bb->succ->succ_next->flags &= ~EDGE_IRREDUCIBLE_LOOP;
} }
add_to_dominance_info (loops->cfg.dom, switch_bb); add_to_dominance_info (loops->cfg.dom, switch_bb);
RBI (unswitch_on)->copy = unswitch_on_alt; unswitch_on->rbi->copy = unswitch_on_alt;
/* Loopify from the copy of LOOP body, constructing the new loop. */ /* Loopify from the copy of LOOP body, constructing the new loop. */
for (latch_edge = RBI (loop->latch)->copy->succ; for (latch_edge = loop->latch->rbi->copy->succ;
latch_edge->dest != loop->header; latch_edge->dest != loop->header;
latch_edge = latch_edge->succ_next); latch_edge = latch_edge->succ_next);
nloop = loopify (loops, latch_edge, nloop = loopify (loops, latch_edge,
RBI (loop->header)->copy->pred, switch_bb); loop->header->rbi->copy->pred, switch_bb);
/* Remove branches that are now unreachable in new loops. We rely on the /* Remove branches that are now unreachable in new loops. We rely on the
fact that cfg_layout_duplicate_bb reverses list of edges. */ fact that cfg_layout_duplicate_bb reverses list of edges. */
......
...@@ -64,7 +64,7 @@ static int branch_ratio_cutoff; ...@@ -64,7 +64,7 @@ static int branch_ratio_cutoff;
/* Return true if BB has been seen - it is connected to some trace /* Return true if BB has been seen - it is connected to some trace
already. */ already. */
#define seen(bb) (RBI (bb)->visited || RBI (bb)->next) #define seen(bb) (bb->rbi->visited || bb->rbi->next)
/* Return true if we should ignore the basic block for purposes of tracing. */ /* Return true if we should ignore the basic block for purposes of tracing. */
static bool static bool
...@@ -295,8 +295,8 @@ tail_duplicate () ...@@ -295,8 +295,8 @@ tail_duplicate ()
fprintf (rtl_dump_file, "Duplicated %i as %i [%i]\n", fprintf (rtl_dump_file, "Duplicated %i as %i [%i]\n",
old->index, bb2->index, bb2->frequency); old->index, bb2->index, bb2->frequency);
} }
RBI (bb)->next = bb2; bb->rbi->next = bb2;
RBI (bb2)->visited = 1; bb2->rbi->visited = 1;
bb = bb2; bb = bb2;
/* In case the trace became infrequent, stop duplicating. */ /* In case the trace became infrequent, stop duplicating. */
if (ignore_bb_p (bb)) if (ignore_bb_p (bb))
...@@ -330,28 +330,28 @@ layout_superblocks () ...@@ -330,28 +330,28 @@ layout_superblocks ()
while (bb != EXIT_BLOCK_PTR) while (bb != EXIT_BLOCK_PTR)
{ {
edge e, best = NULL; edge e, best = NULL;
while (RBI (end)->next) while (end->rbi->next)
end = RBI (end)->next; end = end->rbi->next;
for (e = end->succ; e; e = e->succ_next) for (e = end->succ; e; e = e->succ_next)
if (e->dest != EXIT_BLOCK_PTR if (e->dest != EXIT_BLOCK_PTR
&& e->dest != ENTRY_BLOCK_PTR->succ->dest && e->dest != ENTRY_BLOCK_PTR->succ->dest
&& !RBI (e->dest)->visited && !e->dest->rbi->visited
&& (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best))) && (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best)))
best = e; best = e;
if (best) if (best)
{ {
RBI (end)->next = best->dest; end->rbi->next = best->dest;
RBI (best->dest)->visited = 1; best->dest->rbi->visited = 1;
} }
else else
for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb) for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb)
{ {
if (!RBI (bb)->visited) if (!bb->rbi->visited)
{ {
RBI (end)->next = bb; end->rbi->next = bb;
RBI (bb)->visited = 1; bb->rbi->visited = 1;
break; break;
} }
} }
...@@ -365,7 +365,7 @@ tracer () ...@@ -365,7 +365,7 @@ tracer ()
{ {
if (n_basic_blocks <= 1) if (n_basic_blocks <= 1)
return; return;
cfg_layout_initialize (NULL); cfg_layout_initialize ();
mark_dfs_back_edges (); mark_dfs_back_edges ();
if (rtl_dump_file) if (rtl_dump_file)
dump_flow_info (rtl_dump_file); dump_flow_info (rtl_dump_file);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment