diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-10-09 19:47:18 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-10-09 19:47:18 +0000 |
commit | 2d9b9dfea029c646d489d11eb327a0e72d31051c (patch) | |
tree | 979c66605d3637bf2f02aa8e816c05810e05aa54 /gcc/recog.c | |
parent | 053352b4aa2b1d19c92c926d174856bbb809ae7b (diff) | |
download | gcc-2d9b9dfea029c646d489d11eb327a0e72d31051c.tar.gz |
* Makefile.in (flow.o): Depend on TREE_H.
* basic-block.h (REG_SET_EQUAL_P): New.
(XOR_REG_SET): New.
(n_edges): Declare.
(free_regset_vector): Remove declaration.
(flow_delete_insn_chain): Declare.
(enum update_life_extent): New.
(update_life_info, count_or_remove_death_notes): Declare.
* combine.c (distribute_notes) [REG_DEAD]: Stop search at bb->head.
Verify register live at bb->global_live_at_start before adding USE.
* flow.c (HAVE_epilogue, HAVE_prologue): Provide default.
(CLEAN_ALLOCA): New.
(n_edges): New.
(PROP_*): New flags.
(find_basic_blocks_1): Use alloc_EXPR_LIST.
(clear_edges): Zero n_edges.
(make_edge): Increment n_edges.
(split_edge): Don't allocate bb->local_set. Increment n_edges.
(flow_delete_insn_chain): Export.
(delete_block): Decrement n_edges.
(merge_blocks_nomove): Likewise.
(life_analysis): Give life_analysis_1 PROP flags.
(verify_wide_reg_1, verify_wide_reg): New.
(verify_local_live_at_start): New.
(update_life_info): Rewrite to call into propogate_block.
(mark_reg): New.
(mark_regs_live_at_end): After reload, if epilogue as rtl,
always mark stack pointer. Conditionally mark PIC register.
After reload, mark call-saved registers, return regsiters.
(life_analysis_1): Accept PROP flags not remove_dead_code.
Call mark_regs_live_at_end before zeroing regs_ever_live.
Use calculate_global_regs_live. Copy global_live_at_end before
calling final propagate_block. Zero reg_next_use on exit.
(calculate_global_regs_live): New.
(allocate_bb_life_data): Don't allocate bb->local_set.
(init_regset_vector, free_regset_vector): Remove.
(propagate_block): Accept FLAGS not FINAL or REMOVE_DEAD_CODE.
Test flags before every operation. Warn if prologue/epilogue insn
would have been deleted.
(mark_set_regs, mark_set_1): Accept and use FLAGS.
Use alloc_EXPR_LIST.
(mark_used_regs): Accept and use FLAGS, not FINAL.
Remove special handling for RETURN.
(try_pre_increment): Use alloc_EXPR_LIST.
(dump_flow_info): Dump n_edges.
(unlink_insn_chain, split_hard_reg_notes): Remove.
(maybe_add_dead_note, maybe_add_dead_note_use): Remove.
(find_insn_with_note, new_insn_dead_notes): Remove.
(update_n_sets, sets_reg_or_subreg_1, sets_reg_or_subreg): Remove.
(maybe_remove_dead_notes, prepend_reg_notes): Remove.
(replace_insns): Remove.
(count_or_remove_death_notes): New.
(verify_flow_info): Abort on error after all checks.
(remove_edge): Decrement n_edges.
(remove_fake_edges): Tweek format.
* haifa-sched.c (schedule_insns): Use split_all_insns.
* output.h (update_life_info): Remove declaration.
* recog.c (split_all_insns): From the corpse of split_block_insns,
do the whole function block by block. Use update_life_info.
(recog_last_allowed_insn): New.
(recog_next_insn): Mind it.
(peephole2_optimize): Set it. Walk backwards through blocks.
Use update_life_info.
* rtl.h (update_flow_info, replace_insns): Remove declarations.
(split_all_insns): Declare.
* toplev.c (rest_of_compilation): Thread prologue before flow2.
Use split_all_insns.
* i386.md (or -1 peep2s): Disable.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@29877 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/recog.c')
-rw-r--r-- | gcc/recog.c | 225 |
1 files changed, 135 insertions, 90 deletions
diff --git a/gcc/recog.c b/gcc/recog.c index 5a29920350d..1d277304e2a 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -2562,88 +2562,104 @@ reg_fits_class_p (operand, class, offset, mode) return 0; } -/* Do the splitting of insns in the block B. Only try to actually split if - DO_SPLIT is true; otherwise, just remove nops. */ +/* Split all insns in the function. If UPD_LIFE, update life info after. */ void -split_block_insns (b, do_split) - int b; - int do_split; +split_all_insns (upd_life) + int upd_life; { - rtx insn, next; + sbitmap blocks; + int changed; + int i; + + blocks = sbitmap_alloc (n_basic_blocks); + sbitmap_zero (blocks); + changed = 0; - for (insn = BLOCK_HEAD (b);; insn = next) + for (i = n_basic_blocks - 1; i >= 0; --i) { - rtx set; + basic_block bb = BASIC_BLOCK (i); + rtx insn, next; - /* Can't use `next_real_insn' because that - might go across CODE_LABELS and short-out basic blocks. */ - next = NEXT_INSN (insn); - if (GET_CODE (insn) != INSN) + for (insn = bb->head; insn ; insn = next) { - if (insn == BLOCK_END (b)) - break; + rtx set; - continue; - } + /* Can't use `next_real_insn' because that might go across + CODE_LABELS and short-out basic blocks. */ + next = NEXT_INSN (insn); + if (GET_CODE (insn) != INSN) + ; - /* Don't split no-op move insns. These should silently disappear - later in final. Splitting such insns would break the code - that handles REG_NO_CONFLICT blocks. */ - set = single_set (insn); - if (set && rtx_equal_p (SET_SRC (set), SET_DEST (set))) - { - if (insn == BLOCK_END (b)) - break; + /* Don't split no-op move insns. These should silently + disappear later in final. Splitting such insns would + break the code that handles REG_NO_CONFLICT blocks. */ - /* Nops get in the way while scheduling, so delete them now if - register allocation has already been done. It is too risky - to try to do this before register allocation, and there are - unlikely to be very many nops then anyways. */ - if (reload_completed) + else if ((set = single_set (insn)) != NULL + && rtx_equal_p (SET_SRC (set), SET_DEST (set))) { - - PUT_CODE (insn, NOTE); - NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (insn) = 0; + /* Nops get in the way while scheduling, so delete them + now if register allocation has already been done. It + is too risky to try to do this before register + allocation, and there are unlikely to be very many + nops then anyways. */ + if (reload_completed) + { + PUT_CODE (insn, NOTE); + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; + NOTE_SOURCE_FILE (insn) = 0; + } } - - continue; - } - - if (do_split) - { - /* Split insns here to get max fine-grain parallelism. */ - rtx first = PREV_INSN (insn); - rtx notes = REG_NOTES (insn); - rtx last = try_split (PATTERN (insn), insn, 1); - - if (last != insn) + else { - /* try_split returns the NOTE that INSN became. */ - first = NEXT_INSN (first); -#ifdef INSN_SCHEDULING - update_life_info (notes, first, last, insn, insn); -#endif - PUT_CODE (insn, NOTE); - NOTE_SOURCE_FILE (insn) = 0; - NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - if (insn == BLOCK_HEAD (b)) - BLOCK_HEAD (b) = first; - if (insn == BLOCK_END (b)) + /* Split insns here to get max fine-grain parallelism. */ + rtx first = PREV_INSN (insn); + rtx last = try_split (PATTERN (insn), insn, 1); + + if (last != insn) { - BLOCK_END (b) = last; - break; + SET_BIT (blocks, i); + changed = 1; + + /* try_split returns the NOTE that INSN became. */ + first = NEXT_INSN (first); + PUT_CODE (insn, NOTE); + NOTE_SOURCE_FILE (insn) = 0; + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; + + if (insn == bb->end) + { + bb->end = last; + break; + } } } + + if (insn == bb->end) + break; } - if (insn == BLOCK_END (b)) - break; + /* ??? When we're called from just after reload, the CFG is in bad + shape, and we may have fallen off the end. This could be fixed + by having reload not try to delete unreachable code. Otherwise + assert we found the end insn. */ + if (insn == NULL && upd_life) + abort (); } + + if (changed && upd_life) + { + count_or_remove_death_notes (blocks, 1); + update_life_info (blocks, UPDATE_LIFE_LOCAL); + } + + sbitmap_free (blocks); } #ifdef HAVE_peephole2 +/* This is the last insn we'll allow recog_next_insn to consider. */ +static rtx recog_last_allowed_insn; + /* Return the Nth non-note insn after INSN, or return NULL_RTX if it does not exist. Used by the recognizer to find the next insn to match in a multi-insn pattern. */ @@ -2652,17 +2668,20 @@ recog_next_insn (insn, n) rtx insn; int n; { - while (insn != NULL_RTX && n > 0) + if (insn != NULL_RTX) { - insn = next_nonnote_insn (insn); - - if (insn == NULL_RTX) - return insn; + while (n > 0) + { + if (insn == recog_last_allowed_insn) + return NULL_RTX; - if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') - return NULL_RTX; + insn = NEXT_INSN (insn); + if (insn == NULL_RTX) + break; - n--; + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') + n -= 1; + } } return insn; @@ -2673,38 +2692,64 @@ void peephole2_optimize (dump_file) FILE *dump_file ATTRIBUTE_UNUSED; { - rtx insn; - rtx epilogue_insn = 0; + rtx insn, prev; + int i, changed; + sbitmap blocks; - for (insn = get_last_insn (); insn != NULL_RTX; insn = PREV_INSN (insn)) - { - if (GET_CODE (insn) == NOTE - && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG) - { - epilogue_insn = insn; - break; - } - } + /* ??? TODO: Arrange with resource.c to start at bb->global_live_at_end + and backtrack insn by insn as we proceed through the block. In this + way we'll not need to keep searching forward from the beginning of + basic blocks to find register life info. */ - init_resource_info (epilogue_insn); + init_resource_info (NULL); - for (insn = get_insns (); insn != NULL; - insn = next_nonnote_insn (insn)) + blocks = sbitmap_alloc (n_basic_blocks); + sbitmap_zero (blocks); + changed = 0; + + for (i = n_basic_blocks - 1; i >= 0; --i) { - if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) - { - rtx last_insn; - rtx before = PREV_INSN (insn); + basic_block bb = BASIC_BLOCK (i); + + /* Since we don't update life info until the very end, we can't + allow matching instructions that we've replaced before. Walk + backward through the basic block so that we don't have to + care about subsequent life info; recog_last_allowed_insn to + restrict how far forward we will allow the match to proceed. */ - rtx try = peephole2_insns (PATTERN (insn), insn, &last_insn); - if (try != NULL) + recog_last_allowed_insn = bb->end; + for (insn = bb->end; ; insn = prev) + { + prev = PREV_INSN (insn); + if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') { - replace_insns (insn, last_insn, try, NULL_RTX); - insn = NEXT_INSN (before); + rtx try, last_insn; + + try = peephole2_insns (PATTERN (insn), insn, &last_insn); + if (try != NULL) + { + flow_delete_insn_chain (insn, last_insn); + try = emit_insn_after (try, prev); + + if (last_insn == bb->end) + bb->end = try; + if (insn == bb->head) + bb->head = NEXT_INSN (prev); + + recog_last_allowed_insn = prev; + SET_BIT (blocks, i); + changed = 1; + } } + + if (insn == bb->head) + break; } } free_resource_info (); + + count_or_remove_death_notes (blocks, 1); + update_life_info (blocks, UPDATE_LIFE_LOCAL); } #endif |