diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-02-06 10:03:13 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-02-06 10:03:13 +0000 |
commit | 505f406ce35ec8e0eb962365527d3634b9a50cf9 (patch) | |
tree | d48ce6d178524f715563dd56706ee443cb3f0d5b /gcc/sched-ebb.c | |
parent | 84d86c97c8e0abda6fd63eeb2d8cc905e0ddb06e (diff) | |
download | gcc-505f406ce35ec8e0eb962365527d3634b9a50cf9.tar.gz |
* i386.c (x86_inter_unit_moves): New variable.
(ix86_secondary_memory_needed): Fix 64bit case, honor
TARGET_INTER_UNIT_MOVES
* i386.h (x86_inter_unit_moves): Declare.
(TARGET_INTER_UNIT_MOVES): New macro.
* i386.md (movsi_1): Cleanup constraints; disable
when not doing inter-unit moves.
(movsi_1_nointernunit): New.
(movdi_1_rex64): Fix constraints; deal with SSE->GPR moves.
(movdi_1_rex64_nointerunit): New.
(mivsf_1): disable when not doing inter-unit moves.
(movsf_1_nointerunit): New.
* basic-block.h (inside_basic_block_p): Declare.
* cfgbuild.c (inside_basic_block_p): Make global.
* haifa-sched.c (unlink_other_notes0: Deal with NOT_INSN_BASIC_BLOCK.
* scheudle-ebb.c (schedule_ebb): Return last basic block of trace;
update CFG.
(fix_basic_block_boundaries, add_missing_bbs): New.
(rank): Use profile.
(scheudle_ebbs): Rely on CFG; update coments.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@62477 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/sched-ebb.c')
-rw-r--r-- | gcc/sched-ebb.c | 183 |
1 files changed, 165 insertions, 18 deletions
diff --git a/gcc/sched-ebb.c b/gcc/sched-ebb.c index 5fa64f1f623..c298453f798 100644 --- a/gcc/sched-ebb.c +++ b/gcc/sched-ebb.c @@ -56,7 +56,9 @@ static const char *ebb_print_insn PARAMS ((rtx, int)); static int rank PARAMS ((rtx, rtx)); static int contributes_to_priority PARAMS ((rtx, rtx)); static void compute_jump_reg_dependencies PARAMS ((rtx, regset)); -static void schedule_ebb PARAMS ((rtx, rtx)); +static basic_block schedule_ebb PARAMS ((rtx, rtx)); +static basic_block fix_basic_block_boundaries PARAMS ((basic_block, basic_block, rtx, rtx)); +static void add_missing_bbs PARAMS ((rtx, basic_block, basic_block)); /* Return nonzero if there are more insns that should be scheduled. */ @@ -139,8 +141,17 @@ ebb_print_insn (insn, aligned) static int rank (insn1, insn2) - rtx insn1 ATTRIBUTE_UNUSED, insn2 ATTRIBUTE_UNUSED; + rtx insn1, insn2; { + basic_block bb1 = BLOCK_FOR_INSN (insn1); + basic_block bb2 = BLOCK_FOR_INSN (insn2); + + if (bb1->count > bb2->count + || bb1->frequency > bb2->frequency) + return -1; + if (bb1->count < bb2->count + || bb1->frequency < bb2->frequency) + return 1; return 0; } @@ -192,18 +203,157 @@ static struct sched_info ebb_sched_info = 0, 1 }; +/* It is possible that ebb scheduling elliminated some blocks. + Place blocks from FIRST to LAST before BEFORE. */ + +static void +add_missing_bbs (before, first, last) + rtx before; + basic_block first, last; +{ + for (; last != first->prev_bb; last = last->prev_bb) + { + before = emit_note_before (NOTE_INSN_BASIC_BLOCK, before); + NOTE_BASIC_BLOCK (before) = last; + last->head = before; + last->end = before; + update_bb_for_insn (last); + } +} + +/* Fixup the CFG after EBB scheduling. Re-recognize the basic + block boundaries in between HEAD and TAIL and update basic block + structures between BB and LAST. */ + +static basic_block +fix_basic_block_boundaries (bb, last, head, tail) + basic_block bb, last; + rtx head, tail; +{ + rtx insn = head; + rtx last_inside = bb->head; + rtx aftertail = NEXT_INSN (tail); + + head = bb->head; + + for (; insn != aftertail; insn = NEXT_INSN (insn)) + { + if (GET_CODE (insn) == CODE_LABEL) + abort (); + /* Create new basic blocks just before first insn. */ + if (inside_basic_block_p (insn)) + { + if (!last_inside) + { + rtx note; + + /* Re-emit the basic block note for newly found BB header. */ + if (GET_CODE (insn) == CODE_LABEL) + { + note = emit_note_after (NOTE_INSN_BASIC_BLOCK, insn); + head = insn; + last_inside = note; + } + else + { + note = emit_note_before (NOTE_INSN_BASIC_BLOCK, insn); + head = note; + last_inside = insn; + } + } + else + last_inside = insn; + } + /* Control flow instruction terminate basic block. It is possible + that we've elliminated some basic blocks (made them empty). + Find the proper basic block using BLOCK_FOR_INSN and arrange things in + a sensible way by inserting empty basic blocks as needed. */ + if (control_flow_insn_p (insn) || (insn == tail && last_inside)) + { + basic_block curr_bb = BLOCK_FOR_INSN (insn); + rtx note; + + if (!control_flow_insn_p (insn)) + curr_bb = last; + if (bb == last->next_bb) + { + edge f; + rtx h; + + /* An obscure special case, where we do have partially dead + instruction scheduled after last control flow instruction. + In this case we can create new basic block. It is + always exactly one basic block last in the sequence. Handle + it by splitting the edge and repositioning the block. + This is somewhat hackish, but at least avoid cut&paste + + Safter sollution 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; + + if (f) + { + last = curr_bb = split_edge (f); + h = curr_bb->head; + curr_bb->head = head; + curr_bb->end = insn; + /* Edge splitting created missplaced BASIC_BLOCK note, kill + it. */ + delete_insn (h); + } + /* It may happen that code got moved past unconditional jump in + case the code is completely dead. Kill it. */ + else + { + rtx next = next_nonnote_insn (insn); + delete_insn_chain (head, insn); + /* We keep some notes in the way that may split barrier from the + jump. */ + if (GET_CODE (next) == BARRIER) + { + emit_barrier_after (prev_nonnote_insn (head)); + delete_insn (next); + } + insn = NULL; + } + } + else + { + curr_bb->head = head; + curr_bb->end = insn; + add_missing_bbs (curr_bb->head, bb, curr_bb->prev_bb); + } + note = GET_CODE (head) == CODE_LABEL ? NEXT_INSN (head) : head; + NOTE_BASIC_BLOCK (note) = curr_bb; + update_bb_for_insn (curr_bb); + bb = curr_bb->next_bb; + last_inside = NULL; + if (!insn) + break; + } + } + add_missing_bbs (last->next_bb->head, bb, last); + return bb->prev_bb; +} + /* Schedule a single extended basic block, defined by the boundaries HEAD and TAIL. */ -static void +static basic_block schedule_ebb (head, tail) rtx head, tail; { int n_insns; + basic_block b; struct deps tmp_deps; + basic_block first_bb = BLOCK_FOR_INSN (head); + basic_block last_bb = BLOCK_FOR_INSN (tail); if (no_real_insns_p (head, tail)) - return; + return BLOCK_FOR_INSN (tail); init_deps_global (); @@ -266,8 +416,10 @@ schedule_ebb (head, tail) if (write_symbols != NO_DEBUG) restore_line_notes (head, tail); + b = fix_basic_block_boundaries (first_bb, last_bb, head, tail); finish_deps_global (); + return b; } /* The one entry point in this file. DUMP_FILE is the dump file for @@ -309,17 +461,8 @@ schedule_ebbs (dump_file) break; if (! e) break; - if (GET_CODE (tail) == JUMP_INSN) - { - rtx x = find_reg_note (tail, REG_BR_PROB, 0); - if (x) - { - int pred_val = INTVAL (XEXP (x, 0)); - if (pred_val > REG_BR_PROB_BASE / 2) - break; - } - } - + if (e->probability < REG_BR_PROB_BASE / 2) + break; bb = bb->next_bb; } @@ -337,11 +480,11 @@ schedule_ebbs (dump_file) break; } - schedule_ebb (head, tail); + bb = schedule_ebb (head, tail); } - /* It doesn't make much sense to try and update life information here - we - probably messed up even the flow graph. */ + /* Updating life info can be done by local propagation over the modified + superblocks. */ /* Reposition the prologue and epilogue notes in case we moved the prologue/epilogue insns. */ @@ -352,4 +495,8 @@ schedule_ebbs (dump_file) rm_redundant_line_notes (); sched_finish (); + +#ifdef ENABLE_CHECKING + verify_flow_info (); +#endif } |