diff options
author | Jan Hubicka <jh@suse.cz> | 2003-06-06 11:24:26 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2003-06-06 09:24:26 +0000 |
commit | 9ee634e345c67ea1aa84591aa91c7e18020c19ae (patch) | |
tree | 366519e64f386e83f2c89bfffb438c340d608e78 /gcc/cfgrtl.c | |
parent | 7654db1b6667c4bb7fa927c3628cf661ca8465d9 (diff) | |
download | gcc-9ee634e345c67ea1aa84591aa91c7e18020c19ae.tar.gz |
function.c (FLOOR_ROUND, CEIL_ROUND): Fix.
* function.c (FLOOR_ROUND, CEIL_ROUND): Fix.
* i386.md (gen_pro_epilogue_adjust_stack): Deal with gigantic stack frames.
(pro_epilogue_adjust_stack_rex64_2): New pattern
* cfghooks.h, cfghooks.c: New files.
* Makefile.in (BASIC_BLOCK_H): Depends on cfghooks.h.
(OBJS): Add cfghooks.o.
(cfghooks.o): New rule.
* basic-block.h (split_edge): Rename to rtl_split_edge.
(verify_flow_info): Rename to rtl_verify_flow_info.
(cfghooks.h): Included here.
* cfgrtl.c (split_edge): Renamed rtl_split_edge.
(verify_flow_info): Renamed rtl_verify_flow_info.
* toplev.c (rest_of_compilation): Call rtl_register_cfg_hooks.
* basic-block.h (split_block, split_edge, flow_delete_block,
redirect_edge_and_branch, redirect_edge_and_branch_force): Delete.
(flow_delete_block_noexpunge): Return void.
* cfg.c (verify_flow_info): New function.
* cfgcleanup.c (try_simplify_condjump, outgoing_edges_match,
try_crossjump_to_edge, try_optimize_cfg, delete_unreachable_blocks):
Use delete_block.
* cfglayout.c (function_footer): Rename to...
(cfg_layout_function_footer): ... this variable
(unlink_insn_chain): Make global.
(fixup_reorder_chain, record_effective_endpoints): Update.
(cleanup_unconditional_jumps): Use delete_block.
(cfg_layout_redirect_edge, cfg_layout_split_block): Move to cfgrtl.c
(cfg_layout_duplicate_bb): Use redirect_edge_and_branch_force.
(cfg_layout_initialize, cfg_layout_finalize): Update hooks.
* cfglayout.h (cfg_layout_redirect_edge, cfg_layout_split_block): Delete.
(cfg_layout_function_footer): Declare.
* cfgloopmanip (split_loop_bb): Do not update RBI.
(remove_bbs): Use delete_block.
(loop_reidrect_edge, loop_delete_branch_edge): Use
redirect_edge_and_branch.
(create_preheader): Use split_block and redirect_edge_and_branch_force.
(split_edge_with): Likewise.
* cfgrtl.c: Include cfglayout.h
(split_edge): Rename to ...
(rtl_split_edge) ... this one; make local.
(redirect_edge_and_branch): Rename to ...
(rtl_redirect_edge_and_branch) ... this one; make local.
(redirect_edge_and_branch_force): Rename to ...
(rtl_redirect_edge_and_branch_force) ... this one; make local.
(cfg_layout_delete_block, cfg_layout_delete_edge_and_branch_force): New.
(cfg_layout_redirect_edge_and_branch, cfg_layout_split_block): Move here from
cfglayout.c; update to directly call RTL counterparts.
(rtl_cfg_hooks, cfg_layout_rtl_cfg_hooks): New functions.
* ifcvt.c (find_cond_trap): Use delete_block.
(find_if_case_1): Use delete_block.
(find_if_case_2): Use delete_block.
* rtl.h (unlink_insn_chain): Declare.
* toplev.c (rtl_reigster_cfg_hooks): New.
From-SVN: r67535
Diffstat (limited to 'gcc/cfgrtl.c')
-rw-r--r-- | gcc/cfgrtl.c | 213 |
1 files changed, 194 insertions, 19 deletions
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 0ba32c5782e..b0678f09f1c 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -26,7 +26,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA - CFG-aware instruction chain manipulation delete_insn, delete_insn_chain - Basic block manipulation - create_basic_block, flow_delete_block, split_block, + create_basic_block, rtl_delete_block,rtl_split_block, merge_blocks_nomove - Infrastructure to determine quickly basic block for insn compute_bb_for_insn, update_bb_for_insn, set_block_for_insn, @@ -59,6 +59,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "tm_p.h" #include "obstack.h" #include "insn-config.h" +#include "cfglayout.h" /* Stubs in case we don't have a return insn. */ #ifndef HAVE_return @@ -79,6 +80,16 @@ static bool try_redirect_by_replacing_jump PARAMS ((edge, basic_block)); static rtx last_loop_beg_note PARAMS ((rtx)); static bool back_edge_of_syntactic_loop_p PARAMS ((basic_block, basic_block)); basic_block force_nonfallthru_and_redirect PARAMS ((edge, basic_block)); +static basic_block rtl_split_edge PARAMS ((edge)); +static void rtl_verify_flow_info PARAMS ((void)); +static edge cfg_layout_split_block PARAMS ((basic_block, void *)); +static bool cfg_layout_redirect_edge_and_branch PARAMS ((edge, basic_block)); +static basic_block cfg_layout_redirect_edge_and_branch_force PARAMS ((edge, basic_block)); +static void cfg_layout_delete_block PARAMS ((basic_block)); +static void rtl_delete_block PARAMS ((basic_block)); +static basic_block rtl_redirect_edge_and_branch_force PARAMS ((edge, basic_block)); +static bool rtl_redirect_edge_and_branch PARAMS ((edge, basic_block)); +static edge rtl_split_block PARAMS ((basic_block, void *)); /* Return true if NOTE is not one of the ones that must be kept paired, so that we may simply delete it. */ @@ -348,11 +359,10 @@ create_basic_block (head, end, after) /* ??? Preserving all such notes strikes me as wrong. It would be nice to post-process the stream to remove empty blocks, loops, ranges, etc. */ -int +void flow_delete_block_noexpunge (b) basic_block b; { - int deleted_handler = 0; rtx insn, end, tmp; /* If the head of this block is a CODE_LABEL, then it might be the @@ -404,20 +414,16 @@ flow_delete_block_noexpunge (b) b->pred = NULL; b->succ = NULL; - - return deleted_handler; } -int -flow_delete_block (b) +static void +rtl_delete_block (b) basic_block b; { - int deleted_handler = flow_delete_block_noexpunge (b); + flow_delete_block_noexpunge (b); /* Remove the basic block from the array. */ expunge_block (b); - - return deleted_handler; } /* Records the basic block struct in BLOCK_FOR_INSN for every insn. */ @@ -474,14 +480,15 @@ update_bb_for_insn (bb) this function renumbers all the basic blocks so that the new one has a number one greater than the block split. */ -edge -split_block (bb, insn) +static edge +rtl_split_block (bb, insnp) basic_block bb; - rtx insn; + void *insnp; { basic_block new_bb; edge new_edge; edge e; + rtx insn = insnp; /* There is no point splitting the block after its end. */ if (bb->end == insn) @@ -811,8 +818,8 @@ last_loop_beg_note (insn) already destinated TARGET and we didn't managed to simplify instruction stream. */ -bool -redirect_edge_and_branch (e, target) +static bool +rtl_redirect_edge_and_branch (e, target) edge e; basic_block target; { @@ -1076,8 +1083,8 @@ force_nonfallthru (e) basic block. Return new basic block if created, NULL otherwise. Abort if conversion is impossible. */ -basic_block -redirect_edge_and_branch_force (e, target) +static basic_block +rtl_redirect_edge_and_branch_force (e, target) edge e; basic_block target; { @@ -1230,7 +1237,7 @@ back_edge_of_syntactic_loop_p (bb1, bb2) block with multiple predecessors is not handled optimally. */ basic_block -split_edge (edge_in) +rtl_split_edge (edge_in) edge edge_in; { basic_block bb; @@ -1741,7 +1748,7 @@ update_br_prob_note (bb) (reachability of basic blocks, life information, etc. etc.). */ void -verify_flow_info () +rtl_verify_flow_info () { const int max_uid = get_max_uid (); const rtx rtx_first = get_insns (); @@ -2363,3 +2370,171 @@ purge_all_dead_edges (update_life_p) sbitmap_free (blocks); return purged; } + +/* Same as split_block but update cfg_layout structures. */ +static edge +cfg_layout_split_block (bb, insnp) + basic_block bb; + void *insnp; +{ + rtx insn = 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; + return fallthru; +} + + +/* Redirect Edge to DEST. */ +static bool +cfg_layout_redirect_edge_and_branch (e, dest) + edge e; + basic_block dest; +{ + basic_block src = e->src; + basic_block old_next_bb = src->next_bb; + bool ret; + + /* 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. */ + if (GET_CODE (src->end) == JUMP_INSN + && JUMP_LABEL (src->end) == e->dest->head) + { + if (!redirect_jump (src->end, block_label (dest), 0)) + abort (); + } + /* In case we are redirecting fallthru edge to the branch edge + of conditional jump, remove it. */ + if (src->succ->succ_next + && !src->succ->succ_next->succ_next) + { + edge s = e->succ_next ? e->succ_next : src->succ; + if (s->dest == dest + && any_condjump_p (src->end) + && onlyjump_p (src->end)) + delete_insn (src->end); + } + redirect_edge_succ_nodup (e, dest); + + ret = true; + } + else + ret = rtl_redirect_edge_and_branch (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; + + return ret; +} + +/* Simple wrapper as we always can redirect fallthru edges. */ +static basic_block +cfg_layout_redirect_edge_and_branch_force (e, dest) + edge e; + basic_block dest; +{ + if (!cfg_layout_redirect_edge_and_branch (e, dest)) + abort (); + return NULL; +} + +/* Same as flow_delete_block but update cfg_layout structures. */ +static void +cfg_layout_delete_block (bb) + basic_block bb; +{ + rtx insn, next, prev = PREV_INSN (bb->head), *to, remaints; + + if (RBI (bb)->header) + { + next = bb->head; + if (prev) + NEXT_INSN (prev) = RBI (bb)->header; + else + set_first_insn (RBI (bb)->header); + PREV_INSN (RBI (bb)->header) = prev; + insn = RBI (bb)->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) + { + 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); + } + if (bb->next_bb != EXIT_BLOCK_PTR) + to = &RBI(bb->next_bb)->header; + else + to = &cfg_layout_function_footer; + rtl_delete_block (bb); + + if (prev) + prev = NEXT_INSN (prev); + else + prev = get_insns (); + if (next) + next = PREV_INSN (next); + else + next = get_last_insn (); + + if (next && NEXT_INSN (next) != prev) + { + remaints = unlink_insn_chain (prev, next); + insn = remaints; + while (NEXT_INSN (insn)) + insn = NEXT_INSN (insn); + NEXT_INSN (insn) = *to; + if (*to) + PREV_INSN (*to) = insn; + *to = remaints; + } +} + +/* Implementation of CFG manipulation for linearized RTL. */ +struct cfg_hooks rtl_cfg_hooks = { + rtl_verify_flow_info, + rtl_redirect_edge_and_branch, + rtl_redirect_edge_and_branch_force, + rtl_delete_block, + rtl_split_block, + rtl_split_edge +}; + +/* Implementation of CFG manipulation for cfg layout RTL, where + basic block connected via fallthru edges does not have to be adjacent. + This representation will hopefully become the default one in future + version of the compiler. */ +struct cfg_hooks cfg_layout_rtl_cfg_hooks = { + NULL, /* verify_flow_info. */ + cfg_layout_redirect_edge_and_branch, + cfg_layout_redirect_edge_and_branch_force, + cfg_layout_delete_block, + cfg_layout_split_block, + NULL /* split_edge. */ +}; |