From c60fa3a778a01ab52008d1bd4d832658ca8943e6 Mon Sep 17 00:00:00 2001 From: hubicka Date: Thu, 3 Jul 2003 18:40:29 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@68899 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 76 ++++++++++ gcc/basic-block.h | 6 +- gcc/bb-reorder.c | 58 ++++---- gcc/cfg.c | 6 +- gcc/cfganal.c | 4 +- gcc/cfgcleanup.c | 67 ++++++--- gcc/cfghooks.h | 12 ++ gcc/cfglayout.c | 246 ++++++++++++++----------------- gcc/cfglayout.h | 5 +- gcc/cfgloop.h | 3 +- gcc/cfgloopmanip.c | 43 ++---- gcc/cfgrtl.c | 416 ++++++++++++++++++++++++++++++++++++++++------------ gcc/flow.c | 5 +- gcc/ifcvt.c | 10 +- gcc/loop-init.c | 17 ++- gcc/loop-unswitch.c | 8 +- gcc/tracer.c | 24 +-- 17 files changed, 666 insertions(+), 340 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a614b50..77765f0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,79 @@ +Thu Jul 3 20:36:47 CEST 2003 Jan Hubicka + + * 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 * Makefile.in: Use dependency variables in lieu of explicit diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 65e5d82..cdefca3 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -241,6 +241,9 @@ typedef struct basic_block_def { /* Various flags. See BB_* below. */ int flags; + + /* Additional data maintained by cfg_layout routines. */ + struct reorder_block_def *rbi; } *basic_block; #define BB_FREQ_MAX 10000 @@ -362,9 +365,7 @@ extern void redirect_edge_succ PARAMS ((edge, basic_block)); extern edge redirect_edge_succ_nodup 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 PARAMS ((rtx, rtx, basic_block)); 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, basic_block)); extern void tidy_fallthru_edges PARAMS ((void)); @@ -500,6 +501,7 @@ enum update_life_extent #define CLEANUP_THREADING 64 /* Do jump threading. */ #define CLEANUP_NO_INSN_DEL 128 /* Do not try to delete trivially dead insns. */ +#define CLEANUP_CFGLAYOUT 256 /* Do cleanup in cfglayout mode. */ extern void life_analysis PARAMS ((rtx, FILE *, int)); extern int update_life_info PARAMS ((sbitmap, enum update_life_extent, int)); diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index 24e6df0..e75958e 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -205,7 +205,7 @@ find_traces (int *n_traces, struct trace *traces) basic_block bb; fprintf (rtl_dump_file, "Trace %d (round %d): ", i + 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]\n", bb->index, bb->frequency); } @@ -237,14 +237,14 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) edge e; for (e = bb->succ; e; e = e->succ_next) 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_COMPLEX)) { if (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) { /* The current edge E is also preferred. */ @@ -260,7 +260,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) } else { - if (!RBI (e->dest)->visited + if (!e->dest->rbi->visited || bbd[e->dest->index].start_of_trace >= 0) { /* The current edge E is preferred. */ @@ -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); @@ -293,17 +293,17 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) the trace. */ if (back_edge->dest == trace->first) { - trace->first = RBI (best_bb)->next; + trace->first = best_bb->rbi->next; } else { basic_block prev_bb; for (prev_bb = trace->first; - RBI (prev_bb)->next != back_edge->dest; - prev_bb = RBI (prev_bb)->next) + prev_bb->rbi->next != back_edge->dest; + 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. */ if (prev_bb->succ && !prev_bb->succ->succ_next) @@ -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. */ best_bb = back_edge->src; } - RBI (best_bb)->next = NULL; + best_bb->rbi->next = NULL; return best_bb; } @@ -333,7 +333,7 @@ rotate_loop (edge back_edge, struct trace *trace, int trace_n) static void mark_bb_visited (basic_block bb, int trace) { - RBI (bb)->visited = trace; + bb->rbi->visited = trace; if (bbd[bb->index].heap) { 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, if (e->dest == EXIT_BLOCK_PTR) continue; - if (RBI (e->dest)->visited - && RBI (e->dest)->visited != *n_traces) + if (e->dest->rbi->visited + && e->dest->rbi->visited != *n_traces) continue; prob = e->probability; @@ -453,7 +453,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, { if (e == best_edge || e->dest == EXIT_BLOCK_PTR - || RBI (e->dest)->visited) + || e->dest->rbi->visited) continue; key = bb_to_key (e->dest); @@ -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 (RBI (best_edge->dest)->visited == *n_traces) + if (best_edge->dest->rbi->visited == *n_traces) { /* We do nothing with one basic block loops. */ if (best_edge->dest != bb) @@ -528,7 +528,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, "Rotating loop %d - %d\n", 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); } } @@ -583,7 +583,7 @@ find_traces_1_round (int branch_th, int exec_th, gcov_type count_th, if (e != best_edge && (e->flags & EDGE_CAN_FALLTHRU) && !(e->flags & EDGE_COMPLEX) - && !RBI (e->dest)->visited + && !e->dest->rbi->visited && !e->dest->pred->pred_next && e->dest->succ && (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, break; } - RBI (bb)->next = best_edge->dest; + bb->rbi->next = 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, for (e = bb->succ; e; e = e->succ_next) { if (e->dest == EXIT_BLOCK_PTR - || RBI (e->dest)->visited) + || e->dest->rbi->visited) continue; if (bbd[e->dest->index].heap) @@ -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); if (e->dest != new_bb) abort (); - if (RBI (e->dest)->visited) + if (e->dest->rbi->visited) abort (); if (rtl_dump_file) fprintf (rtl_dump_file, "Duplicated bb %d (created bb %d)\n", old_bb->index, new_bb->index); - RBI (new_bb)->visited = trace; - RBI (new_bb)->next = RBI (bb)->next; - RBI (bb)->next = new_bb; + new_bb->rbi->visited = trace; + new_bb->rbi->next = bb->rbi->next; + bb->rbi->next = new_bb; if (new_bb->index >= array_size || last_basic_block > array_size) { @@ -826,7 +826,7 @@ connect_traces (int n_traces, struct trace *traces) } if (best) { - RBI (best->src)->next = best->dest; + best->src->rbi->next = best->dest; t2 = bbd[best->src->index].end_of_trace; connected[t2] = true; if (rtl_dump_file) @@ -840,7 +840,7 @@ connect_traces (int n_traces, struct trace *traces) } 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; /* Find the successor traces. */ @@ -876,7 +876,7 @@ connect_traces (int n_traces, struct trace *traces) best->src->index, best->dest->index); } 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; last_trace = t; } @@ -964,7 +964,7 @@ connect_traces (int n_traces, struct trace *traces) 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; + traces[last_trace].last->rbi->next = traces[t].first; connected[t] = true; last_trace = t; } @@ -982,7 +982,7 @@ connect_traces (int n_traces, struct trace *traces) basic_block bb; 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, "\n"); fflush (rtl_dump_file); @@ -1064,7 +1064,7 @@ reorder_basic_blocks (void) if ((* targetm.cannot_modify_jumps_p) ()) return; - cfg_layout_initialize (NULL); + cfg_layout_initialize (); set_edge_can_fallthru_flag (); mark_dfs_back_edges (); diff --git a/gcc/cfg.c b/gcc/cfg.c index b55a2c0..ced99a3 100644 --- a/gcc/cfg.c +++ b/gcc/cfg.c @@ -113,7 +113,8 @@ struct basic_block_def entry_exit_blocks[2] NULL, /* loop_father */ 0, /* count */ 0, /* frequency */ - 0 /* flags */ + 0, /* flags */ + NULL /* rbi */ }, { NULL, /* head */ @@ -134,7 +135,8 @@ struct basic_block_def entry_exit_blocks[2] NULL, /* loop_father */ 0, /* count */ 0, /* frequency */ - 0 /* flags */ + 0, /* flags */ + NULL /* rbi */ } }; diff --git a/gcc/cfganal.c b/gcc/cfganal.c index 4054996..d3383c0 100644 --- a/gcc/cfganal.c +++ b/gcc/cfganal.c @@ -104,12 +104,12 @@ bool can_fallthru (basic_block src, basic_block target) { rtx insn = src->end; - rtx insn2 = target->head; + rtx insn2 = target == EXIT_BLOCK_PTR ? NULL : target->head; if (src->next_bb != target) return 0; - if (!active_insn_p (insn2)) + if (insn2 && !active_insn_p (insn2)) insn2 = next_active_insn (insn2); /* ??? Later we may add code to move jump tables offline. */ diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 0ad1c6b..da874f7 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -77,7 +77,6 @@ static bool label_is_jump_target_p (rtx, rtx); static bool tail_recursion_label_p (rtx); static void merge_blocks_move_predecessor_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_simplify_condjump (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) link_block (a, b->prev_bb); /* 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 @@ -758,7 +757,7 @@ merge_blocks_move_successor_nojumps (basic_block a, basic_block b) b->index, a->index); /* 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. @@ -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. */ 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; /* 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) if (e->flags & EDGE_FALLTHRU) { int b_index = b->index, c_index = c->index; - merge_blocks_nomove (b, c); + merge_blocks (b, c); update_forwarder_flag (b); if (rtl_dump_file) @@ -1686,7 +1685,8 @@ try_optimize_cfg (int mode) b->index); delete_block (b); - changed = true; + if (!(mode & CLEANUP_CFGLAYOUT)) + changed = true; b = c; } @@ -1712,15 +1712,24 @@ try_optimize_cfg (int mode) { rtx label = b->head; - b->head = NEXT_INSN (b->head); 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) fprintf (rtl_dump_file, "Deleted label in block %i.\n", b->index); } /* 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) && GET_CODE (b->head) != CODE_LABEL && FORWARDER_BLOCK_P (b) @@ -1746,21 +1755,39 @@ try_optimize_cfg (int mode) && !(s->flags & EDGE_COMPLEX) && (c = s->dest) != EXIT_BLOCK_PTR && c->pred->pred_next == NULL - && b != c - /* 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 (s, b, c, mode))) - { - b = next; - changed_here = true; + && b != c) + { + /* When not in cfg_layout mode use code aware of reordering + INSN. This code possibly creates new basic blocks so it + does not fit merge_blocks interface and is kept here in + hope that it will become useless once more of compiler + is transformed to use cfg_layout mode. */ + + if ((mode & CLEANUP_CFGLAYOUT) + && can_merge_blocks_p (b, c)) + { + 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. */ - if ((mode & CLEANUP_EXPENSIVE) && try_simplify_condjump (b)) + if ((mode & CLEANUP_EXPENSIVE) + && !(mode & CLEANUP_CFGLAYOUT) + && try_simplify_condjump (b)) changed_here = true; /* If B has a single outgoing edge, but uses a diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h index 00a9816..a44a208 100644 --- a/gcc/cfghooks.h +++ b/gcc/cfghooks.h @@ -31,6 +31,9 @@ struct cfg_hooks /* 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 representation. Returns false when edge is not easily redirectable for whatever reason. */ @@ -47,6 +50,12 @@ struct cfg_hooks /* Split basic block B after specified instruction 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 we didn't have some oddities in RTL and Tree representations. */ basic_block (*cfgh_split_edge) (edge); @@ -57,6 +66,9 @@ struct cfg_hooks #define split_block(e,i) cfg_hooks->split_block (e,i) #define delete_block(b) cfg_hooks->delete_block (b) #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. */ extern struct cfg_hooks rtl_cfg_hooks; diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 12cc255..a576f0e 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -34,13 +34,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "cfgloop.h" #include "target.h" #include "ggc.h" +#include "alloc-pool.h" /* The contents of the current function definition are allocated in this obstack, and all are freed at the end of the function. */ extern struct obstack flow_obstack; +alloc_pool cfg_layout_pool; + /* 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 void record_effective_endpoints (void); @@ -51,7 +54,6 @@ static void set_block_levels (tree, int); static void change_scope (rtx, tree, tree); void verify_insn_chain (void); -static void cleanup_unconditional_jumps (struct loops *); static void fixup_fallthru_exit_predecessor (void); static rtx duplicate_insn_chain (rtx, rtx); static void break_superblocks (void); @@ -189,19 +191,38 @@ label_for_bb (basic_block bb) static void record_effective_endpoints (void) { - rtx next_insn = get_insns (); + rtx next_insn; 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) { rtx end; 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)); end = skip_insns_after_block (bb); 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); } @@ -529,21 +550,29 @@ fixup_reorder_chain (void) int index; 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 the needed changes to jumps and labels. */ for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0; bb != 0; - bb = RBI (bb)->next, index++) + bb = bb->rbi->next, index++) { - if (RBI (bb)->header) + if (bb->rbi->header) { if (insn) - NEXT_INSN (insn) = RBI (bb)->header; + NEXT_INSN (insn) = bb->rbi->header; else - set_first_insn (RBI (bb)->header); - PREV_INSN (RBI (bb)->header) = insn; - insn = RBI (bb)->header; + set_first_insn (bb->rbi->header); + PREV_INSN (bb->rbi->header) = insn; + insn = bb->rbi->header; while (NEXT_INSN (insn)) insn = NEXT_INSN (insn); } @@ -553,10 +582,10 @@ fixup_reorder_chain (void) set_first_insn (bb->head); PREV_INSN (bb->head) = insn; insn = bb->end; - if (RBI (bb)->footer) + if (bb->rbi->footer) { - NEXT_INSN (insn) = RBI (bb)->footer; - PREV_INSN (RBI (bb)->footer) = insn; + NEXT_INSN (insn) = bb->rbi->footer; + PREV_INSN (bb->rbi->footer) = insn; while (NEXT_INSN (insn)) insn = NEXT_INSN (insn); } @@ -580,7 +609,7 @@ fixup_reorder_chain (void) /* Now add jumps and labels as needed to match the blocks new 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; rtx bb_end_insn; @@ -604,8 +633,8 @@ fixup_reorder_chain (void) if (any_condjump_p (bb_end_insn)) { /* If the old fallthru is still next, nothing to do. */ - if (RBI (bb)->next == e_fall->dest - || (!RBI (bb)->next + if (bb->rbi->next == e_fall->dest + || (!bb->rbi->next && e_fall->dest == EXIT_BLOCK_PTR)) continue; @@ -645,7 +674,7 @@ fixup_reorder_chain (void) such as happens at the very end of a function, then we'll need to add a new unconditional jump. Choose the taken 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); @@ -684,7 +713,7 @@ fixup_reorder_chain (void) #ifdef CASE_DROPS_THROUGH /* Except for VAX. Since we didn't have predication for the tablejump, the fallthru block should not have moved. */ - if (RBI (bb)->next == e_fall->dest) + if (bb->rbi->next == e_fall->dest) continue; bb_end_insn = skip_insns_after_block (bb); #else @@ -701,11 +730,11 @@ fixup_reorder_chain (void) continue; /* 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; /* 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; } @@ -713,10 +742,10 @@ fixup_reorder_chain (void) nb = force_nonfallthru (e_fall); if (nb) { - alloc_aux_for_block (nb, sizeof (struct reorder_block_def)); - RBI (nb)->visited = 1; - RBI (nb)->next = RBI (bb)->next; - RBI (bb)->next = nb; + cfg_layout_initialize_rbi (nb); + nb->rbi->visited = 1; + nb->rbi->next = bb->rbi->next; + bb->rbi->next = nb; /* Don't process this new block. */ bb = nb; } @@ -727,12 +756,12 @@ fixup_reorder_chain (void) if (rtl_dump_file) { 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); - if (RBI (bb)->original) + if (bb->rbi->original) 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) fprintf (rtl_dump_file, "compensation "); else @@ -745,7 +774,7 @@ fixup_reorder_chain (void) bb = ENTRY_BLOCK_PTR->next_bb; 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; BASIC_BLOCK (index) = bb; @@ -755,6 +784,16 @@ fixup_reorder_chain (void) } prev_bb->next_bb = EXIT_BLOCK_PTR; 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. @@ -788,87 +827,6 @@ verify_insn_chain (void) 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 reordered chain. Ensure that this condition is met. */ static void @@ -881,19 +839,19 @@ fixup_fallthru_exit_predecessor (void) if (e->flags & EDGE_FALLTHRU) bb = e->src; - if (bb && RBI (bb)->next) + if (bb && bb->rbi->next) { basic_block c = ENTRY_BLOCK_PTR->next_bb; - while (RBI (c)->next != bb) - c = RBI (c)->next; + while (c->rbi->next != bb) + c = c->rbi->next; - RBI (c)->next = RBI (bb)->next; - while (RBI (c)->next) - c = RBI (c)->next; + c->rbi->next = bb->rbi->next; + while (c->rbi->next) + c = c->rbi->next; - RBI (c)->next = bb; - RBI (bb)->next = NULL; + c->rbi->next = bb; + bb->rbi->next = NULL; } } @@ -1050,26 +1008,25 @@ cfg_layout_duplicate_bb (basic_block bb, edge e) new_bb = create_basic_block (insn, insn ? get_last_insn () : NULL, 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)) insn = NEXT_INSN (insn); - insn = duplicate_insn_chain (RBI (bb)->header, insn); + insn = duplicate_insn_chain (bb->rbi->header, 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)) insn = NEXT_INSN (insn); - insn = duplicate_insn_chain (RBI (bb)->footer, insn); + insn = duplicate_insn_chain (bb->rbi->footer, 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) @@ -1113,25 +1070,42 @@ cfg_layout_duplicate_bb (basic_block bb, edge e) if (bb->frequency < 0) bb->frequency = 0; - RBI (new_bb)->original = bb; - RBI (bb)->copy = new_bb; + new_bb->rbi->original = bb; + bb->rbi->copy = 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 CFG layout changes. It keeps LOOPS up-to-date if not null. */ void -cfg_layout_initialize (struct loops *loops) +cfg_layout_initialize () { + basic_block bb; + /* Our algorithm depends on fact that there are now dead jumptables around the code. */ - alloc_aux_for_blocks (sizeof (struct reorder_block_def)); - cfg_layout_rtl_register_cfg_hooks (); + cfg_layout_pool = + 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 (); + + cleanup_cfg (CLEANUP_CFGLAYOUT); } /* Splits superblocks. */ @@ -1169,6 +1143,8 @@ break_superblocks (void) void cfg_layout_finalize (void) { + basic_block bb; + #ifdef ENABLE_CHECKING verify_flow_info (); #endif @@ -1180,7 +1156,9 @@ cfg_layout_finalize (void) verify_insn_chain (); #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 (); diff --git a/gcc/cfglayout.h b/gcc/cfglayout.h index 1ab3e1f..1602289 100644 --- a/gcc/cfglayout.h +++ b/gcc/cfglayout.h @@ -33,13 +33,12 @@ typedef struct reorder_block_def int visited; } *reorder_block_def; -#define RBI(BB) ((reorder_block_def) (BB)->aux) - 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 bool cfg_layout_can_duplicate_bb_p (basic_block); extern basic_block cfg_layout_duplicate_bb (basic_block, edge); extern void insn_locators_initialize (void); extern void reemit_insn_block_notes (void); +extern void cfg_layout_initialize_rbi (basic_block); diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index d3ab8e8..3fdc609 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -294,8 +294,7 @@ extern int fix_loop_placement (struct loop *); enum { - CP_SIMPLE_PREHEADERS = 1, - CP_INSIDE_CFGLAYOUT = 2 + CP_SIMPLE_PREHEADERS = 1 }; extern void create_preheaders (struct loops *, int); diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index 5675f71..c627ea0 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -860,7 +860,7 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge, /* Duplicate. */ bb = bbs[i]; 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_bb_to_loop (new_bb, bb->loop_father->copy); 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, { /* For anything else than loop header, just copy it. */ dom_bb = get_immediate_dominator (loops->cfg.dom, bb); - dom_bb = RBI (dom_bb)->copy; + dom_bb = dom_bb->rbi->copy; } else { @@ -910,7 +910,7 @@ copy_bbs (basic_block *bbs, int n, edge entry, edge latch_edge, e_pred = e->pred_next; - if (!RBI (src)->duplicated) + if (!src->rbi->duplicated) continue; /* 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, if (add_irreducible_flag && (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; } } /* 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); *header_edge = e; loop_redirect_edge (*header_edge, 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; /* Clear information about duplicates. */ 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. */ @@ -995,7 +995,7 @@ record_exit_edges (edge orig, basic_block *bbs, int nbbs, edge *to_remove, 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) break; if (!e) @@ -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, &e, &he, add_irreducible_flag); if (is_latch) - loop->latch = RBI (latch)->copy; + loop->latch = latch->rbi->copy; /* Record exit edges in this copy. */ if (TEST_BIT (wont_exit, j + 1)) @@ -1209,7 +1209,7 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e, struct loops *loops, if (!first_active_latch) { memcpy (first_active, new_bbs, n * sizeof (basic_block)); - first_active_latch = RBI (latch)->copy; + first_active_latch = latch->rbi->copy; } free (new_bbs); @@ -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 if we duplicated on its only entry edge. */ 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) { /* Update edge from latch. */ - for (latch_edge = RBI (header)->copy->pred; + for (latch_edge = header->rbi->copy->pred; latch_edge->src != latch; latch_edge = latch_edge->pred_next); } @@ -1409,33 +1409,20 @@ loop_split_edge_with (edge e, rtx insns, struct loops *loops) /* 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_bb_to_loop (new_bb, loop_c); new_bb->flags = insns ? BB_SUPERBLOCK : 0; - new_e = make_edge (new_bb, dest, EDGE_FALLTHRU); - new_e->probability = REG_BR_PROB_BASE; - new_e->count = e->count; + new_e = new_bb->succ; if (e->flags & EDGE_IRREDUCIBLE_LOOP) { new_bb->flags |= BB_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) - { - start_sequence (); - emit_insn (insns); - insns = get_insns (); - end_sequence (); - emit_insn_after (insns, new_bb->end); - } + emit_insn_after (insns, new_bb->end); set_immediate_dominator (loops->cfg.dom, new_bb, src); set_immediate_dominator (loops->cfg.dom, dest, diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 7340b9f..1f878ee 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -23,20 +23,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA that are aware of the RTL intermediate language. Available functionality: + - Basic CFG/RTL manipulation API documented in cfghooks.h - CFG-aware instruction chain manipulation delete_insn, delete_insn_chain - - Basic block manipulation - create_basic_block, rtl_delete_block,rtl_split_block, - merge_blocks_nomove + - Edge splitting and committing to edges + insert_insn_on_edge, commit_edge_insertions + - 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 compute_bb_for_insn, update_bb_for_insn, set_block_for_insn, - Edge redirection with updating and optimizing of insn chain - block_label, redirect_edge_and_branch, - 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 */ + block_label, tidy_fallthru_edge, force_nonfallthru */ #include "config.h" #include "system.h" @@ -73,7 +72,6 @@ rtx tail_recursion_label_list; static int can_delete_note_p (rtx); static int can_delete_label_p (rtx); 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 bool back_edge_of_syntactic_loop_p (basic_block, 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) create new empty basic block before HEAD. Both END and HEAD can be NULL to create basic block at the end of INSN chain. */ -basic_block -create_basic_block (rtx head, rtx end, basic_block after) +static basic_block +rtl_create_basic_block (void *headp, void *endp, basic_block after) { + rtx head = headp, end = endp; basic_block bb; /* Place the new block just after the end. */ @@ -340,6 +339,15 @@ create_basic_block (rtx head, rtx end, basic_block after) bb->aux = NULL; 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 non-deleted-note insn, and update the flow graph appropriately. @@ -517,16 +525,42 @@ rtl_split_block (basic_block bb, void *insnp) 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 - are already contiguous, hence `nomove'. */ + are already contiguous. */ -void -merge_blocks_nomove (basic_block a, basic_block b) +static void +rtl_merge_blocks (basic_block a, basic_block b) { rtx b_head = b->head, b_end = b->end, a_end = a->end; rtx del_first = NULL_RTX, del_last = NULL_RTX; int b_empty = 0; - edge e; /* If there was a CODE_LABEL beginning B, delete it. */ if (GET_CODE (b_head) == CODE_LABEL) @@ -585,24 +619,7 @@ merge_blocks_nomove (basic_block a, basic_block b) else if (GET_CODE (NEXT_INSN (a_end)) == BARRIER) del_first = NEXT_INSN (a_end); - /* 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); + update_cfg_after_block_merging (a, b); /* Delete everything marked above as well as crap that might be hanging out between the two blocks. */ @@ -623,6 +640,24 @@ merge_blocks_nomove (basic_block a, basic_block b) 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 exist. */ @@ -647,7 +682,7 @@ block_label (basic_block block) return values are equivalent to redirect_edge_and_branch. */ 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; rtx insn = src->end, kill_from; @@ -679,14 +714,38 @@ try_redirect_by_replacing_jump (edge e, basic_block target) #endif /* See if we can create the fallthru edge. */ - if (can_fallthru (src, target)) + if (in_cfglayout || can_fallthru (src, target)) { if (rtl_dump_file) fprintf (rtl_dump_file, "Removing jump %i.\n", INSN_UID (insn)); fallthru = 1; /* 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. */ @@ -782,36 +841,15 @@ last_loop_beg_note (rtx insn) return last; } -/* 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. */ - +/* Redirect edge representing branch of (un)conditional jump or tablejump. */ static bool -rtl_redirect_edge_and_branch (edge e, basic_block target) +redirect_branch_edge (edge e, basic_block target) { rtx tmp; rtx old_label = e->dest->head; basic_block src = e->src; 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. */ if (e->flags & EDGE_FALLTHRU) return false; @@ -884,6 +922,37 @@ rtl_redirect_edge_and_branch (edge e, basic_block target) if (e->dest != 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; } @@ -2323,9 +2392,8 @@ cfg_layout_split_block (basic_block bb, void *insnp) edge fallthru = rtl_split_block (bb, insn); - alloc_aux_for_block (fallthru->dest, sizeof (struct reorder_block_def)); - RBI (fallthru->dest)->footer = RBI (fallthru->src)->footer; - RBI (fallthru->src)->footer = NULL; + fallthru->dest->rbi->footer = fallthru->src->rbi->footer; + fallthru->src->rbi->footer = NULL; return fallthru; } @@ -2335,14 +2403,33 @@ static bool cfg_layout_redirect_edge_and_branch (edge e, basic_block dest) { basic_block src = e->src; - basic_block old_next_bb = src->next_bb; 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 in the case the basic block appears to be in sequence. Avoid this transformation. */ - src->next_bb = NULL; if (e->flags & EDGE_FALLTHRU) { /* Redirect any branch edges unified with the fallthru one. */ @@ -2364,20 +2451,18 @@ cfg_layout_redirect_edge_and_branch (edge e, basic_block dest) delete_insn (src->end); } 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; } 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. */ if (simplejump_p (src->end)) - { - delete_insn (src->end); - delete_barrier (NEXT_INSN (src->end)); - src->succ->flags |= EDGE_FALLTHRU; - } - src->next_bb = old_next_bb; + abort (); return ret; } @@ -2397,36 +2482,55 @@ cfg_layout_delete_block (basic_block bb) { rtx insn, next, prev = PREV_INSN (bb->head), *to, remaints; - if (RBI (bb)->header) + if (bb->rbi->header) { next = bb->head; if (prev) - NEXT_INSN (prev) = RBI (bb)->header; + NEXT_INSN (prev) = bb->rbi->header; else - set_first_insn (RBI (bb)->header); - PREV_INSN (RBI (bb)->header) = prev; - insn = RBI (bb)->header; + set_first_insn (bb->rbi->header); + PREV_INSN (bb->rbi->header) = prev; + insn = bb->rbi->header; while (NEXT_INSN (insn)) insn = NEXT_INSN (insn); NEXT_INSN (insn) = next; PREV_INSN (next) = insn; } next = NEXT_INSN (bb->end); - if (RBI (bb)->footer) + if (bb->rbi->footer) { - insn = bb->end; - NEXT_INSN (insn) = RBI (bb)->footer; - PREV_INSN (RBI (bb)->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); + insn = bb->rbi->footer; + while (insn) + { + if (GET_CODE (insn) == BARRIER) + { + if (PREV_INSN (insn)) + NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn); + else + bb->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); + } + 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) - to = &RBI(bb->next_bb)->header; + to = &bb->next_bb->rbi->header; else to = &cfg_layout_function_footer; rtl_delete_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. */ struct cfg_hooks rtl_cfg_hooks = { rtl_verify_flow_info, rtl_dump_bb, + rtl_create_basic_block, rtl_redirect_edge_and_branch, rtl_redirect_edge_and_branch_force, rtl_delete_block, rtl_split_block, + rtl_can_merge_blocks, /* can_merge_blocks_p */ + rtl_merge_blocks, rtl_split_edge }; @@ -2469,11 +2700,14 @@ struct cfg_hooks rtl_cfg_hooks = { This representation will hopefully become the default one in future version of the compiler. */ struct cfg_hooks cfg_layout_rtl_cfg_hooks = { - rtl_verify_flow_info_1, /* verify_flow_info. */ + rtl_verify_flow_info_1, rtl_dump_bb, + cfg_layout_create_basic_block, cfg_layout_redirect_edge_and_branch, cfg_layout_redirect_edge_and_branch_force, cfg_layout_delete_block, cfg_layout_split_block, - NULL /* split_edge. */ + cfg_layout_can_merge_blocks_p, + cfg_layout_merge_blocks, + cfg_layout_split_edge }; diff --git a/gcc/flow.c b/gcc/flow.c index b70f8c7..4fab7b3 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -2063,7 +2063,10 @@ propagate_block (basic_block bb, regset live, regset local_set, IOR_REG_SET (regs_live_at_setjmp, pbi->reg_live); 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) break; diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 7ae08da..9c1beec 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -2016,7 +2016,7 @@ merge_if_block (ce_info) fallthru = block_fallthru (bb); if (post_dominators) delete_from_dominance_info (post_dominators, bb); - merge_blocks_nomove (combo_bb, bb); + merge_blocks (combo_bb, bb); num_removed_blocks++; } while (bb != last_test_bb); @@ -2033,7 +2033,7 @@ merge_if_block (ce_info) then_bb->global_live_at_end); if (post_dominators) delete_from_dominance_info (post_dominators, then_bb); - merge_blocks_nomove (combo_bb, then_bb); + merge_blocks (combo_bb, then_bb); num_removed_blocks++; } @@ -2044,7 +2044,7 @@ merge_if_block (ce_info) { if (post_dominators) delete_from_dominance_info (post_dominators, else_bb); - merge_blocks_nomove (combo_bb, else_bb); + merge_blocks (combo_bb, else_bb); num_removed_blocks++; } @@ -2101,7 +2101,7 @@ merge_if_block (ce_info) if (post_dominators) delete_from_dominance_info (post_dominators, join_bb); - merge_blocks_nomove (combo_bb, join_bb); + merge_blocks (combo_bb, join_bb); num_removed_blocks++; } else @@ -3129,7 +3129,7 @@ if_convert (x_life_data_ok) life_data_ok = (x_life_data_ok != 0); /* 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); /* Compute postdominators if we think we'll use them. */ diff --git a/gcc/loop-init.c b/gcc/loop-init.c index 6cae157..a04faefa 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -37,6 +37,9 @@ loop_optimizer_init (dumpfile) struct loops *loops = xcalloc (1, sizeof (struct loops)); edge e; + /* Initialize structures for layout changes. */ + cfg_layout_initialize (); + /* Avoid annoying special cases of edges going to exit block. */ for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next) @@ -47,9 +50,16 @@ loop_optimizer_init (dumpfile) if (flow_loops_find (loops, LOOP_TREE) <= 1) { + basic_block bb; + /* No loops. */ flow_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; } @@ -59,11 +69,8 @@ loop_optimizer_init (dumpfile) free (loops->cfg.dfs_order); loops->cfg.dfs_order = NULL; - /* Initialize structures for layout changes. */ - cfg_layout_initialize (loops); - /* 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_single_succ_latches (loops); @@ -94,7 +101,7 @@ loop_optimizer_finalize (loops, dumpfile) /* Make chain. */ FOR_EACH_BB (bb) if (bb->next_bb != EXIT_BLOCK_PTR) - RBI (bb)->next = bb->next_bb; + bb->rbi->next = bb->next_bb; /* Another dump. */ flow_loops_dump (loops, dumpfile, NULL, 1); diff --git a/gcc/loop-unswitch.c b/gcc/loop-unswitch.c index dd8bcbd..202cbff 100644 --- a/gcc/loop-unswitch.c +++ b/gcc/loop-unswitch.c @@ -377,7 +377,7 @@ unswitch_loop (loops, loop, unswitch_on) entry->flags |= irred_flag; /* 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 it as switch to decide which loop we want to use. */ @@ -395,14 +395,14 @@ unswitch_loop (loops, loop, unswitch_on) switch_bb->succ->succ_next->flags &= ~EDGE_IRREDUCIBLE_LOOP; } 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. */ - for (latch_edge = RBI (loop->latch)->copy->succ; + for (latch_edge = loop->latch->rbi->copy->succ; latch_edge->dest != loop->header; latch_edge = latch_edge->succ_next); 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 fact that cfg_layout_duplicate_bb reverses list of edges. */ diff --git a/gcc/tracer.c b/gcc/tracer.c index ec9b9ba..ba1f09e 100644 --- a/gcc/tracer.c +++ b/gcc/tracer.c @@ -64,7 +64,7 @@ static int branch_ratio_cutoff; /* Return true if BB has been seen - it is connected to some trace 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. */ static bool @@ -295,8 +295,8 @@ tail_duplicate () fprintf (rtl_dump_file, "Duplicated %i as %i [%i]\n", old->index, bb2->index, bb2->frequency); } - RBI (bb)->next = bb2; - RBI (bb2)->visited = 1; + bb->rbi->next = bb2; + bb2->rbi->visited = 1; bb = bb2; /* In case the trace became infrequent, stop duplicating. */ if (ignore_bb_p (bb)) @@ -330,28 +330,28 @@ layout_superblocks () while (bb != EXIT_BLOCK_PTR) { edge e, best = NULL; - while (RBI (end)->next) - end = RBI (end)->next; + while (end->rbi->next) + end = end->rbi->next; for (e = end->succ; e; e = e->succ_next) if (e->dest != EXIT_BLOCK_PTR && e->dest != ENTRY_BLOCK_PTR->succ->dest - && !RBI (e->dest)->visited + && !e->dest->rbi->visited && (!best || EDGE_FREQUENCY (e) > EDGE_FREQUENCY (best))) best = e; if (best) { - RBI (end)->next = best->dest; - RBI (best->dest)->visited = 1; + end->rbi->next = best->dest; + best->dest->rbi->visited = 1; } else for (; bb != EXIT_BLOCK_PTR; bb = bb->next_bb) { - if (!RBI (bb)->visited) + if (!bb->rbi->visited) { - RBI (end)->next = bb; - RBI (bb)->visited = 1; + end->rbi->next = bb; + bb->rbi->visited = 1; break; } } @@ -365,7 +365,7 @@ tracer () { if (n_basic_blocks <= 1) return; - cfg_layout_initialize (NULL); + cfg_layout_initialize (); mark_dfs_back_edges (); if (rtl_dump_file) dump_flow_info (rtl_dump_file); -- 2.7.4