X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fsched-ebb.c;h=4f97b7c7c5431d263bb011d42b4cd18d83df2dac;hb=1e5fcbe2009a34584768d8b8833756bc8de97dc3;hp=0e316b51d6616154715f1919881c429bb76ebcaa;hpb=60b8c5b34ab84501de6a513517a9e78e3e2c4d00;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/sched-ebb.c b/gcc/sched-ebb.c index 0e316b51d66..4f97b7c7c54 100644 --- a/gcc/sched-ebb.c +++ b/gcc/sched-ebb.c @@ -1,6 +1,6 @@ /* Instruction scheduling pass. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by, and currently maintained by, Jim Wilson (wilson@cygnus.com) @@ -39,6 +39,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "toplev.h" #include "recog.h" #include "cfglayout.h" +#include "params.h" #include "sched-int.h" #include "target.h" @@ -55,7 +56,7 @@ static int schedule_more_p (void); static const char *ebb_print_insn (rtx, int); static int rank (rtx, rtx); static int contributes_to_priority (rtx, rtx); -static void compute_jump_reg_dependencies (rtx, regset); +static void compute_jump_reg_dependencies (rtx, regset, regset, regset); static basic_block earliest_block_with_similiar_load (basic_block, rtx); static void add_deps_for_risky_insns (rtx, rtx); static basic_block schedule_ebb (rtx, rtx); @@ -163,20 +164,29 @@ contributes_to_priority (rtx next ATTRIBUTE_UNUSED, return 1; } -/* INSN is a JUMP_INSN. Store the set of registers that must be considered - to be set by this jump in SET. */ + /* INSN is a JUMP_INSN, COND_SET is the set of registers that are + conditionally set before INSN. Store the set of registers that + must be considered as used by this jump in USED and that of + registers that must be considered as set in SET. */ static void -compute_jump_reg_dependencies (rtx insn, regset set) +compute_jump_reg_dependencies (rtx insn, regset cond_set, regset used, + regset set) { basic_block b = BLOCK_FOR_INSN (insn); edge e; - for (e = b->succ; e; e = e->succ_next) - if ((e->flags & EDGE_FALLTHRU) == 0) - { - bitmap_operation (set, set, e->dest->global_live_at_start, - BITMAP_IOR); - } + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, b->succs) + if (e->flags & EDGE_FALLTHRU) + /* The jump may be a by-product of a branch that has been merged + in the main codepath after being conditionalized. Therefore + it may guard the fallthrough block from using a value that has + conditionally overwritten that of the main codepath. So we + consider that it restores the value of the main codepath. */ + bitmap_and (set, e->dest->global_live_at_start, cond_set); + else + bitmap_ior_into (used, e->dest->global_live_at_start); } /* Used in schedule_insns to initialize current_sched_info for scheduling @@ -195,7 +205,7 @@ static struct sched_info ebb_sched_info = NULL, NULL, NULL, NULL, - 0, 1 + 0, 1, 0 }; /* It is possible that ebb scheduling eliminated some blocks. @@ -208,8 +218,8 @@ add_missing_bbs (rtx before, basic_block first, basic_block last) { before = emit_note_before (NOTE_INSN_BASIC_BLOCK, before); NOTE_BASIC_BLOCK (before) = last; - last->head = before; - last->end = before; + BB_HEAD (last) = before; + BB_END (last) = before; update_bb_for_insn (last); } } @@ -223,15 +233,14 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head, rtx tail) { rtx insn = head; - rtx last_inside = bb->head; + rtx last_inside = BB_HEAD (bb); rtx aftertail = NEXT_INSN (tail); - head = bb->head; + head = BB_HEAD (bb); for (; insn != aftertail; insn = NEXT_INSN (insn)) { - if (GET_CODE (insn) == CODE_LABEL) - abort (); + gcc_assert (!LABEL_P (insn)); /* Create new basic blocks just before first insn. */ if (inside_basic_block_p (insn)) { @@ -240,7 +249,7 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head, rtx note; /* Re-emit the basic block note for newly found BB header. */ - if (GET_CODE (insn) == CODE_LABEL) + if (LABEL_P (insn)) { note = emit_note_after (NOTE_INSN_BASIC_BLOCK, insn); head = insn; @@ -271,6 +280,7 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head, { edge f; rtx h; + edge_iterator ei; /* An obscure special case, where we do have partially dead instruction scheduled after last control flow instruction. @@ -282,16 +292,17 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head, A safer solution can be to bring the code into sequence, do the split and re-emit it back in case this will ever trigger problem. */ - f = bb->prev_bb->succ; - while (f && !(f->flags & EDGE_FALLTHRU)) - f = f->succ_next; + + FOR_EACH_EDGE (f, ei, bb->prev_bb->succs) + if (f->flags & EDGE_FALLTHRU) + break; if (f) { last = curr_bb = split_edge (f); - h = curr_bb->head; - curr_bb->head = head; - curr_bb->end = insn; + h = BB_HEAD (curr_bb); + BB_HEAD (curr_bb) = head; + BB_END (curr_bb) = insn; /* Edge splitting created misplaced BASIC_BLOCK note, kill it. */ delete_insn (h); @@ -304,7 +315,7 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head, delete_insn_chain (head, insn); /* We keep some notes in the way that may split barrier from the jump. */ - if (GET_CODE (next) == BARRIER) + if (BARRIER_P (next)) { emit_barrier_after (prev_nonnote_insn (head)); delete_insn (next); @@ -314,11 +325,11 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head, } else { - curr_bb->head = head; - curr_bb->end = insn; - add_missing_bbs (curr_bb->head, bb, curr_bb->prev_bb); + BB_HEAD (curr_bb) = head; + BB_END (curr_bb) = insn; + add_missing_bbs (BB_HEAD (curr_bb), bb, curr_bb->prev_bb); } - note = GET_CODE (head) == CODE_LABEL ? NEXT_INSN (head) : head; + note = LABEL_P (head) ? NEXT_INSN (head) : head; NOTE_BASIC_BLOCK (note) = curr_bb; update_bb_for_insn (curr_bb); bb = curr_bb->next_bb; @@ -327,7 +338,7 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head, break; } } - add_missing_bbs (last->next_bb->head, bb, last); + add_missing_bbs (BB_HEAD (last->next_bb), bb, last); return bb->prev_bb; } @@ -410,7 +421,7 @@ add_deps_for_risky_insns (rtx head, rtx tail) basic_block last_block = NULL, bb; for (insn = head; insn != next_tail; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == JUMP_INSN) + if (JUMP_P (insn)) { bb = BLOCK_FOR_INSN (insn); bb->aux = last_block; @@ -432,10 +443,10 @@ add_deps_for_risky_insns (rtx head, rtx tail) bb = bb->aux; if (!bb) break; - prev = bb->end; + prev = BB_END (bb); } } - /* FALLTHRU */ + /* Fall through. */ case TRAP_RISKY: case IRISKY: case PRISKY_CANDIDATE: @@ -532,8 +543,7 @@ schedule_ebb (rtx head, rtx tail) schedule_block (-1, n_insns); /* Sanity check: verify that all region insns were scheduled. */ - if (sched_n_insns != n_insns) - abort (); + gcc_assert (sched_n_insns == n_insns); head = current_sched_info->head; tail = current_sched_info->tail; @@ -552,6 +562,13 @@ void schedule_ebbs (FILE *dump_file) { basic_block bb; + int probability_cutoff; + + if (profile_info && flag_branch_probabilities) + probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK); + else + probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY); + probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff; /* Taking care of this degenerate case makes the rest of this code simpler. */ @@ -562,28 +579,28 @@ schedule_ebbs (FILE *dump_file) current_sched_info = &ebb_sched_info; - allocate_reg_life_data (); compute_bb_for_insn (); /* Schedule every region in the subroutine. */ FOR_EACH_BB (bb) { - rtx head = bb->head; + rtx head = BB_HEAD (bb); rtx tail; for (;;) { edge e; - tail = bb->end; + edge_iterator ei; + tail = BB_END (bb); if (bb->next_bb == EXIT_BLOCK_PTR - || GET_CODE (bb->next_bb->head) == CODE_LABEL) + || LABEL_P (BB_HEAD (bb->next_bb))) break; - for (e = bb->succ; e; e = e->succ_next) + FOR_EACH_EDGE (e, ei, bb->succs) if ((e->flags & EDGE_FALLTHRU) != 0) break; if (! e) break; - if (e->probability < REG_BR_PROB_BASE / 2) + if (e->probability <= probability_cutoff) break; bb = bb->next_bb; } @@ -592,11 +609,11 @@ schedule_ebbs (FILE *dump_file) a note or two. */ while (head != tail) { - if (GET_CODE (head) == NOTE) + if (NOTE_P (head)) head = NEXT_INSN (head); - else if (GET_CODE (tail) == NOTE) + else if (NOTE_P (tail)) tail = PREV_INSN (tail); - else if (GET_CODE (head) == CODE_LABEL) + else if (LABEL_P (head)) head = NEXT_INSN (head); else break;