Mercurial > hg > CbC > CbC_gcc
diff gcc/sel-sched.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
line wrap: on
line diff
--- a/gcc/sel-sched.c Tue May 25 18:58:51 2010 +0900 +++ b/gcc/sel-sched.c Tue Mar 22 17:18:12 2011 +0900 @@ -1,5 +1,6 @@ /* Instruction scheduling pass. Selective scheduler and pipeliner. - Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GCC. @@ -21,8 +22,7 @@ #include "system.h" #include "coretypes.h" #include "tm.h" -#include "toplev.h" -#include "rtl.h" +#include "rtl-error.h" #include "tm_p.h" #include "hard-reg-set.h" #include "regs.h" @@ -31,7 +31,6 @@ #include "insn-config.h" #include "insn-attr.h" #include "except.h" -#include "toplev.h" #include "recog.h" #include "params.h" #include "target.h" @@ -45,6 +44,7 @@ #include "langhooks.h" #include "rtlhooks-def.h" #include "output.h" +#include "emit-rtl.h" #ifdef INSN_SCHEDULING #include "sel-sched-ir.h" @@ -613,12 +613,14 @@ in_fallthru_bb_p (rtx insn, rtx succ) { basic_block bb = BLOCK_FOR_INSN (insn); + edge e; if (bb == BLOCK_FOR_INSN (succ)) return true; - if (find_fallthru_edge (bb)) - bb = find_fallthru_edge (bb)->dest; + e = find_fallthru_edge_from (bb); + if (e) + bb = e->dest; else return false; @@ -836,7 +838,8 @@ if (GET_CODE (*cur_rtx) == SUBREG && REG_P (p->x) - && REGNO (SUBREG_REG (*cur_rtx)) == REGNO (p->x)) + && (!REG_P (SUBREG_REG (*cur_rtx)) + || REGNO (SUBREG_REG (*cur_rtx)) == REGNO (p->x))) { /* ??? Do not support substituting regs inside subregs. In that case, simplify_subreg will be called by validate_replace_rtx, and @@ -1137,6 +1140,9 @@ /* Can't use regs which aren't saved by the prologue. */ || !TEST_HARD_REG_BIT (sel_hrd.regs_ever_used, cur_reg + i) + /* Can't use regs with non-null REG_BASE_VALUE, because adjusting + it affects aliasing globally and invalidates all AV sets. */ + || get_reg_base_value (cur_reg + i) #ifdef LEAF_REGISTERS /* We can't use a non-leaf register if we're in a leaf function. */ @@ -1236,7 +1242,7 @@ frame pointer, or we could not discover its class. */ if (fixed_regs[regno] || global_regs[regno] -#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM +#if !HARD_FRAME_POINTER_IS_FRAME_POINTER || (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM) #else || (frame_pointer_needed && regno == FRAME_POINTER_REGNUM) @@ -1263,7 +1269,7 @@ SET_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, FRAME_POINTER_REGNUM + i); -#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM +#if !HARD_FRAME_POINTER_IS_FRAME_POINTER for (i = hard_regno_nregs[HARD_FRAME_POINTER_REGNUM][Pmode]; i--;) SET_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, HARD_FRAME_POINTER_REGNUM + i); @@ -2136,6 +2142,15 @@ ds_t *has_dep_p; ds_t full_ds; + /* ??? We use dependencies of non-debug insns on debug insns to + indicate that the debug insns need to be reset if the non-debug + insn is pulled ahead of it. It's hard to figure out how to + introduce such a notion in sel-sched, but it already fails to + support debug insns in other ways, so we just go ahead and + let the deug insns go corrupt for now. */ + if (DEBUG_INSN_P (through_insn) && !DEBUG_INSN_P (insn)) + return MOVEUP_EXPR_SAME; + /* When inside_insn_group, delegate to the helper. */ if (inside_insn_group) return moveup_expr_inside_insn_group (expr, through_insn); @@ -2166,10 +2181,8 @@ || ! in_current_region_p (fallthru_bb)) return MOVEUP_EXPR_NULL; - /* And it should be mutually exclusive with through_insn, or - be an unconditional jump. */ - if (! any_uncondjump_p (insn) - && ! sched_insns_conditions_mutex_p (insn, through_insn) + /* And it should be mutually exclusive with through_insn. */ + if (! sched_insns_conditions_mutex_p (insn, through_insn) && ! DEBUG_INSN_P (through_insn)) return MOVEUP_EXPR_NULL; } @@ -2736,7 +2749,7 @@ /* Add insn to to the tail of current path. */ ilist_add (&p, insn); - for (is = 0; VEC_iterate (rtx, sinfo->succs_ok, is, succ); is++) + FOR_EACH_VEC_ELT (rtx, sinfo->succs_ok, is, succ) { av_set_t succ_set; @@ -2790,7 +2803,7 @@ /* Check liveness restrictions via hard way when there are more than two successors. */ if (sinfo->succs_ok_n > 2) - for (is = 0; VEC_iterate (rtx, sinfo->succs_ok, is, succ); is++) + FOR_EACH_VEC_ELT (rtx, sinfo->succs_ok, is, succ) { basic_block succ_bb = BLOCK_FOR_INSN (succ); @@ -2801,7 +2814,7 @@ /* Finally, check liveness restrictions on paths leaving the region. */ if (sinfo->all_succs_n > sinfo->succs_ok_n) - for (is = 0; VEC_iterate (rtx, sinfo->succs_other, is, succ); is++) + FOR_EACH_VEC_ELT (rtx, sinfo->succs_other, is, succ) mark_unavailable_targets (av1, NULL, BB_LV_SET (BLOCK_FOR_INSN (succ))); @@ -3572,7 +3585,7 @@ vinsn_t vinsn; int n; - for (n = 0; VEC_iterate (vinsn_t, vinsn_vec, n, vinsn); n++) + FOR_EACH_VEC_ELT (vinsn_t, vinsn_vec, n, vinsn) if (VINSN_SEPARABLE_P (vinsn)) { if (vinsn_equal_p (vinsn, EXPR_VINSN (expr))) @@ -3646,7 +3659,7 @@ vinsn_t vinsn; int n; - for (n = 0; VEC_iterate (vinsn_t, *vinsn_vec, n, vinsn); n++) + FOR_EACH_VEC_ELT (vinsn_t, *vinsn_vec, n, vinsn) vinsn_detach (vinsn); VEC_block_remove (vinsn_t, *vinsn_vec, 0, len); } @@ -3719,8 +3732,7 @@ } /* Sort the vector. */ - qsort (VEC_address (expr_t, vec_av_set), VEC_length (expr_t, vec_av_set), - sizeof (expr_t), sel_rank_for_schedule); + VEC_qsort (expr_t, vec_av_set, sel_rank_for_schedule); /* We record maximal priority of insns in av set for current instruction group. */ @@ -3734,7 +3746,7 @@ { expr_t expr = VEC_index (expr_t, vec_av_set, n); insn_t insn = EXPR_INSN_RTX (expr); - char target_available; + signed char target_available; bool is_orig_reg_p = true; int need_cycles, new_prio; @@ -3934,15 +3946,14 @@ gcc_assert (min_need_stall == 0); /* Sort the vector. */ - qsort (VEC_address (expr_t, vec_av_set), VEC_length (expr_t, vec_av_set), - sizeof (expr_t), sel_rank_for_schedule); + VEC_qsort (expr_t, vec_av_set, sel_rank_for_schedule); if (sched_verbose >= 4) { sel_print ("Total ready exprs: %d, stalled: %d\n", VEC_length (expr_t, vec_av_set), stalled); sel_print ("Sorted av set (%d): ", VEC_length (expr_t, vec_av_set)); - for (n = 0; VEC_iterate (expr_t, vec_av_set, n, expr); n++) + FOR_EACH_VEC_ELT (expr_t, vec_av_set, n, expr) dump_expr (expr); sel_print ("\n"); } @@ -3971,7 +3982,7 @@ sched_extend_ready_list (ready.n_ready); } - for (n = 0; VEC_iterate (expr_t, vec_av_set, n, expr); n++) + FOR_EACH_VEC_ELT (expr_t, vec_av_set, n, expr) { vinsn_t vi = EXPR_VINSN (expr); insn_t insn = VINSN_INSN_RTX (vi); @@ -4320,8 +4331,9 @@ if (dfa_lookahead > 0) { cycle_issued_insns = FENCE_ISSUED_INSNS (fence); + /* TODO: pass equivalent of first_cycle_insn_p to max_issue (). */ can_issue = max_issue (&ready, privileged_n, - FENCE_STATE (fence), index); + FENCE_STATE (fence), true, index); if (sched_verbose >= 2) sel_print ("max_issue: we can issue %d insns, already did %d insns\n", can_issue, FENCE_ISSUED_INSNS (fence)); @@ -4402,7 +4414,8 @@ { can_issue_more = invoke_aftermath_hooks (fence, EXPR_INSN_RTX (best), can_issue_more); - if (can_issue_more == 0) + if (targetm.sched.variable_issue + && can_issue_more == 0) *pneed_stall = 1; } @@ -4632,11 +4645,8 @@ if (INSN_P (insn)) EXPR_ORIG_BB_INDEX (INSN_EXPR (insn)) = succ->index; - if (bitmap_bit_p (code_motion_visited_blocks, new_bb->index)) - { - bitmap_set_bit (code_motion_visited_blocks, succ->index); - bitmap_clear_bit (code_motion_visited_blocks, new_bb->index); - } + if (bitmap_clear_bit (code_motion_visited_blocks, new_bb->index)) + bitmap_set_bit (code_motion_visited_blocks, succ->index); gcc_assert (LABEL_P (BB_HEAD (new_bb)) && LABEL_P (BB_HEAD (succ))); @@ -4878,22 +4888,39 @@ move_cond_jump (rtx insn, bnd_t bnd) { edge ft_edge; - basic_block block_from, block_next, block_new; - rtx next, prev, link; - - /* BLOCK_FROM holds basic block of the jump. */ + basic_block block_from, block_next, block_new, block_bnd, bb; + rtx next, prev, link, head; + block_from = BLOCK_FOR_INSN (insn); - - /* Moving of jump should not cross any other jumps or - beginnings of new basic blocks. */ - gcc_assert (block_from == BLOCK_FOR_INSN (BND_TO (bnd))); + block_bnd = BLOCK_FOR_INSN (BND_TO (bnd)); + prev = BND_TO (bnd); + +#ifdef ENABLE_CHECKING + /* Moving of jump should not cross any other jumps or beginnings of new + basic blocks. The only exception is when we move a jump through + mutually exclusive insns along fallthru edges. */ + if (block_from != block_bnd) + { + bb = block_from; + for (link = PREV_INSN (insn); link != PREV_INSN (prev); + link = PREV_INSN (link)) + { + if (INSN_P (link)) + gcc_assert (sched_insns_conditions_mutex_p (insn, link)); + if (BLOCK_FOR_INSN (link) && BLOCK_FOR_INSN (link) != bb) + { + gcc_assert (single_pred (bb) == BLOCK_FOR_INSN (link)); + bb = BLOCK_FOR_INSN (link); + } + } + } +#endif /* Jump is moved to the boundary. */ - prev = BND_TO (bnd); next = PREV_INSN (insn); BND_TO (bnd) = insn; - ft_edge = find_fallthru_edge (block_from); + ft_edge = find_fallthru_edge_from (block_from); block_next = ft_edge->dest; /* There must be a fallthrough block (or where should go control flow in case of false jump predicate otherwise?). */ @@ -4904,28 +4931,35 @@ gcc_assert (block_new->next_bb == block_next && block_from->next_bb == block_new); - gcc_assert (BB_END (block_from) == insn); - - /* Move all instructions except INSN from BLOCK_FROM to - BLOCK_NEW. */ - for (link = prev; link != insn; link = NEXT_INSN (link)) - { - EXPR_ORIG_BB_INDEX (INSN_EXPR (link)) = block_new->index; - df_insn_change_bb (link, block_new); - } - - /* Set correct basic block and instructions properties. */ - BB_END (block_new) = PREV_INSN (insn); - - NEXT_INSN (PREV_INSN (prev)) = insn; - PREV_INSN (insn) = PREV_INSN (prev); + /* Move all instructions except INSN to BLOCK_NEW. */ + bb = block_bnd; + head = BB_HEAD (block_new); + while (bb != block_from->next_bb) + { + rtx from, to; + from = bb == block_bnd ? prev : sel_bb_head (bb); + to = bb == block_from ? next : sel_bb_end (bb); + + /* The jump being moved can be the first insn in the block. + In this case we don't have to move anything in this block. */ + if (NEXT_INSN (to) != from) + { + reorder_insns (from, to, head); + + for (link = to; link != head; link = PREV_INSN (link)) + EXPR_ORIG_BB_INDEX (INSN_EXPR (link)) = block_new->index; + head = to; + } + + /* Cleanup possibly empty blocks left. */ + block_next = bb->next_bb; + if (bb != block_from) + tidy_control_flow (bb, false); + bb = block_next; + } /* Assert there is no jump to BLOCK_NEW, only fallthrough edge. */ gcc_assert (NOTE_INSN_BASIC_BLOCK_P (BB_HEAD (block_new))); - PREV_INSN (prev) = BB_HEAD (block_new); - NEXT_INSN (next) = NEXT_INSN (BB_HEAD (block_new)); - NEXT_INSN (BB_HEAD (block_new)) = prev; - PREV_INSN (NEXT_INSN (next)) = next; gcc_assert (!sel_bb_empty_p (block_from) && !sel_bb_empty_p (block_new)); @@ -4954,7 +4988,7 @@ int i; insn_t insn; - for (i = 0; VEC_iterate (insn_t, vec_temp_moveop_nops, i, insn); i++) + FOR_EACH_VEC_ELT (insn_t, vec_temp_moveop_nops, i, insn) { gcc_assert (INSN_NOP_P (insn)); return_nop_to_pool (insn, full_tidying); @@ -5489,7 +5523,7 @@ blist_t *bnds_tailp1, *bndsp; expr_t expr_vliw; int need_stall; - int was_stall = 0, scheduled_insns = 0, stall_iterations = 0; + int was_stall = 0, scheduled_insns = 0; int max_insns = pipelining_p ? issue_rate : 2 * issue_rate; int max_stall = pipelining_p ? 1 : 3; bool last_insn_was_debug = false; @@ -5508,16 +5542,15 @@ do { expr_vliw = find_best_expr (&av_vliw, bnds, fence, &need_stall); - if (!expr_vliw && need_stall) + if (! expr_vliw && need_stall) { /* All expressions required a stall. Do not recompute av sets as we'll get the same answer (modulo the insns between the fence and its boundary, which will not be available for - pipelining). */ - gcc_assert (! expr_vliw && stall_iterations < 2); + pipelining). + If we are going to stall for too long, break to recompute av + sets and bring more insns for pipelining. */ was_stall++; - /* If we are going to stall for too long, break to recompute av - sets and bring more insns for pipelining. */ if (need_stall <= 3) stall_for_cycles (fence, need_stall); else @@ -5785,7 +5818,7 @@ we still need to count it as an originator. */ bitmap_set_bit (current_originators, INSN_UID (insn)); - if (!bitmap_bit_p (current_copies, INSN_UID (insn))) + if (!bitmap_clear_bit (current_copies, INSN_UID (insn))) { /* Note that original block needs to be rescheduled, as we pulled an instruction out of it. */ @@ -5794,8 +5827,6 @@ else if (INSN_UID (insn) < first_emitted_uid && !DEBUG_INSN_P (insn)) num_insns_scheduled++; } - else - bitmap_clear_bit (current_copies, INSN_UID (insn)); /* For instructions we must immediately remove insn from the stream, so subsequent update_data_sets () won't include this @@ -6350,10 +6381,10 @@ bookkeeping generated for another fence or for another path in current move_op. */ gcc_assert (res == 1 - || (res == 0 - && av_set_could_be_blocked_by_bookkeeping_p (orig_ops, + || (res == 0 + && av_set_could_be_blocked_by_bookkeeping_p (orig_ops, static_params)) - || res == -1); + || res == -1); #endif /* Merge data, clean up, etc. */ @@ -6692,6 +6723,8 @@ init_seqno_1 (succ, visited_bbs, blocks_to_reschedule); } + else if (blocks_to_reschedule) + bitmap_set_bit (forced_ebb_heads, succ->index); } for (insn = BB_END (bb); insn != note; insn = PREV_INSN (insn)) @@ -6862,11 +6895,11 @@ /* Set hooks so that no newly generated insn will go out unnoticed. */ sel_register_cfg_hooks (); - /* !!! We call target.sched.md_init () for the whole region, but we invoke - targetm.sched.md_finish () for every ebb. */ - if (targetm.sched.md_init) + /* !!! We call target.sched.init () for the whole region, but we invoke + targetm.sched.finish () for every ebb. */ + if (targetm.sched.init) /* None of the arguments are actually used in any target. */ - targetm.sched.md_init (sched_dump, sched_verbose, -1); + targetm.sched.init (sched_dump, sched_verbose, -1); first_emitted_uid = get_max_uid () + 1; preheader_removed = false; @@ -6946,13 +6979,14 @@ int last_clock = 0; int haifa_last_clock = -1; int haifa_clock = 0; + int issued_insns = 0; insn_t insn; - if (targetm.sched.md_init) + if (targetm.sched.init) { /* None of the arguments are actually used in any target. NB: We should have md_reset () hook for cases like this. */ - targetm.sched.md_init (sched_dump, sched_verbose, -1); + targetm.sched.init (sched_dump, sched_verbose, -1); } state_reset (curr_state); @@ -6964,7 +6998,7 @@ { int cost, haifa_cost; int sort_p; - bool asm_p, real_insn, after_stall; + bool asm_p, real_insn, after_stall, all_issued; int clock; if (!INSN_P (insn)) @@ -7000,7 +7034,9 @@ haifa_cost = cost; after_stall = 1; } - + all_issued = issued_insns == issue_rate; + if (haifa_cost == 0 && all_issued) + haifa_cost = 1; if (haifa_cost > 0) { int i = 0; @@ -7008,6 +7044,7 @@ while (haifa_cost--) { advance_state (curr_state); + issued_insns = 0; i++; if (sched_verbose >= 2) @@ -7024,9 +7061,22 @@ && haifa_cost > 0 && estimate_insn_cost (insn, curr_state) == 0) break; - } + + /* When the data dependency stall is longer than the DFA stall, + and when we have issued exactly issue_rate insns and stalled, + it could be that after this longer stall the insn will again + become unavailable to the DFA restrictions. Looks strange + but happens e.g. on x86-64. So recheck DFA on the last + iteration. */ + if ((after_stall || all_issued) + && real_insn + && haifa_cost == 0) + haifa_cost = estimate_insn_cost (insn, curr_state); + } haifa_clock += i; + if (sched_verbose >= 2) + sel_print ("haifa clock: %d\n", haifa_clock); } else gcc_assert (haifa_cost == 0); @@ -7040,21 +7090,27 @@ &sort_p)) { advance_state (curr_state); + issued_insns = 0; haifa_clock++; if (sched_verbose >= 2) { sel_print ("advance_state (dfa_new_cycle)\n"); debug_state (curr_state); + sel_print ("haifa clock: %d\n", haifa_clock + 1); } } if (real_insn) { cost = state_transition (curr_state, insn); + issued_insns++; if (sched_verbose >= 2) - debug_state (curr_state); - + { + sel_print ("scheduled insn %d, clock %d\n", INSN_UID (insn), + haifa_clock + 1); + debug_state (curr_state); + } gcc_assert (cost < 0); } @@ -7130,14 +7186,14 @@ if (reset_sched_cycles_p) reset_sched_cycles_in_current_ebb (); - if (targetm.sched.md_init) - targetm.sched.md_init (sched_dump, sched_verbose, -1); + if (targetm.sched.init) + targetm.sched.init (sched_dump, sched_verbose, -1); put_TImodes (); - if (targetm.sched.md_finish) + if (targetm.sched.finish) { - targetm.sched.md_finish (sched_dump, sched_verbose); + targetm.sched.finish (sched_dump, sched_verbose); /* Extend luids so that insns generated by the target will get zero luid. */ @@ -7467,21 +7523,23 @@ { basic_block bb = EBB_FIRST_BB (i); - if (sel_bb_empty_p (bb)) - { - bitmap_clear_bit (blocks_to_reschedule, bb->index); - continue; - } - if (bitmap_bit_p (blocks_to_reschedule, bb->index)) { + if (! bb_ends_ebb_p (bb)) + bitmap_set_bit (blocks_to_reschedule, bb_next_bb (bb)->index); + if (sel_bb_empty_p (bb)) + { + bitmap_clear_bit (blocks_to_reschedule, bb->index); + continue; + } clear_outdated_rtx_info (bb); if (sel_insn_is_speculation_check (BB_END (bb)) && JUMP_P (BB_END (bb))) bitmap_set_bit (blocks_to_reschedule, BRANCH_EDGE (bb)->dest->index); } - else if (INSN_SCHED_TIMES (sel_bb_head (bb)) <= 0) + else if (! sel_bb_empty_p (bb) + && INSN_SCHED_TIMES (sel_bb_head (bb)) <= 0) bitmap_set_bit (blocks_to_reschedule, bb->index); } @@ -7507,8 +7565,6 @@ /* Mark BB as head of the new ebb. */ bitmap_set_bit (forced_ebb_heads, bb->index); - bitmap_clear_bit (blocks_to_reschedule, bb->index); - gcc_assert (fences == NULL); init_fences (bb_note (bb));