diff options
author | mkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-02 09:11:11 +0000 |
---|---|---|
committer | mkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-02 09:11:11 +0000 |
commit | 9997bd271736dc80d321fb8146633ccda9ae184e (patch) | |
tree | e202a5e628bb892458b9fe788d9efe2eaaa8c5da /gcc/haifa-sched.c | |
parent | 2289a5f2f2a2ed725781661b40fc1ec00e23e856 (diff) | |
download | gcc-9997bd271736dc80d321fb8146633ccda9ae184e.tar.gz |
* sched-int.h (ds_to_dk, dk_to_ds): Declare functions.
(struct _dep): New type.
(dep_t): New typedef.
(DEP_PRO, DEP_CON, DEP_KIND): New access macros.
(DEP_STATUS): New access macro. The macro with the same name was
renamed to DEP_LINK_STATUS.
(dep_init): Declare function
(struct _dep_link): New type.
(dep_link_t): New typedef.
(DEP_LINK_NODE, DEP_LINK_NEXT, DEP_LINK_PREV_NEXTP): New access macros.
(DEP_LINK_DEP, DEP_LINK_PRO, DEP_LINK_CON, DEP_LINK_KIND): New macros.
(DEP_LINK_STATUS): New macro.
(debug_dep_links): New debug function.
(struct _deps_list): New type.
(deps_list_t): New typedef.
(DEPS_LIST_FIRST): New access macro.
(FOR_EACH_DEP_LINK): New cycle macro.
(create_deps_list, free_deps_list, delete_deps_list): Declare
functions.
(deps_list_empty_p, debug_deps_list, add_back_dep_to_deps_list): Ditto.
(find_link_by_pro_in_deps_list, find_link_by_con_in_deps_list): Ditto.
(copy_deps_list_change_con): Ditto.
(move_dep_link): Declare function.
(struct _dep_node): New type.
(dep_node_t): New typedef.
(DEP_NODE_BACK, DEP_NODE_DEP, DEP_NODE_FORW): New access macros.
(struct haifa_insn_data.back_deps): New field to hold backward
dependencies of the insn.
(struct haifa_insn_data.depend): Rename to forw_deps. Change its type
to deps_list_t.
(struct haifa_insn_data.resolved_deps): Rename to resolved_back_deps.
Change its type to deps_list_t.
(INSN_BACK_DEPS): New access macro to use instead of LOG_LINKS.
(INSN_DEPEND): Rename to INSN_FORW_DEPS.
(RESOLVED_DEPS): Rename to INSN_RESOLVED_BACK_DEPS.
(INSN_COST): Move to haifa-sched.c. Use insn_cost () instead.
(DEP_STATUS): Rename to DEP_LINK_STATUS. Fix typo in the comment.
(add_forw_dep, delete_back_forw_dep, insn_cost): Update declaration and
all callers.
(dep_cost): Declare.
* sched-deps.c (CHECK): New macro to (en/dis)able sanity checks.
(ds_to_dk, dk_to_ds): New functions.
(init_dep_1): New static function.
(init_dep): New function.
(copy_dep): New static function.
(dep_link_consistent_p, attach_dep_link, add_to_deps_list): New static
functions.
(detach_dep_link): New static function.
(move_dep_link): New function.
(dep_links_consistent_p, dump_dep_links): New static functions.
(debug_dep_links): New debugging function.
(deps_obstack, dl_obstack, dn_obstack): New static variables.
(alloc_deps_list, init_deps_list): New static functions.
(create_deps_list): New function.
(clear_deps_list): New static function.
(free_deps_list, delete_deps_list, deps_list_empty_p): New functions.
(deps_list_consistent_p, dump_deps_list): New static functions.
(debug_deps_list): New function.
(add_back_dep_to_deps_list, find_link_by_pro_in_deps_list): New
functions.
(find_link_by_con_in_deps_list, copy_deps_list_change_con): Ditto.
(maybe_add_or_update_back_dep_1, add_or_update_back_dep_1): Update to
use new scheduler dependencies lists.
(add_back_dep, delete_all_dependences, fixup_sched_groups): Ditto.
(sched_analyze): Ditto. Initialize dependencies lists.
(add_forw_dep, compute_forward_dependences): Update to use new
scheduler dependencies lists.
(init_dependency_caches): Init deps_obstack.
(free_dependency_caches): Free deps_obstack.
(adjust_add_sorted_back_dep, adjust_back_add_forw_dep): Update to use
new scheduler dependencies lists.
(delete_forw_dep, add_or_update_back_forw_dep): Ditto.
(add_back_forw_dep, delete_back_forw_dep): Ditto.
* sched-rgn.c (set_spec_fed, find_conditional_protection, is_pfree):
Update to use new scheduler dependencies lists.
(is_conditionally_protected, is_prisky, add_branch_dependences): Ditto.
(debug_dependencies): Ditto.
(schedule_region): Update comments.
* sched-ebb.c (earliest_block_with_similiar_load): Update to use new
scheduler dependencies lists.
(schedule_ebb): Update comments.
* rtl.def (DEPS_LIST): Remove.
* lists.c (unused_deps_list): Remove.
(free_list): Update assertions.
(alloc_DEPS_LIST, free_DEPS_LIST_list, free_DEPS_LIST_node): Remove.
(remove_free_DEPS_LIST_elem, copy_DEPS_LIST_list): Ditto.
* rtl.h (free_DEPS_LIST_list, alloc_DEPS_LIST): Remove declarations.
(remove_free_DEPS_LIST_elem, copy_DEPS_LIST_list): Ditto.
* haifa-sched.c (comments): Update.
(insn_cost1): Remove. Inline the code into insn_cost ().
(insn_cost): Update to use new scheduler dependencies lists. Move
processing of the dependency cost to dep_cost ().
(dep_cost): New function. Use it instead of insn_cost () when
evaluating cost of the dependency. Use compatible interface to
interact with the target.
(priority): Update to use new scheduler dependencies lists.
(rank_for_schedule): Ditto. Optimize heuristic that prefers the insn
with greater number of insns that depend on the insn.
(schedule_insn): Update to use new scheduler dependencies lists. Add
code to free backward dependencies lists. Inline and optimize code
from resolve_dep () - see PR28071.
(ok_for_early_queue_removal): Update to use new scheduler dependencies
lists. Update call to targetm.sched.is_costly_dependence hook.
(fix_inter_tick, try_ready, fix_tick_ready): Update to use new
scheduler dependencies lists.
(resolve_dep): Remove. Move the logic to schedule_insn ().
(init_h_i_d): Initialize dependencies lists.
(process_insn_depend_be_in_spec): Rename to
process_insn_forw_deps_be_in_spec. Update to use new scheduler
dependencies lists.
(add_to_speculative_block, create_check_block_twin, fix_recovery_deps):
Update to use new scheduler dependencies lists.
(clear_priorities, calc_priorities, add_jump_dependencies): Ditto.
* ddg.c (create_ddg_dependence, create_ddg_dep_no_link): Update to use
new scheduler dependencies lists.
(build_intra_loop_deps): Ditto.
* target.h (struct _dep): Declare to use in
gcc_target.sched.is_costly_dependence.
(struct gcc_target.sched.adjust_cost): Fix typo.
(struct gcc_target.sched.is_costly_dependence): Change signature to use
single dep_t parameter instead of an equivalent triad.
(struct gcc_target.sched.adjust_cost_2): Remove.
* target-def.h (TARGET_SCHED_ADJUST_COST_2): Remove.
* reg-notes.def (DEP_TRUE, DEP_OUTPUT, DEP_ANTI): Update comments.
* doc/tm.texi (TARGET_SCHED_IS_COSTLY_DEPENDENCE): Update
documentation.
(TARGET_SCHED_ADJUST_COST_2): Remove documentation.
* doc/rtl.texi (LOG_LINKS): Remove part about instruction scheduler.
(REG_DEP_TRUE): Document.
* config/ia64/ia64.c (ia64_adjust_cost_2): Rename to ia64_adjust_cost.
Change signature to correspond to the targetm.sched.adjust_cost hook.
Update use in TARGET_SCHED_ADJUST_COST_2.
(TARGET_SCHED_ADJUST_COST_2): Rename to TARGET_SCHED_ADJUST_COST.
(ia64_dependencies_evaluation_hook, ia64_dfa_new_cycle): Update to use
new scheduler dependencies lists.
(ia64_gen_check): Ditto.
* config/mips/mips.c (vr4130_swap_insns_p): Update to use new scheduler
dependencies lists.
* config/rs6000/rs6000.c (rs6000_is_costly_dependence): Change
signature to correspond to the targetm.sched.is_costly_dependence hook.
(is_costly_group): Update to use new scheduler dependencies lists.
* config/spu/spu.c (spu_sched_adjust_cost): Use insn_cost () function
instead of INSN_COST () macro.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121494 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/haifa-sched.c')
-rw-r--r-- | gcc/haifa-sched.c | 504 |
1 files changed, 290 insertions, 214 deletions
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 21b3d645042..87d7bd11910 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -82,9 +82,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA compute_block_backward_dependences (). Dependencies set up by memory references are treated in exactly the - same way as other dependencies, by using LOG_LINKS backward - dependences. LOG_LINKS are translated into INSN_DEPEND forward - dependences for the purpose of forward list scheduling. + same way as other dependencies, by using insn backward dependences + INSN_BACK_DEPS. INSN_BACK_DEPS are translated into forward dependences + INSN_FORW_DEPS the purpose of forward list scheduling. Having optimized the critical path, we may have also unduly extended the lifetimes of some registers. If an operation requires @@ -251,8 +251,8 @@ static basic_block before_recovery; sufficient time has passed to make them ready. As time passes, insns move from the "Queued" set to the "Ready" list. - The "Pending" list (P) are the insns in the INSN_DEPEND of the unscheduled - insns, i.e., those that are ready, queued, and pending. + The "Pending" list (P) are the insns in the INSN_FORW_DEPS of the + unscheduled insns, i.e., those that are ready, queued, and pending. The "Queued" set (Q) is implemented by the variable `insn_queue'. The "Ready" list (R) is implemented by the variables `ready' and `n_ready'. @@ -489,7 +489,6 @@ haifa_classify_insn (rtx insn) /* Forward declarations. */ -HAIFA_INLINE static int insn_cost1 (rtx, enum reg_note, rtx, rtx); static int priority (rtx); static int rank_for_schedule (const void *, const void *); static void swap_sort (rtx *, int); @@ -544,7 +543,6 @@ static rtx choose_ready (struct ready_list *); static void fix_inter_tick (rtx, rtx); static int fix_tick_ready (rtx); static void change_queue_index (rtx, int); -static void resolve_dep (rtx, rtx); /* The following functions are used to implement scheduling of data/control speculative instructions. */ @@ -555,7 +553,7 @@ static void extend_global (rtx); static void extend_all (rtx); static void init_h_i_d (rtx); static void generate_recovery_code (rtx); -static void process_insn_depend_be_in_spec (rtx, rtx, ds_t); +static void process_insn_forw_deps_be_in_spec (deps_list_t, rtx, ds_t); static void begin_speculative_block (rtx); static void add_to_speculative_block (rtx); static dw_t dep_weak (ds_t); @@ -607,27 +605,15 @@ static struct sched_info current_sched_info_var; static rtx last_scheduled_insn; -/* Compute cost of executing INSN given the dependence LINK on the insn USED. - This is the number of cycles between instruction issue and - instruction results. */ +/* Cached cost of the instruction. Use below function to get cost of the + insn. -1 here means that the field is not initialized. */ +#define INSN_COST(INSN) (h_i_d[INSN_UID (INSN)].cost) -HAIFA_INLINE int -insn_cost (rtx insn, rtx link, rtx used) -{ - return insn_cost1 (insn, used ? REG_NOTE_KIND (link) : REG_NOTE_MAX, - link, used); -} - -/* Compute cost of executing INSN given the dependence on the insn USED. - If LINK is not NULL, then its REG_NOTE_KIND is used as a dependence type. - Otherwise, dependence between INSN and USED is assumed to be of type - DEP_TYPE. This function was introduced as a workaround for - targetm.adjust_cost hook. +/* Compute cost of executing INSN. This is the number of cycles between instruction issue and instruction results. */ - -HAIFA_INLINE static int -insn_cost1 (rtx insn, enum reg_note dep_type, rtx link, rtx used) +HAIFA_INLINE int +insn_cost (rtx insn) { int cost = INSN_COST (insn); @@ -652,9 +638,17 @@ insn_cost1 (rtx insn, enum reg_note dep_type, rtx link, rtx used) } } - /* In this case estimate cost without caring how insn is used. */ - if (used == 0) - return cost; + return cost; +} + +/* Compute cost of dependence LINK. + This is the number of cycles between instruction issue and + instruction results. */ +int +dep_cost (dep_t link) +{ + rtx used = DEP_CON (link); + int cost; /* A USE insn should never require the value used to be computed. This allows the computation of a function's result and parameter @@ -663,7 +657,10 @@ insn_cost1 (rtx insn, enum reg_note dep_type, rtx link, rtx used) cost = 0; else { - gcc_assert (!link || dep_type == REG_NOTE_KIND (link)); + rtx insn = DEP_PRO (link); + enum reg_note dep_type = DEP_KIND (link); + + cost = insn_cost (insn); if (INSN_CODE (insn) >= 0) { @@ -680,13 +677,23 @@ insn_cost1 (rtx insn, enum reg_note dep_type, rtx link, rtx used) cost = insn_latency (insn, used); } - if (targetm.sched.adjust_cost_2) - cost = targetm.sched.adjust_cost_2 (used, (int) dep_type, insn, cost); - else + if (targetm.sched.adjust_cost != NULL) { - gcc_assert (link); - if (targetm.sched.adjust_cost) - cost = targetm.sched.adjust_cost (used, link, insn, cost); + /* This variable is used for backward compatibility with the + targets. */ + rtx dep_cost_rtx_link = alloc_INSN_LIST (NULL_RTX, NULL_RTX); + + /* Make it self-cycled, so that if some tries to walk over this + incomplete list he/she will be cought in an endless loop. */ + XEXP (dep_cost_rtx_link, 1) = dep_cost_rtx_link; + + /* Targets use only REG_NOTE_KIND of the link. */ + PUT_REG_NOTE_KIND (dep_cost_rtx_link, DEP_KIND (link)); + + cost = targetm.sched.adjust_cost (used, dep_cost_rtx_link, + insn, cost); + + free_INSN_LIST_node (dep_cost_rtx_link); } if (cost < 0) @@ -701,7 +708,7 @@ insn_cost1 (rtx insn, enum reg_note dep_type, rtx link, rtx used) static int priority (rtx insn) { - rtx link; + dep_link_t link; if (! INSN_P (insn)) return 0; @@ -710,8 +717,12 @@ priority (rtx insn) { int this_priority = 0; - if (INSN_DEPEND (insn) == 0) - this_priority = insn_cost (insn, 0, 0); + if (deps_list_empty_p (INSN_FORW_DEPS (insn))) + /* ??? We should set INSN_PRIORITY to insn_cost when and insn has + some forward deps but all of them are ignored by + contributes_to_priority hook. At the moment we set priority of + such insn to 0. */ + this_priority = insn_cost (insn); else { rtx prev_first, twin; @@ -719,8 +730,9 @@ priority (rtx insn) /* For recovery check instructions we calculate priority slightly different than that of normal instructions. Instead of walking - through INSN_DEPEND (check) list, we walk through INSN_DEPEND list - of each instruction in the corresponding recovery block. */ + through INSN_FORW_DEPS (check) list, we walk through + INSN_FORW_DEPS list of each instruction in the corresponding + recovery block. */ rec = RECOVERY_BLOCK (insn); if (!rec || rec == EXIT_BLOCK_PTR) @@ -736,15 +748,18 @@ priority (rtx insn) do { - for (link = INSN_DEPEND (twin); link; link = XEXP (link, 1)) + FOR_EACH_DEP_LINK (link, INSN_FORW_DEPS (twin)) { rtx next; int next_priority; - - next = XEXP (link, 0); - + dep_t dep = DEP_LINK_DEP (link); + + next = DEP_CON (dep); + if (BLOCK_FOR_INSN (next) != rec) { + int cost; + /* Critical path is meaningful in block boundaries only. */ if (! (*current_sched_info->contributes_to_priority) @@ -756,17 +771,23 @@ priority (rtx insn) producers will more likely be scheduled, thus, resolving the dependence. */ || ((current_sched_info->flags & DO_SPECULATION) - && (DEP_STATUS (link) & SPECULATIVE) + && (DEP_STATUS (dep) & SPECULATIVE) && !(spec_info->flags & COUNT_SPEC_IN_CRITICAL_PATH))) continue; - - next_priority = insn_cost1 (insn, - twin == insn ? - REG_NOTE_KIND (link) : - REG_DEP_ANTI, - twin == insn ? link : 0, - next) + priority (next); + + if (twin == insn) + cost = dep_cost (dep); + else + { + struct _dep _dep1, *dep1 = &_dep1; + + init_dep (dep1, insn, next, REG_DEP_ANTI); + + cost = dep_cost (dep1); + } + + next_priority = cost + priority (next); if (next_priority > this_priority) this_priority = next_priority; @@ -803,8 +824,8 @@ rank_for_schedule (const void *x, const void *y) { rtx tmp = *(const rtx *) y; rtx tmp2 = *(const rtx *) x; - rtx link; - int tmp_class, tmp2_class, depend_count1, depend_count2; + dep_link_t link1, link2; + int tmp_class, tmp2_class; int val, priority_val, weight_val, info_val; /* The insn in a schedule group should be issued the first. */ @@ -858,18 +879,26 @@ rank_for_schedule (const void *x, const void *y) 2) Anti/Output dependent on last scheduled insn. 3) Independent of last scheduled insn, or has latency of one. Choose the insn from the highest numbered class if different. */ - link = find_insn_list (tmp, INSN_DEPEND (last_scheduled_insn)); - if (link == 0 || insn_cost (last_scheduled_insn, link, tmp) == 1) + link1 + = find_link_by_con_in_deps_list (INSN_FORW_DEPS (last_scheduled_insn), + tmp); + + if (link1 == NULL || dep_cost (DEP_LINK_DEP (link1)) == 1) tmp_class = 3; - else if (REG_NOTE_KIND (link) == 0) /* Data dependence. */ + else if (/* Data dependence. */ + DEP_LINK_KIND (link1) == REG_DEP_TRUE) tmp_class = 1; else tmp_class = 2; - link = find_insn_list (tmp2, INSN_DEPEND (last_scheduled_insn)); - if (link == 0 || insn_cost (last_scheduled_insn, link, tmp2) == 1) + link2 + = find_link_by_con_in_deps_list (INSN_FORW_DEPS (last_scheduled_insn), + tmp2); + + if (link2 == NULL || dep_cost (DEP_LINK_DEP (link2)) == 1) tmp2_class = 3; - else if (REG_NOTE_KIND (link) == 0) /* Data dependence. */ + else if (/* Data dependence. */ + DEP_LINK_KIND (link2) == REG_DEP_TRUE) tmp2_class = 1; else tmp2_class = 2; @@ -881,17 +910,22 @@ rank_for_schedule (const void *x, const void *y) /* Prefer the insn which has more later insns that depend on it. This gives the scheduler more freedom when scheduling later instructions at the expense of added register pressure. */ - depend_count1 = 0; - for (link = INSN_DEPEND (tmp); link; link = XEXP (link, 1)) - depend_count1++; - depend_count2 = 0; - for (link = INSN_DEPEND (tmp2); link; link = XEXP (link, 1)) - depend_count2++; + link1 = DEPS_LIST_FIRST (INSN_FORW_DEPS (tmp)); + link2 = DEPS_LIST_FIRST (INSN_FORW_DEPS (tmp2)); - val = depend_count2 - depend_count1; - if (val) - return val; + while (link1 != NULL && link2 != NULL) + { + link1 = DEP_LINK_NEXT (link1); + link2 = DEP_LINK_NEXT (link2); + } + + if (link1 != NULL && link2 == NULL) + /* TMP (Y) has more insns that depend on it. */ + return -1; + if (link1 == NULL && link2 != NULL) + /* TMP2 (X) has more insns that depend on it. */ + return 1; /* If insns are equally good, sort by INSN_LUID (original insn order), so that we make the sort stable. This minimizes instruction movement, @@ -1127,7 +1161,7 @@ static int last_clock_var; static int schedule_insn (rtx insn) { - rtx link; + dep_link_t link; int advance = 0; if (sched_verbose >= 1) @@ -1147,18 +1181,16 @@ schedule_insn (rtx insn) /* Scheduling instruction should have all its dependencies resolved and should have been removed from the ready list. */ - gcc_assert (INSN_DEP_COUNT (insn) == 0); - gcc_assert (!LOG_LINKS (insn)); - gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE); + gcc_assert (INSN_DEP_COUNT (insn) == 0 + && deps_list_empty_p (INSN_BACK_DEPS (insn))); + free_deps_list (INSN_BACK_DEPS (insn)); + + /* Now we can free INSN_RESOLVED_BACK_DEPS list. */ + delete_deps_list (INSN_RESOLVED_BACK_DEPS (insn)); + gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE); QUEUE_INDEX (insn) = QUEUE_SCHEDULED; - - /* Now we can free RESOLVED_DEPS list. */ - if (current_sched_info->flags & USE_DEPS_LIST) - free_DEPS_LIST_list (&RESOLVED_DEPS (insn)); - else - free_INSN_LIST_list (&RESOLVED_DEPS (insn)); - + gcc_assert (INSN_TICK (insn) >= MIN_TICK); if (INSN_TICK (insn) > clock_var) /* INSN has been prematurely moved from the queue to the ready list. @@ -1170,11 +1202,19 @@ schedule_insn (rtx insn) INSN_TICK (insn) = clock_var; /* Update dependent instructions. */ - for (link = INSN_DEPEND (insn); link; link = XEXP (link, 1)) + FOR_EACH_DEP_LINK (link, INSN_FORW_DEPS (insn)) { - rtx next = XEXP (link, 0); + rtx next = DEP_LINK_CON (link); + + /* Resolve the dependence between INSN and NEXT. */ + + INSN_DEP_COUNT (next)--; - resolve_dep (next, insn); + move_dep_link (DEP_NODE_BACK (DEP_LINK_NODE (link)), + INSN_RESOLVED_BACK_DEPS (next)); + + gcc_assert ((INSN_DEP_COUNT (next) == 0) + == deps_list_empty_p (INSN_BACK_DEPS (next))); if (!IS_SPECULATION_BRANCHY_CHECK_P (insn)) { @@ -1191,7 +1231,7 @@ schedule_insn (rtx insn) /* Check always has only one forward dependence (to the first insn in the recovery block), therefore, this will be executed only once. */ { - gcc_assert (XEXP (link, 1) == 0); + gcc_assert (DEP_LINK_NEXT (link) == NULL); fix_recovery_deps (RECOVERY_BLOCK (insn)); } } @@ -1525,17 +1565,22 @@ ok_for_early_queue_removal (rtx insn) { for ( ; prev_insn; prev_insn = PREV_INSN (prev_insn)) { - rtx dep_link = 0; - int dep_cost; + int cost; if (!NOTE_P (prev_insn)) { - dep_link = find_insn_list (insn, INSN_DEPEND (prev_insn)); + dep_link_t dep_link; + + dep_link = (find_link_by_con_in_deps_list + (INSN_FORW_DEPS (prev_insn), insn)); + if (dep_link) { - dep_cost = insn_cost (prev_insn, dep_link, insn) ; - if (targetm.sched.is_costly_dependence (prev_insn, insn, - dep_link, dep_cost, + dep_t dep = DEP_LINK_DEP (dep_link); + + cost = dep_cost (dep); + + if (targetm.sched.is_costly_dependence (dep, cost, flag_sched_stalled_insns_dep - n_cycles)) return false; } @@ -2705,7 +2750,7 @@ fix_inter_tick (rtx head, rtx tail) if (INSN_P (head)) { int tick; - rtx link; + dep_link_t link; tick = INSN_TICK (head); gcc_assert (tick >= MIN_TICK); @@ -2722,11 +2767,11 @@ fix_inter_tick (rtx head, rtx tail) INSN_TICK (head) = tick; } - for (link = INSN_DEPEND (head); link; link = XEXP (link, 1)) + FOR_EACH_DEP_LINK (link, INSN_FORW_DEPS (head)) { rtx next; - next = XEXP (link, 0); + next = DEP_LINK_CON (link); tick = INSN_TICK (next); if (tick != INVALID_TICK @@ -2764,7 +2809,7 @@ int try_ready (rtx next) { ds_t old_ts, *ts; - rtx link; + dep_link_t link; ts = &TODO_SPEC (next); old_ts = *ts; @@ -2775,27 +2820,34 @@ try_ready (rtx next) if (!(current_sched_info->flags & DO_SPECULATION)) { - if (!LOG_LINKS (next)) + if (deps_list_empty_p (INSN_BACK_DEPS (next))) *ts &= ~HARD_DEP; } else { - *ts &= ~SPECULATIVE & ~HARD_DEP; - - link = LOG_LINKS (next); - if (link) + *ts &= ~SPECULATIVE & ~HARD_DEP; + + link = DEPS_LIST_FIRST (INSN_BACK_DEPS (next)); + + if (link != NULL) { - /* LOG_LINKS are maintained sorted. + ds_t ds = DEP_LINK_STATUS (link) & SPECULATIVE; + + /* Backward dependencies of the insn are maintained sorted. So if DEP_STATUS of the first dep is SPECULATIVE, than all other deps are speculative too. */ - if (DEP_STATUS (link) & SPECULATIVE) + if (ds != 0) { /* Now we've got NEXT with speculative deps only. 1. Look at the deps to see what we have to do. 2. Check if we can do 'todo'. */ - *ts = DEP_STATUS (link) & SPECULATIVE; - while ((link = XEXP (link, 1))) - *ts = ds_merge (*ts, DEP_STATUS (link) & SPECULATIVE); + *ts = ds; + + while ((link = DEP_LINK_NEXT (link)) != NULL) + { + ds = DEP_LINK_STATUS (link) & SPECULATIVE; + *ts = ds_merge (*ts, ds); + } if (dep_weak (*ts) < spec_info->weakness_cutoff) /* Too few points. */ @@ -2805,25 +2857,25 @@ try_ready (rtx next) *ts |= HARD_DEP; } } - + if (*ts & HARD_DEP) gcc_assert (*ts == old_ts && QUEUE_INDEX (next) == QUEUE_NOWHERE); else if (current_sched_info->new_ready) - *ts = current_sched_info->new_ready (next, *ts); + *ts = current_sched_info->new_ready (next, *ts); - /* * if !(old_ts & SPECULATIVE) (e.g. HARD_DEP or 0), then insn might + /* * if !(old_ts & SPECULATIVE) (e.g. HARD_DEP or 0), then insn might have its original pattern or changed (speculative) one. This is due to changing ebb in region scheduling. * But if (old_ts & SPECULATIVE), then we are pretty sure that insn has speculative pattern. - + We can't assert (!(*ts & HARD_DEP) || *ts == old_ts) here because control-speculative NEXT could have been discarded by sched-rgn.c (the same case as when discarded by can_schedule_ready_p ()). */ - + if ((*ts & SPECULATIVE) - /* If (old_ts == *ts), then (old_ts & SPECULATIVE) and we don't + /* If (old_ts == *ts), then (old_ts & SPECULATIVE) and we don't need to change anything. */ && *ts != old_ts) { @@ -2920,33 +2972,34 @@ try_ready (rtx next) static int fix_tick_ready (rtx next) { - rtx link; int tick, delay; - link = RESOLVED_DEPS (next); - - if (link) + if (!deps_list_empty_p (INSN_RESOLVED_BACK_DEPS (next))) { int full_p; + dep_link_t link; tick = INSN_TICK (next); /* if tick is not equal to INVALID_TICK, then update INSN_TICK of NEXT with the most recent resolved dependence cost. Otherwise, recalculate from scratch. */ - full_p = tick == INVALID_TICK; - do - { - rtx pro; + full_p = (tick == INVALID_TICK); + + FOR_EACH_DEP_LINK (link, INSN_RESOLVED_BACK_DEPS (next)) + { + dep_t dep = DEP_LINK_DEP (link); + rtx pro = DEP_PRO (dep); int tick1; - pro = XEXP (link, 0); gcc_assert (INSN_TICK (pro) >= MIN_TICK); - tick1 = INSN_TICK (pro) + insn_cost (pro, link, next); + tick1 = INSN_TICK (pro) + dep_cost (dep); if (tick1 > tick) tick = tick1; + + if (!full_p) + break; } - while ((link = XEXP (link, 1)) && full_p); } else tick = -1; @@ -3005,22 +3058,6 @@ change_queue_index (rtx next, int delay) } } -/* INSN is being scheduled. Resolve the dependence between INSN and NEXT. */ -static void -resolve_dep (rtx next, rtx insn) -{ - rtx dep; - - INSN_DEP_COUNT (next)--; - - dep = remove_list_elem (insn, &LOG_LINKS (next)); - XEXP (dep, 1) = RESOLVED_DEPS (next); - RESOLVED_DEPS (next) = dep; - - gcc_assert ((INSN_DEP_COUNT (next) != 0 || !LOG_LINKS (next)) - && (LOG_LINKS (next) || INSN_DEP_COUNT (next) == 0)); -} - /* Extend H_I_D data. */ static void extend_h_i_d (void) @@ -3095,7 +3132,15 @@ init_h_i_d (rtx insn) QUEUE_INDEX (insn) = QUEUE_NOWHERE; INSN_TICK (insn) = INVALID_TICK; INTER_TICK (insn) = INVALID_TICK; - find_insn_reg_weight1 (insn); + find_insn_reg_weight1 (insn); + + /* These two lists will be freed in schedule_insn (). */ + INSN_BACK_DEPS (insn) = create_deps_list (false); + INSN_RESOLVED_BACK_DEPS (insn) = create_deps_list (false); + + /* This one should be allocated on the obstack because it should live till + the scheduling ends. */ + INSN_FORW_DEPS (insn) = create_deps_list (true); } /* Generates recovery code for INSN. */ @@ -3114,18 +3159,20 @@ generate_recovery_code (rtx insn) /* Helper function. Tries to add speculative dependencies of type FS between instructions - in LINK list and TWIN. */ + in deps_list L and TWIN. */ static void -process_insn_depend_be_in_spec (rtx link, rtx twin, ds_t fs) +process_insn_forw_deps_be_in_spec (deps_list_t l, rtx twin, ds_t fs) { - for (; link; link = XEXP (link, 1)) + dep_link_t link; + + FOR_EACH_DEP_LINK (link, l) { ds_t ds; rtx consumer; - consumer = XEXP (link, 0); + consumer = DEP_LINK_CON (link); - ds = DEP_STATUS (link); + ds = DEP_LINK_STATUS (link); if (/* If we want to create speculative dep. */ fs @@ -3152,7 +3199,7 @@ process_insn_depend_be_in_spec (rtx link, rtx twin, ds_t fs) ds |= fs; } - add_back_forw_dep (consumer, twin, REG_NOTE_KIND (link), ds); + add_back_forw_dep (consumer, twin, DEP_LINK_KIND (link), ds); } } @@ -3175,7 +3222,8 @@ static void add_to_speculative_block (rtx insn) { ds_t ts; - rtx link, twins = NULL; + dep_link_t link; + rtx twins = NULL; ts = TODO_SPEC (insn); gcc_assert (!(ts & ~BE_IN_SPEC)); @@ -3191,34 +3239,37 @@ add_to_speculative_block (rtx insn) DONE_SPEC (insn) |= ts; /* First we convert all simple checks to branchy. */ - for (link = LOG_LINKS (insn); link;) + for (link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); link != NULL;) { - rtx check; - - check = XEXP (link, 0); + rtx check = DEP_LINK_PRO (link); if (IS_SPECULATION_SIMPLE_CHECK_P (check)) { create_check_block_twin (check, true); - link = LOG_LINKS (insn); + + /* Restart search. */ + link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); } else - link = XEXP (link, 1); + /* Continue search. */ + link = DEP_LINK_NEXT (link); } clear_priorities (insn); do { - rtx link, check, twin; + dep_link_t link; + rtx check, twin; basic_block rec; - link = LOG_LINKS (insn); - gcc_assert (!(DEP_STATUS (link) & BEGIN_SPEC) - && (DEP_STATUS (link) & BE_IN_SPEC) - && (DEP_STATUS (link) & DEP_TYPES) == DEP_TRUE); + link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); - check = XEXP (link, 0); + gcc_assert ((DEP_LINK_STATUS (link) & BEGIN_SPEC) == 0 + && (DEP_LINK_STATUS (link) & BE_IN_SPEC) != 0 + && (DEP_LINK_STATUS (link) & DEP_TYPES) == DEP_TRUE); + + check = DEP_LINK_PRO (link); gcc_assert (!IS_SPECULATION_CHECK_P (check) && !ORIG_PAT (check) && QUEUE_INDEX (check) == QUEUE_NOWHERE); @@ -3228,7 +3279,9 @@ add_to_speculative_block (rtx insn) twin = emit_insn_before (copy_rtx (PATTERN (insn)), BB_END (rec)); extend_global (twin); - RESOLVED_DEPS (twin) = copy_DEPS_LIST_list (RESOLVED_DEPS (insn)); + copy_deps_list_change_con (INSN_RESOLVED_BACK_DEPS (twin), + INSN_RESOLVED_BACK_DEPS (insn), + twin); if (sched_verbose && spec_info->dump) /* INSN_BB (insn) isn't determined for twin insns yet. @@ -3246,10 +3299,11 @@ add_to_speculative_block (rtx insn) do { - link = XEXP (link, 1); - if (link) + link = DEP_LINK_NEXT (link); + + if (link != NULL) { - check = XEXP (link, 0); + check = DEP_LINK_PRO (link); if (BLOCK_FOR_INSN (check) == rec) break; } @@ -3258,27 +3312,31 @@ add_to_speculative_block (rtx insn) } while (1); } - while (link); + while (link != NULL); - process_insn_depend_be_in_spec (INSN_DEPEND (insn), twin, ts); + process_insn_forw_deps_be_in_spec (INSN_FORW_DEPS (insn), twin, ts); - for (link = LOG_LINKS (insn); link;) + /* Remove all dependencies between INSN and insns in REC. */ + for (link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); link != NULL;) { - check = XEXP (link, 0); + check = DEP_LINK_PRO (link); if (BLOCK_FOR_INSN (check) == rec) { - delete_back_forw_dep (insn, check); - link = LOG_LINKS (insn); + delete_back_forw_dep (link); + + /* Restart search. */ + link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); } else - link = XEXP (link, 1); + /* Continue search. */ + link = DEP_LINK_NEXT (link); } } - while (LOG_LINKS (insn)); + while (!deps_list_empty_p (INSN_BACK_DEPS (insn))); - /* We can't add the dependence between insn and twin earlier because - that would make twin appear in the INSN_DEPEND (insn). */ + /* We couldn't have added the dependencies between INSN and TWINS earlier + because that would make TWINS appear in the INSN_BACK_DEPS (INSN). */ while (twins) { rtx twin; @@ -3471,7 +3529,8 @@ static void create_check_block_twin (rtx insn, bool mutate_p) { basic_block rec; - rtx label, check, twin, link; + rtx label, check, twin; + dep_link_t link; ds_t fs; gcc_assert (ORIG_PAT (insn) @@ -3521,14 +3580,14 @@ create_check_block_twin (rtx insn, bool mutate_p) in the recovery block). */ if (rec != EXIT_BLOCK_PTR) { - rtx link; - - for (link = RESOLVED_DEPS (insn); link; link = XEXP (link, 1)) - if (DEP_STATUS (link) & DEP_OUTPUT) + FOR_EACH_DEP_LINK (link, INSN_RESOLVED_BACK_DEPS (insn)) + if ((DEP_LINK_STATUS (link) & DEP_OUTPUT) != 0) { - RESOLVED_DEPS (check) = - alloc_DEPS_LIST (XEXP (link, 0), RESOLVED_DEPS (check), DEP_TRUE); - PUT_REG_NOTE_KIND (RESOLVED_DEPS (check), REG_DEP_TRUE); + struct _dep _dep, *dep = &_dep; + + init_dep (dep, DEP_LINK_PRO (link), check, REG_DEP_TRUE); + + add_back_dep_to_deps_list (INSN_RESOLVED_BACK_DEPS (check), dep); } twin = emit_insn_after (ORIG_PAT (insn), BB_END (rec)); @@ -3549,7 +3608,9 @@ create_check_block_twin (rtx insn, bool mutate_p) (TRUE | OUTPUT). */ } - RESOLVED_DEPS (twin) = copy_DEPS_LIST_list (RESOLVED_DEPS (insn)); + copy_deps_list_change_con (INSN_RESOLVED_BACK_DEPS (twin), + INSN_RESOLVED_BACK_DEPS (insn), + twin); if (rec != EXIT_BLOCK_PTR) /* In case of branchy check, fix CFG. */ @@ -3612,8 +3673,10 @@ create_check_block_twin (rtx insn, bool mutate_p) /* Move backward dependences from INSN to CHECK and move forward dependences from INSN to TWIN. */ - for (link = LOG_LINKS (insn); link; link = XEXP (link, 1)) + FOR_EACH_DEP_LINK (link, INSN_BACK_DEPS (insn)) { + rtx pro = DEP_LINK_PRO (link); + enum reg_note dk = DEP_LINK_KIND (link); ds_t ds; /* If BEGIN_DATA: [insn ~~TRUE~~> producer]: @@ -3631,7 +3694,7 @@ create_check_block_twin (rtx insn, bool mutate_p) twin ~~TRUE~~> producer twin --ANTI--> check */ - ds = DEP_STATUS (link); + ds = DEP_LINK_STATUS (link); if (ds & BEGIN_SPEC) { @@ -3641,24 +3704,27 @@ create_check_block_twin (rtx insn, bool mutate_p) if (rec != EXIT_BLOCK_PTR) { - add_back_forw_dep (check, XEXP (link, 0), REG_NOTE_KIND (link), ds); - add_back_forw_dep (twin, XEXP (link, 0), REG_NOTE_KIND (link), ds); + add_back_forw_dep (check, pro, dk, ds); + add_back_forw_dep (twin, pro, dk, ds); } else - add_back_forw_dep (check, XEXP (link, 0), REG_NOTE_KIND (link), ds); + add_back_forw_dep (check, pro, dk, ds); } - for (link = LOG_LINKS (insn); link;) - if ((DEP_STATUS (link) & BEGIN_SPEC) + for (link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); link != NULL;) + if ((DEP_LINK_STATUS (link) & BEGIN_SPEC) || mutate_p) /* We can delete this dep only if we totally overcome it with BEGIN_SPECULATION. */ { - delete_back_forw_dep (insn, XEXP (link, 0)); - link = LOG_LINKS (insn); + delete_back_forw_dep (link); + + /* Restart search. */ + link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); } else - link = XEXP (link, 1); + /* Continue search. */ + link = DEP_LINK_NEXT (link); fs = 0; @@ -3683,7 +3749,7 @@ create_check_block_twin (rtx insn, bool mutate_p) CHECK_SPEC (check) = CHECK_SPEC (insn); /* Future speculations: call the helper. */ - process_insn_depend_be_in_spec (INSN_DEPEND (insn), twin, fs); + process_insn_forw_deps_be_in_spec (INSN_FORW_DEPS (insn), twin, fs); if (rec != EXIT_BLOCK_PTR) { @@ -3698,12 +3764,19 @@ create_check_block_twin (rtx insn, bool mutate_p) } else { + dep_link_t link; + if (spec_info->dump) fprintf (spec_info->dump, ";;\t\tRemoved simple check : %s\n", (*current_sched_info->print_insn) (insn, 0)); - for (link = INSN_DEPEND (insn); link; link = INSN_DEPEND (insn)) - delete_back_forw_dep (XEXP (link, 0), insn); + /* Remove all forward dependencies of the INSN. */ + link = DEPS_LIST_FIRST (INSN_FORW_DEPS (insn)); + while (link != NULL) + { + delete_back_forw_dep (link); + link = DEPS_LIST_FIRST (INSN_FORW_DEPS (insn)); + } if (QUEUE_INDEX (insn) != QUEUE_NOWHERE) try_ready (check); @@ -3731,8 +3804,10 @@ create_check_block_twin (rtx insn, bool mutate_p) static void fix_recovery_deps (basic_block rec) { - rtx note, insn, link, jump, ready_list = 0; + dep_link_t link; + rtx note, insn, jump, ready_list = 0; bitmap_head in_ready; + rtx link1; bitmap_initialize (&in_ready, 0); @@ -3745,29 +3820,31 @@ fix_recovery_deps (basic_block rec) do { - for (link = INSN_DEPEND (insn); link;) + for (link = DEPS_LIST_FIRST (INSN_FORW_DEPS (insn)); link != NULL;) { rtx consumer; - consumer = XEXP (link, 0); + consumer = DEP_LINK_CON (link); if (BLOCK_FOR_INSN (consumer) != rec) { - delete_back_forw_dep (consumer, insn); + delete_back_forw_dep (link); if (!bitmap_bit_p (&in_ready, INSN_LUID (consumer))) { ready_list = alloc_INSN_LIST (consumer, ready_list); bitmap_set_bit (&in_ready, INSN_LUID (consumer)); } - - link = INSN_DEPEND (insn); + + /* Restart search. */ + link = DEPS_LIST_FIRST (INSN_FORW_DEPS (insn)); } else { - gcc_assert ((DEP_STATUS (link) & DEP_TYPES) == DEP_TRUE); + gcc_assert ((DEP_LINK_STATUS (link) & DEP_TYPES) == DEP_TRUE); - link = XEXP (link, 1); + /* Continue search. */ + link = DEP_LINK_NEXT (link); } } @@ -3778,8 +3855,8 @@ fix_recovery_deps (basic_block rec) bitmap_clear (&in_ready); /* Try to add instructions to the ready or queue list. */ - for (link = ready_list; link; link = XEXP (link, 1)) - try_ready (XEXP (link, 0)); + for (link1 = ready_list; link1; link1 = XEXP (link1, 1)) + try_ready (XEXP (link1, 0)); free_INSN_LIST_list (&ready_list); /* Fixing jump's dependences. */ @@ -4209,13 +4286,12 @@ sched_remove_insn (rtx insn) static void clear_priorities (rtx insn) { - rtx link; + dep_link_t link; - for (link = LOG_LINKS (insn); link; link = XEXP (link, 1)) + FOR_EACH_DEP_LINK (link, INSN_BACK_DEPS (insn)) { - rtx pro; + rtx pro = DEP_LINK_PRO (link); - pro = XEXP (link, 0); if (INSN_PRIORITY_KNOWN (pro)) { INSN_PRIORITY_KNOWN (pro) = 0; @@ -4229,13 +4305,12 @@ clear_priorities (rtx insn) static void calc_priorities (rtx insn) { - rtx link; + dep_link_t link; - for (link = LOG_LINKS (insn); link; link = XEXP (link, 1)) + FOR_EACH_DEP_LINK (link, INSN_BACK_DEPS (insn)) { - rtx pro; + rtx pro = DEP_LINK_PRO (link); - pro = XEXP (link, 0); if (!INSN_PRIORITY_KNOWN (pro)) { priority (pro); @@ -4256,11 +4331,12 @@ add_jump_dependencies (rtx insn, rtx jump) if (insn == jump) break; - if (!INSN_DEPEND (insn)) + if (deps_list_empty_p (INSN_FORW_DEPS (insn))) add_back_forw_dep (jump, insn, REG_DEP_ANTI, DEP_ANTI); } while (1); - gcc_assert (LOG_LINKS (jump)); + + gcc_assert (!deps_list_empty_p (INSN_BACK_DEPS (jump))); } /* Return the NOTE_INSN_BASIC_BLOCK of BB. */ |