mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-20 19:01:12 +08:00
sel-sched.h, [...]: New files.
2008-08-31 Andrey Belevantsev <abel@ispras.ru> Dmitry Melnik <dm@ispras.ru> Dmitry Zhurikhin <zhur@ispras.ru> Alexander Monakov <amonakov@ispras.ru> Maxim Kuvyrkov <maxim@codesourcery.com> * sel-sched.h, sel-sched-dump.h, sel-sched-ir.h, sel-sched.c, sel-sched-dump.c, sel-sched-ir.c: New files. * Makefile.in (OBJS-common): Add selective scheduling object files. (sel-sched.o, sel-sched-dump.o, sel-sched-ir.o): New entries. (SEL_SCHED_IR_H, SEL_SCHED_DUMP_H): New entries. (sched-vis.o): Add dependency on $(INSN_ATTR_H). * cfghooks.h (get_cfg_hooks, set_cfg_hooks): New prototypes. * cfghooks.c (get_cfg_hooks, set_cfg_hooks): New functions. (make_forwarder_block): Update loop latch if we have redirected the loop latch edge. * cfgloop.c (get_loop_body_in_custom_order): New function. * cfgloop.h (LOOPS_HAVE_FALLTHRU_PREHEADERS): New enum field. (CP_FALLTHRU_PREHEADERS): Likewise. (get_loop_body_in_custom_order): Declare. * cfgloopmanip.c (has_preds_from_loop): New. (create_preheader): Honor CP_FALLTHRU_PREHEADERS. Assert that the preheader edge will be fall thru when it is set. * common.opt (fsel-sched-bookkeeping, fsel-sched-pipelining, fsel-sched-pipelining-outer-loops, fsel-sched-renaming, fsel-sched-substitution, fselective-scheduling): New flags. * cse.c (hash_rtx_cb): New. (hash_rtx): Use it. * dbgcnt.def (sel_sched_cnt, sel_sched_region_cnt, sel_sched_insn_cnt): New counters. * final.c (compute_alignments): Export. Free dominance info after loop_optimizer_finalize. * genattr.c (main): Output maximal_insn_latency prototype. * genautomata.c (output_default_latencies): New. Factor its code from ... (output_internal_insn_latency_func): ... here. (output_internal_maximal_insn_latency_func): New. (output_maximal_insn_latency_func): New. * hard-reg-set.h (UHOST_BITS_PER_WIDE_INT): Define unconditionally. (struct hard_reg_set_iterator): New. (hard_reg_set_iter_init, hard_reg_set_iter_set, hard_reg_set_iter_next): New functions. (EXECUTE_IF_SET_IN_HARD_REG_SET): New macro. * lists.c (remove_free_INSN_LIST_node, remove_free_EXPR_LIST_node): New functions. * loop-init.c (loop_optimizer_init): When LOOPS_HAVE_FALLTHRU_PREHEADERS, set CP_FALLTHRU_PREHEADERS when calling create_preheaders. (loop_optimizer_finalize): Do not verify flow info after reload. * recog.c (validate_replace_rtx_1): New parameter simplify. Default it to true. Update all uses. Factor out simplifying code to ... (simplify_while_replacing): ... this new function. (validate_replace_rtx_part, validate_replace_rtx_part_nosimplify): New. * recog.h (validate_replace_rtx_part, validate_replace_rtx_part_nosimplify): Declare. * rtl.c (rtx_equal_p_cb): New. (rtx_equal_p): Use it. * rtl.h (rtx_equal_p_cb, hash_rtx_cb): Declare. (remove_free_INSN_LIST_NODE, remove_free_EXPR_LIST_node, debug_bb_n_slim, debug_bb_slim, print_rtl_slim): Likewise. * vecprim.h: Add a vector type for unsigned int. * haifa-sched.c: Include vecprim.h and cfgloop.h. (issue_rate, sched_verbose_param, note_list, dfa_state_size, ready_try, cycle_issued_insns, spec_info): Make global. (readyp): Initialize. (dfa_lookahead): New global variable. (old_max_uid, old_last_basic_block): Remove. (h_i_d): Make it a vector. (INSN_TICK, INTER_TICK, QUEUE_INDEX, INSN_COST): Make them work through HID macro. (after_recovery, adding_bb_to_current_region_p): New variables to handle correct insertion of the recovery code. (struct ready_list): Move declaration to sched-int.h. (rgn_n_insns): Removed. (rtx_vec_t): Move to sched-int.h. (find_insn_reg_weight): Remove. (find_insn_reg_weight1): Rename to find_insn_reg_weight. (haifa_init_h_i_d, haifa_finish_h_i_d): New functions to initialize / finalize haifa instruction data. (extend_h_i_d, init_h_i_d): Rewrite. (unlink_other_notes): Move logic to add_to_note_list. Handle selective scheduler. (ready_lastpos, ready_element, ready_sort, reemit_notes, find_fallthru_edge): Make global, remove static prototypes. (max_issue): Make global. Add privileged_n and state parameters. Use them. (extend_global, extend_all): Removed. (init_before_recovery): Add new param. Fix the handling of the case when we insert a recovery code before the EXIT which has a predecessor with a fallthrough edge to it. (create_recovery_block): Make global. Rename to sched_create_recovery_block. Update. (change_pattern): Rename to sched_change_pattern. Make global. (speculate_insn): Rename to sched_speculate_insn. Make global. Split haifa-specific functionality into ... (haifa_change_pattern): New static function. (sched_extend_bb): New static function. (sched_init_bbs): New function. (current_sched_info): Change type to struct haifa_sched_info. (insn_cost): Adjust for selective scheduling. (dep_cost_1): New function. Move logic from ... (dep_cost): ... here. (dep_cost): Use dep_cost_1. (contributes_to_priority_p): Use sched_deps_info instead of current_sched_info. (priority): Adjust to work with selective scheduling. Process the corner case when all dependencies don't contribute to priority. (rank_for_schedule): Use ds_weak instead of dep_weak. (advance_state): New function. Move logic from ... (advance_one_cycle): ... here. (add_to_note_list, concat_note_lists): New functions. (rm_other_notes): Make static. Adjust for selective scheduling. (remove_notes, restore_other_notes): New functions. (move_insn): Add two arguments. Update assert. Don't call reemit_notes. (choose_ready): Remove lookahead variable, use dfa_lookahead. Remove more_issue, max_points. Move the code to initialize max_lookahead_tries to max_issue. (schedule_block): Remove rgn_n_insns1 parameter. Don't allocate ready. Adjust use of move_insn. Call restore_other_notes. (luid): Remove. (sched_init, sched_finish): Move Haifa-specific initialization/ finalization to ... (haifa_sched_init, haifa_sched_finish): ... respectively. New functions. (setup_sched_dump): New function. (haifa_init_only_bb): New static function. (haifa_speculate_insn): New static function. (try_ready): Use haifa_* instead of speculate_insn and change_pattern. (extend_ready, extend_all): Remove. (sched_extend_ready_list, sched_finish_ready_list): New functions. (create_check_block_twin, add_to_speculative_block): Use haifa_insns_init instead of extend_global. Update to use new initialization functions. Change parameter. Factor out code from create_check_block_twin to ... (sched_create_recovery_edges) ... this new function. (add_block): Remove. (sched_scan_info): New. (extend_bb): Use sched_scan_info. (init_bb, extend_insn, init_insn, init_insns_in_bb, sched_scan): New static functions for walking through scheduling region. (sched_luids): New vector variable to replace uid_to_luid. (luids_extend_insn): New function. (sched_max_luid): New variable. (luids_init_insn): New function. (sched_init_luids, sched_finish_luids): New functions. (insn_luid): New debug function. (sched_extend_target): New function. (haifa_init_insn): New static function. (sched_init_only_bb): New hook. (sched_split_block): New hook. (sched_split_block_1): New function. (sched_create_empty_bb): New hook. (sched_create_empty_bb_1): New function. (common_sched_info, ready): New global variables. (current_sched_info_var): Remove. (move_block_after_check): Use common_sched_info. (haifa_luid_for_non_insn): New static function. (init_before_recovery): Use haifa_init_only_bb instead of add_block. (increase_insn_priority): New. * modulo-sched.c: (issue_rate): Remove static declaration. (sms_sched_info): Change type to haifa_sched_info. (sms_sched_deps_info, sms_common_sched_info): New variables. (setup_sched_infos): New. (sms_schedule): Initialize them. Call haifa_sched_init/finish. Do not call regstat_free_calls_crossed. (sms_print_insn): Use const_rtx. * params.def (PARAM_MAX_PIPELINE_REGION_BLOCKS, PARAM_MAX_PIPELINE_REGION_INSNS, PARAM_SELSCHED_MAX_LOOKAHEAD, PARAM_SELSCHED_MAX_SCHED_TIMES, PARAM_SELSCHED_INSNS_TO_RENAME, PARAM_SCHED_MEM_TRUE_DEP_COST): New. * sched-deps.c (sched_deps_info): New. Update all relevant uses of current_sched_info to use it. (enum reg_pending_barrier_mode): Move to sched-int.h. (h_d_i_d): New variable. Initialize to NULL. ({true, output, anti, spec, forward}_dependency_cache): Initialize to NULL. (estimate_dep_weak): Remove static declaration. (sched_has_condition_p): New function. Adjust users of sched_get_condition to use it instead. (conditions_mutex_p): Add arguments indicating which conditions are reversed. Use them. (sched_get_condition_with_rev): Rename from sched_get_condition. Add argument to indicate whether returned condition is reversed. Do not generate new rtx when condition should be reversed; indicate it by setting new argument instead. (add_dependence_list_and_free): Add deps parameter. Update all users. Do not free dependence list when deps context is readonly. (add_insn_mem_dependence, flush_pending_lists): Adjust for readonly contexts. (remove_from_dependence_list, remove_from_both_dependence_lists): New. (remove_from_deps): New. Use the above functions. (cur_insn, can_start_lhs_rhs_p): New static variables. (add_or_update_back_dep_1): Initialize present_dep_type. (haifa_start_insn, haifa_finish_insn, haifa_note_reg_set, haifa_note_reg_clobber, haifa_note_reg_use, haifa_note_mem_dep, haifa_note_dep): New functions implementing dependence hooks for the Haifa scheduler. (note_reg_use, note_reg_set, note_reg_clobber, note_mem_dep, note_dep): New functions. (ds_to_dt, extend_deps_reg_info, maybe_extend_reg_info_p): New functions. (init_deps): Initialize last_reg_pending_barrier and deps->readonly. (free_deps): Initialize deps->reg_last. (sched_analyze_reg, sched_analyze_1, sched_analyze_2, sched_analyze_insn): Update to use dependency hooks infrastructure and readonly contexts. (deps_analyze_insn): New function. Move part of logic from ... (sched_analyze): ... here. Also move some logic to ... (deps_start_bb): ... here. New function. (add_forw_dep, delete_forw_dep): Guard use of INSN_DEP_COUNT with sel_sched_p. (sched_deps_init): New function. Move code from ... (init_dependency_caches): ... here. Remove. (init_deps_data_vector): New. (sched_deps_finish): New function. Move code from ... (free_dependency_caches): ... here. Remove. (init_deps_global, finish_deps_global): Adjust for use with selective scheduling. (get_dep_weak): Move logic to ... (get_dep_weak_1): New function. (ds_merge): Move logic to ... (ds_merge_1): New static function. (ds_full_merge, ds_max_merge, ds_get_speculation_types): New functions. (ds_get_max_dep_weak): New function. * sched-ebb.c (sched_n_insns): Rename to sched_rgn_n_insns. (n_insns): Rename to rgn_n_insns. (debug_ebb_dependencies): New function. (init_ready_list): Use it. (begin_schedule_ready): Use sched_init_only_bb. (ebb_print_insn): Indicate when an insn starts a new cycle. (contributes_to_priority, compute_jump_reg_dependencies, add_remove_insn, fix_recovery_cfg): Add ebb_ prefix to function names. (add_block1): Remove to ebb_add_block. (ebb_sched_deps_info, ebb_common_sched_info): New variables. (schedule_ebb): Initialize them. Use remove_notes instead of rm_other_notes. Use haifa_local_init/finish. (schedule_ebbs): Use haifa_sched_init/finish. * sched-int.h: Include vecprim.h, remove rtl.h. (struct ready_list): Delete declaration. (sched_verbose_param, enum sched_pass_id_t, bb_vec_t, insn_vec_t, rtx_vec_t): New. (struct sched_scan_info_def): New structure. (sched_scan_info, sched_scan, sched_init_bbs, sched_init_luids, sched_finish_luids, sched_extend_target, haifa_init_h_i_d, haifa_finish_h_i_d): Declare. (struct common_sched_info_def): New. (common_sched_info, haifa_common_sched_info, sched_emulate_haifa_p): Declare. (sel_sched_p): New. (sched_luids): Declare. (INSN_LUID, LUID_BY_UID, SET_INSN_LUID): Declare. (sched_max_luid, insn_luid): Declare. (note_list, remove_notes, restore_other_notes, bb_note): Declare. (sched_insns_init, sched_insns_finish, xrecalloc, reemit_notes, print_insn, print_pattern, print_value, haifa_classify_insn, sel_find_rgns, sel_mark_hard_insn, dfa_state_size, advance_state, setup_sched_dump, sched_init, sched_finish, sel_insn_is_speculation_check): Export. (struct ready_list): Move from haifa-sched.c. (ready_try, ready, max_issue): Export. (ebb_compute_jump_reg_dependencies, find_fallthru_edge, sched_init_only_bb, sched_split_block, sched_split_block_1, sched_create_empty_bb, sched_create_empty_bb_1, sched_create_recovery_block, sched_create_recovery_edges): Export. (enum reg_pending_barrier_mode): Export. (struct deps): New fields `last_reg_pending_barrier' and `readonly'. (deps_t): New. (struct sched_info): Rename to haifa_sched_info. Use const_rtx for print_insn field. Move add_block and fix_recovery_cfg to common_sched_info_def. Move compute_jump_reg_dependencies, use_cselib ... (struct sched_deps_info_def): ... this new structure. (sched_deps_info): Declare. (struct spec_info_def): Remove weakness_cutoff, add data_weakness_cutoff and control_weakness_cutoff. (spec_info): Declare. (struct _haifa_deps_insn_data): Split from haifa_insn_data. Add dep_count field. (struct haifa_insn_data): Rename to struct _haifa_insn_data. (haifa_insn_data_def, haifa_insn_data_t): New typedefs. (current_sched_info): Change type to struct haifa_sched_info. (haifa_deps_insn_data_def, haifa_deps_insn_data_t): New typedefs. (h_d_i_d): New variable. (HDID): New accessor macro. (h_i_d): Change type to VEC (haifa_insn_data_def, heap) *. (HID): New accessor macro. Rewrite h_i_d accessor macros through HID and HDID. (IS_SPECULATION_CHECK_P): Update for selective scheduler. (enum SCHED_FLAGS): Update for selective scheduler. (enum SPEC_SCHED_FLAGS): New flag SEL_SCHED_SPEC_DONT_CHECK_CONTROL. (init_dependency_caches, free_dependency_caches): Delete declarations. (deps_analyze_insn, remove_from_deps, get_dep_weak_1, estimate_dep_weak, ds_full_merge, ds_max_merge, ds_weak, ds_get_speculation_types, ds_get_max_dep_weak, sched_deps_init, sched_deps_finish, haifa_note_reg_set, haifa_note_reg_use, haifa_note_reg_clobber, maybe_extend_reg_info_p, deps_start_bb, ds_to_dt): Export. (rm_other_notes): Delete declaration. (schedule_block): Remove one argument. (cycle_issued_insns, issue_rate, dfa_lookahead, ready_sort, ready_element, ready_lastpos, sched_extend_ready_list, sched_finish_ready_list, sched_change_pattern, sched_speculate_insn, concat_note_lists): Export. (struct region): Move from sched-rgn.h. (nr_regions, rgn_table, rgn_bb_table, block_to_bb, containing_rgn, RGN_NR_BLOCKS, RGN_BLOCKS, RGN_DONT_CALC_DEPS, RGN_HAS_REAL_EBB, BLOCK_TO_BB, CONTAINING_RGN): Export. (ebb_head, BB_TO_BLOCK, EBB_FIRST_BB, EBB_LAST_BB, INSN_BB): Likewise. (current_nr_blocks, current_blocks, target_bb): Likewise. (dep_cost_1, sched_is_disabled_for_current_region_p, sched_rgn_init, sched_rgn_finish, rgn_setup_region, sched_rgn_compute_dependencies, sched_rgn_local_init, extend_regions, rgn_make_new_region_out_of_new_block, compute_priorities, debug_rgn_dependencies, free_rgn_deps, contributes_to_priority, extend_rgns, deps_join rgn_setup_common_sched_info, rgn_setup_sched_infos, debug_regions, debug_region, dump_region_dot, dump_region_dot_file, haifa_sched_init, haifa_sched_finish): Export. (get_rgn_sched_max_insns_priority, sel_add_to_insn_priority, increase_insn_priority): Likewise. * sched-rgn.c: Include sel-sched.h. (ref_counts): New static variable. Use it ... (INSN_REF_COUNT): ... here. Rewrite and move closer to uses. (FED_BY_SPEC_LOAD, IS_LOAD_INSN): Rewrite to use HID accessor macro. (sched_is_disabled_for_current_region_p): Delete static declaration. (struct region): Move to sched-int.h. (nr_regions, rgn_table, rgn_bb_table, block_to_bb, containing_rgn, ebb_head): Define and initialize. (RGN_NR_BLOCKS, RGN_BLOCKS, RGN_DONT_CALC_DEPS, RGN_HAS_REAL_EBB, BLOCK_TO_BB, CONTAINING_RGN, debug_regions, extend_regions, BB_TO_BLOCK, EBB_FIRST_BB, EBB_LAST_BB): Move to sched-int.h. (find_single_block_region): Add new argument to indicate that EBB regions should be constructed. (debug_live): Delete declaration. (current_nr_blocks, current_blocks, target_bb): Remove static qualifiers. (compute_dom_prob_ps, check_live, update_live, set_spec_fed): Delete declaration. (init_regions): Delete declaration. (debug_region, bb_in_region_p, dump_region_dot_file, dump_region_dot, rgn_estimate_number_of_insns): New. (too_large): Use estimate_number_of_insns. (haifa_find_rgns): New. Move the code from ... (find_rgns): ... here. Call either sel_find_rgns or haifa_find_rgns. (free_trg_info): New. (compute_trg_info): Allocate candidate tables here instead of ... (init_ready_list): ... here. (rgn_print_insn): Use const_rtx. (contributes_to_priority, extend_regions): Delete static declaration. (add_remove_insn, fix_recovery_cfg): Add rgn_ to function names. (add_block1): Rename to rgn_add_block. (debug_rgn_dependencies): Delete static qualifier. (new_ready): Use sched_deps_info. Simplify. (rgn_common_sched_info, rgn_const_sched_deps_info, rgn_const_sel_sched_deps_info, rgn_sched_deps_info, rgn_sched_info): New. (region_sched_info): Rename to rgn_const_sched_info. (deps_join): New, extracted from ... (propagate_deps): ... here. (compute_block_dependences, debug_dependencies): Update for selective scheduling. (free_rgn_deps, compute_priorities): New functions. (sched_rgn_init, sched_rgn_finish, rgn_setup_region, sched_rgn_compute_dependencies): New functions. (schedule_region): Use them. (sched_rgn_local_init, sched_rgn_local_free, sched_rgn_local_finish, rgn_setup_common_sched_info, rgn_setup_sched_infos): New functions. (schedule_insns): Call new functions that were split out. (rgn_make_new_region_out_of_new_block): New. (get_rgn_sched_max_insns_priority): New. (rest_of_handle_sched, rest_of_handle_sched2): Call selective scheduling when appropriate. * sched-vis.c: Include insn-attr.h. (print_value, print_pattern): Make global. (print_rtl_slim, debug_bb_slim, debug_bb_n_slim): New functions. * target-def.h (TARGET_SCHED_ADJUST_COST_2, TARGET_SCHED_ALLOC_SCHED_CONTEXT, TARGET_SCHED_INIT_SCHED_CONTEXT, TARGET_SCHED_SET_SCHED_CONTEXT, TARGET_SCHED_CLEAR_SCHED_CONTEXT, TARGET_SCHED_FREE_SCHED_CONTEXT, TARGET_SCHED_GET_INSN_CHECKED_DS, TARGET_SCHED_GET_INSN_SPEC_DS, TARGET_SCHED_SKIP_RTX_P): New target hooks. Initialize them to 0. (TARGET_SCHED_GEN_CHECK): Rename to TARGET_SCHED_GEN_SPEC_CHECK. * target.h (struct gcc_target): Add them. Rename gen_check field to gen_spec_check. * flags.h (sel_sched_switch_set): Declare. * opts.c (sel_sched_switch_set): New variable. (decode_options): Unset flag_sel_sched_pipelining_outer_loops if pipelining is disabled from command line. (common_handle_option): Record whether selective scheduling is requested from command line. * doc/invoke.texi: Document new flags and parameters. * doc/tm.texi: Document new target hooks. * config/ia64/ia64.c (TARGET_SCHED_GEN_SPEC_CHECK): Define to ia64_gen_check. (dfa_state_size): Do not declare locally. * config/ia64/ia64.opt (msched-ar-data-spec): Default to 0. * config/rs6000/rs6000.c (rs6000_init_sched_context, rs6000_alloc_sched_context, rs6000_set_sched_context, rs6000_free_sched_context): New functions. (struct _rs6000_sched_context): New. (rs6000_sched_reorder2): Do not modify INSN_PRIORITY for selective scheduling. (rs6000_sched_finish): Do not run for selective scheduling. Co-Authored-By: Alexander Monakov <amonakov@ispras.ru> Co-Authored-By: Dmitry Melnik <dm@ispras.ru> Co-Authored-By: Dmitry Zhurikhin <zhur@ispras.ru> Co-Authored-By: Maxim Kuvyrkov <maxim@codesourcery.com> From-SVN: r139854
This commit is contained in:
parent
f57ca1ea5f
commit
e855c69d16
405
gcc/ChangeLog
405
gcc/ChangeLog
@ -1,3 +1,408 @@
|
||||
2008-08-31 Andrey Belevantsev <abel@ispras.ru>
|
||||
Dmitry Melnik <dm@ispras.ru>
|
||||
Dmitry Zhurikhin <zhur@ispras.ru>
|
||||
Alexander Monakov <amonakov@ispras.ru>
|
||||
Maxim Kuvyrkov <maxim@codesourcery.com>
|
||||
|
||||
* sel-sched.h, sel-sched-dump.h, sel-sched-ir.h, sel-sched.c,
|
||||
sel-sched-dump.c, sel-sched-ir.c: New files.
|
||||
* Makefile.in (OBJS-common): Add selective scheduling object
|
||||
files.
|
||||
(sel-sched.o, sel-sched-dump.o, sel-sched-ir.o): New entries.
|
||||
(SEL_SCHED_IR_H, SEL_SCHED_DUMP_H): New entries.
|
||||
(sched-vis.o): Add dependency on $(INSN_ATTR_H).
|
||||
* cfghooks.h (get_cfg_hooks, set_cfg_hooks): New prototypes.
|
||||
* cfghooks.c (get_cfg_hooks, set_cfg_hooks): New functions.
|
||||
(make_forwarder_block): Update loop latch if we have redirected
|
||||
the loop latch edge.
|
||||
* cfgloop.c (get_loop_body_in_custom_order): New function.
|
||||
* cfgloop.h (LOOPS_HAVE_FALLTHRU_PREHEADERS): New enum field.
|
||||
(CP_FALLTHRU_PREHEADERS): Likewise.
|
||||
(get_loop_body_in_custom_order): Declare.
|
||||
* cfgloopmanip.c (has_preds_from_loop): New.
|
||||
(create_preheader): Honor CP_FALLTHRU_PREHEADERS.
|
||||
Assert that the preheader edge will be fall thru when it is set.
|
||||
* common.opt (fsel-sched-bookkeeping, fsel-sched-pipelining,
|
||||
fsel-sched-pipelining-outer-loops, fsel-sched-renaming,
|
||||
fsel-sched-substitution, fselective-scheduling): New flags.
|
||||
* cse.c (hash_rtx_cb): New.
|
||||
(hash_rtx): Use it.
|
||||
* dbgcnt.def (sel_sched_cnt, sel_sched_region_cnt,
|
||||
sel_sched_insn_cnt): New counters.
|
||||
* final.c (compute_alignments): Export. Free dominance info after loop_optimizer_finalize.
|
||||
* genattr.c (main): Output maximal_insn_latency prototype.
|
||||
* genautomata.c (output_default_latencies): New. Factor its code from ...
|
||||
(output_internal_insn_latency_func): ... here.
|
||||
(output_internal_maximal_insn_latency_func): New.
|
||||
(output_maximal_insn_latency_func): New.
|
||||
* hard-reg-set.h (UHOST_BITS_PER_WIDE_INT): Define unconditionally.
|
||||
(struct hard_reg_set_iterator): New.
|
||||
(hard_reg_set_iter_init, hard_reg_set_iter_set,
|
||||
hard_reg_set_iter_next): New functions.
|
||||
(EXECUTE_IF_SET_IN_HARD_REG_SET): New macro.
|
||||
* lists.c (remove_free_INSN_LIST_node,
|
||||
remove_free_EXPR_LIST_node): New functions.
|
||||
* loop-init.c (loop_optimizer_init): When LOOPS_HAVE_FALLTHRU_PREHEADERS,
|
||||
set CP_FALLTHRU_PREHEADERS when calling create_preheaders.
|
||||
(loop_optimizer_finalize): Do not verify flow info after reload.
|
||||
* recog.c (validate_replace_rtx_1): New parameter simplify.
|
||||
Default it to true. Update all uses. Factor out simplifying
|
||||
code to ...
|
||||
(simplify_while_replacing): ... this new function.
|
||||
(validate_replace_rtx_part,
|
||||
validate_replace_rtx_part_nosimplify): New.
|
||||
* recog.h (validate_replace_rtx_part,
|
||||
validate_replace_rtx_part_nosimplify): Declare.
|
||||
* rtl.c (rtx_equal_p_cb): New.
|
||||
(rtx_equal_p): Use it.
|
||||
* rtl.h (rtx_equal_p_cb, hash_rtx_cb): Declare.
|
||||
(remove_free_INSN_LIST_NODE, remove_free_EXPR_LIST_node,
|
||||
debug_bb_n_slim, debug_bb_slim, print_rtl_slim): Likewise.
|
||||
* vecprim.h: Add a vector type for unsigned int.
|
||||
* haifa-sched.c: Include vecprim.h and cfgloop.h.
|
||||
(issue_rate, sched_verbose_param, note_list, dfa_state_size,
|
||||
ready_try, cycle_issued_insns, spec_info): Make global.
|
||||
(readyp): Initialize.
|
||||
(dfa_lookahead): New global variable.
|
||||
(old_max_uid, old_last_basic_block): Remove.
|
||||
(h_i_d): Make it a vector.
|
||||
(INSN_TICK, INTER_TICK, QUEUE_INDEX, INSN_COST): Make them work
|
||||
through HID macro.
|
||||
(after_recovery, adding_bb_to_current_region_p):
|
||||
New variables to handle correct insertion of the recovery code.
|
||||
(struct ready_list): Move declaration to sched-int.h.
|
||||
(rgn_n_insns): Removed.
|
||||
(rtx_vec_t): Move to sched-int.h.
|
||||
(find_insn_reg_weight): Remove.
|
||||
(find_insn_reg_weight1): Rename to find_insn_reg_weight.
|
||||
(haifa_init_h_i_d, haifa_finish_h_i_d):
|
||||
New functions to initialize / finalize haifa instruction data.
|
||||
(extend_h_i_d, init_h_i_d): Rewrite.
|
||||
(unlink_other_notes): Move logic to add_to_note_list. Handle
|
||||
selective scheduler.
|
||||
(ready_lastpos, ready_element, ready_sort, reemit_notes,
|
||||
find_fallthru_edge): Make global, remove static prototypes.
|
||||
(max_issue): Make global. Add privileged_n and state parameters. Use
|
||||
them.
|
||||
(extend_global, extend_all): Removed.
|
||||
(init_before_recovery): Add new param. Fix the handling of the case
|
||||
when we insert a recovery code before the EXIT which has a predecessor
|
||||
with a fallthrough edge to it.
|
||||
(create_recovery_block): Make global. Rename to
|
||||
sched_create_recovery_block. Update.
|
||||
(change_pattern): Rename to sched_change_pattern. Make global.
|
||||
(speculate_insn): Rename to sched_speculate_insn. Make global.
|
||||
Split haifa-specific functionality into ...
|
||||
(haifa_change_pattern): New static function.
|
||||
(sched_extend_bb): New static function.
|
||||
(sched_init_bbs): New function.
|
||||
(current_sched_info): Change type to struct haifa_sched_info.
|
||||
(insn_cost): Adjust for selective scheduling.
|
||||
(dep_cost_1): New function. Move logic from ...
|
||||
(dep_cost): ... here.
|
||||
(dep_cost): Use dep_cost_1.
|
||||
(contributes_to_priority_p): Use sched_deps_info instead of
|
||||
current_sched_info.
|
||||
(priority): Adjust to work with selective scheduling. Process the
|
||||
corner case when all dependencies don't contribute to priority.
|
||||
(rank_for_schedule): Use ds_weak instead of dep_weak.
|
||||
(advance_state): New function. Move logic from ...
|
||||
(advance_one_cycle): ... here.
|
||||
(add_to_note_list, concat_note_lists): New functions.
|
||||
(rm_other_notes): Make static. Adjust for selective scheduling.
|
||||
(remove_notes, restore_other_notes): New functions.
|
||||
(move_insn): Add two arguments. Update assert. Don't call
|
||||
reemit_notes.
|
||||
(choose_ready): Remove lookahead variable, use dfa_lookahead.
|
||||
Remove more_issue, max_points. Move the code to initialize
|
||||
max_lookahead_tries to max_issue.
|
||||
(schedule_block): Remove rgn_n_insns1 parameter. Don't allocate
|
||||
ready. Adjust use of move_insn. Call restore_other_notes.
|
||||
(luid): Remove.
|
||||
(sched_init, sched_finish): Move Haifa-specific initialization/
|
||||
finalization to ...
|
||||
(haifa_sched_init, haifa_sched_finish): ... respectively.
|
||||
New functions.
|
||||
(setup_sched_dump): New function.
|
||||
(haifa_init_only_bb): New static function.
|
||||
(haifa_speculate_insn): New static function.
|
||||
(try_ready): Use haifa_* instead of speculate_insn and
|
||||
change_pattern.
|
||||
(extend_ready, extend_all): Remove.
|
||||
(sched_extend_ready_list, sched_finish_ready_list): New functions.
|
||||
(create_check_block_twin, add_to_speculative_block): Use
|
||||
haifa_insns_init instead of extend_global. Update to use new
|
||||
initialization functions. Change parameter. Factor out code from
|
||||
create_check_block_twin to ...
|
||||
(sched_create_recovery_edges) ... this new function.
|
||||
(add_block): Remove.
|
||||
(sched_scan_info): New.
|
||||
(extend_bb): Use sched_scan_info.
|
||||
(init_bb, extend_insn, init_insn, init_insns_in_bb, sched_scan): New
|
||||
static functions for walking through scheduling region.
|
||||
(sched_luids): New vector variable to replace uid_to_luid.
|
||||
(luids_extend_insn): New function.
|
||||
(sched_max_luid): New variable.
|
||||
(luids_init_insn): New function.
|
||||
(sched_init_luids, sched_finish_luids): New functions.
|
||||
(insn_luid): New debug function.
|
||||
(sched_extend_target): New function.
|
||||
(haifa_init_insn): New static function.
|
||||
(sched_init_only_bb): New hook.
|
||||
(sched_split_block): New hook.
|
||||
(sched_split_block_1): New function.
|
||||
(sched_create_empty_bb): New hook.
|
||||
(sched_create_empty_bb_1): New function.
|
||||
(common_sched_info, ready): New global variables.
|
||||
(current_sched_info_var): Remove.
|
||||
(move_block_after_check): Use common_sched_info.
|
||||
(haifa_luid_for_non_insn): New static function.
|
||||
(init_before_recovery): Use haifa_init_only_bb instead of
|
||||
add_block.
|
||||
(increase_insn_priority): New.
|
||||
* modulo-sched.c: (issue_rate): Remove static declaration.
|
||||
(sms_sched_info): Change type to haifa_sched_info.
|
||||
(sms_sched_deps_info, sms_common_sched_info): New variables.
|
||||
(setup_sched_infos): New.
|
||||
(sms_schedule): Initialize them. Call haifa_sched_init/finish.
|
||||
Do not call regstat_free_calls_crossed.
|
||||
(sms_print_insn): Use const_rtx.
|
||||
* params.def (PARAM_MAX_PIPELINE_REGION_BLOCKS,
|
||||
PARAM_MAX_PIPELINE_REGION_INSNS, PARAM_SELSCHED_MAX_LOOKAHEAD,
|
||||
PARAM_SELSCHED_MAX_SCHED_TIMES, PARAM_SELSCHED_INSNS_TO_RENAME,
|
||||
PARAM_SCHED_MEM_TRUE_DEP_COST): New.
|
||||
* sched-deps.c (sched_deps_info): New. Update all relevant uses of
|
||||
current_sched_info to use it.
|
||||
(enum reg_pending_barrier_mode): Move to sched-int.h.
|
||||
(h_d_i_d): New variable. Initialize to NULL.
|
||||
({true, output, anti, spec, forward}_dependency_cache): Initialize
|
||||
to NULL.
|
||||
(estimate_dep_weak): Remove static declaration.
|
||||
(sched_has_condition_p): New function. Adjust users of
|
||||
sched_get_condition to use it instead.
|
||||
(conditions_mutex_p): Add arguments indicating which conditions are
|
||||
reversed. Use them.
|
||||
(sched_get_condition_with_rev): Rename from sched_get_condition. Add
|
||||
argument to indicate whether returned condition is reversed. Do not
|
||||
generate new rtx when condition should be reversed; indicate it by
|
||||
setting new argument instead.
|
||||
(add_dependence_list_and_free): Add deps parameter.
|
||||
Update all users. Do not free dependence list when
|
||||
deps context is readonly.
|
||||
(add_insn_mem_dependence, flush_pending_lists): Adjust for readonly
|
||||
contexts.
|
||||
(remove_from_dependence_list, remove_from_both_dependence_lists): New.
|
||||
(remove_from_deps): New. Use the above functions.
|
||||
(cur_insn, can_start_lhs_rhs_p): New static variables.
|
||||
(add_or_update_back_dep_1): Initialize present_dep_type.
|
||||
(haifa_start_insn, haifa_finish_insn, haifa_note_reg_set,
|
||||
haifa_note_reg_clobber, haifa_note_reg_use, haifa_note_mem_dep,
|
||||
haifa_note_dep): New functions implementing dependence hooks for
|
||||
the Haifa scheduler.
|
||||
(note_reg_use, note_reg_set, note_reg_clobber, note_mem_dep,
|
||||
note_dep): New functions.
|
||||
(ds_to_dt, extend_deps_reg_info, maybe_extend_reg_info_p): New
|
||||
functions.
|
||||
(init_deps): Initialize last_reg_pending_barrier and deps->readonly.
|
||||
(free_deps): Initialize deps->reg_last.
|
||||
(sched_analyze_reg, sched_analyze_1, sched_analyze_2,
|
||||
sched_analyze_insn): Update to use dependency hooks infrastructure
|
||||
and readonly contexts.
|
||||
(deps_analyze_insn): New function. Move part of logic from ...
|
||||
(sched_analyze): ... here. Also move some logic to ...
|
||||
(deps_start_bb): ... here. New function.
|
||||
(add_forw_dep, delete_forw_dep): Guard use of INSN_DEP_COUNT with
|
||||
sel_sched_p.
|
||||
(sched_deps_init): New function. Move code from ...
|
||||
(init_dependency_caches): ... here. Remove.
|
||||
(init_deps_data_vector): New.
|
||||
(sched_deps_finish): New function. Move code from ...
|
||||
(free_dependency_caches): ... here. Remove.
|
||||
(init_deps_global, finish_deps_global): Adjust for use with
|
||||
selective scheduling.
|
||||
(get_dep_weak): Move logic to ...
|
||||
(get_dep_weak_1): New function.
|
||||
(ds_merge): Move logic to ...
|
||||
(ds_merge_1): New static function.
|
||||
(ds_full_merge, ds_max_merge, ds_get_speculation_types): New functions.
|
||||
(ds_get_max_dep_weak): New function.
|
||||
* sched-ebb.c (sched_n_insns): Rename to sched_rgn_n_insns.
|
||||
(n_insns): Rename to rgn_n_insns.
|
||||
(debug_ebb_dependencies): New function.
|
||||
(init_ready_list): Use it.
|
||||
(begin_schedule_ready): Use sched_init_only_bb.
|
||||
(ebb_print_insn): Indicate when an insn starts a new cycle.
|
||||
(contributes_to_priority, compute_jump_reg_dependencies,
|
||||
add_remove_insn, fix_recovery_cfg): Add ebb_ prefix to function names.
|
||||
(add_block1): Remove to ebb_add_block.
|
||||
(ebb_sched_deps_info, ebb_common_sched_info): New variables.
|
||||
(schedule_ebb): Initialize them. Use remove_notes instead of
|
||||
rm_other_notes. Use haifa_local_init/finish.
|
||||
(schedule_ebbs): Use haifa_sched_init/finish.
|
||||
* sched-int.h: Include vecprim.h, remove rtl.h.
|
||||
(struct ready_list): Delete declaration.
|
||||
(sched_verbose_param, enum sched_pass_id_t,
|
||||
bb_vec_t, insn_vec_t, rtx_vec_t): New.
|
||||
(struct sched_scan_info_def): New structure.
|
||||
(sched_scan_info, sched_scan, sched_init_bbs,
|
||||
sched_init_luids, sched_finish_luids, sched_extend_target,
|
||||
haifa_init_h_i_d, haifa_finish_h_i_d): Declare.
|
||||
(struct common_sched_info_def): New.
|
||||
(common_sched_info, haifa_common_sched_info,
|
||||
sched_emulate_haifa_p): Declare.
|
||||
(sel_sched_p): New.
|
||||
(sched_luids): Declare.
|
||||
(INSN_LUID, LUID_BY_UID, SET_INSN_LUID): Declare.
|
||||
(sched_max_luid, insn_luid): Declare.
|
||||
(note_list, remove_notes, restore_other_notes, bb_note): Declare.
|
||||
(sched_insns_init, sched_insns_finish, xrecalloc, reemit_notes,
|
||||
print_insn, print_pattern, print_value, haifa_classify_insn,
|
||||
sel_find_rgns, sel_mark_hard_insn, dfa_state_size, advance_state,
|
||||
setup_sched_dump, sched_init, sched_finish,
|
||||
sel_insn_is_speculation_check): Export.
|
||||
(struct ready_list): Move from haifa-sched.c.
|
||||
(ready_try, ready, max_issue): Export.
|
||||
(ebb_compute_jump_reg_dependencies, find_fallthru_edge,
|
||||
sched_init_only_bb, sched_split_block, sched_split_block_1,
|
||||
sched_create_empty_bb, sched_create_empty_bb_1,
|
||||
sched_create_recovery_block, sched_create_recovery_edges): Export.
|
||||
(enum reg_pending_barrier_mode): Export.
|
||||
(struct deps): New fields `last_reg_pending_barrier' and `readonly'.
|
||||
(deps_t): New.
|
||||
(struct sched_info): Rename to haifa_sched_info. Use const_rtx for
|
||||
print_insn field. Move add_block and fix_recovery_cfg to
|
||||
common_sched_info_def. Move compute_jump_reg_dependencies, use_cselib ...
|
||||
(struct sched_deps_info_def): ... this new structure.
|
||||
(sched_deps_info): Declare.
|
||||
(struct spec_info_def): Remove weakness_cutoff, add
|
||||
data_weakness_cutoff and control_weakness_cutoff.
|
||||
(spec_info): Declare.
|
||||
(struct _haifa_deps_insn_data): Split from haifa_insn_data. Add
|
||||
dep_count field.
|
||||
(struct haifa_insn_data): Rename to struct _haifa_insn_data.
|
||||
(haifa_insn_data_def, haifa_insn_data_t): New typedefs.
|
||||
(current_sched_info): Change type to struct haifa_sched_info.
|
||||
(haifa_deps_insn_data_def, haifa_deps_insn_data_t): New typedefs.
|
||||
(h_d_i_d): New variable.
|
||||
(HDID): New accessor macro.
|
||||
(h_i_d): Change type to VEC (haifa_insn_data_def, heap) *.
|
||||
(HID): New accessor macro. Rewrite h_i_d accessor macros through HID
|
||||
and HDID.
|
||||
(IS_SPECULATION_CHECK_P): Update for selective scheduler.
|
||||
(enum SCHED_FLAGS): Update for selective scheduler.
|
||||
(enum SPEC_SCHED_FLAGS): New flag SEL_SCHED_SPEC_DONT_CHECK_CONTROL.
|
||||
(init_dependency_caches, free_dependency_caches): Delete declarations.
|
||||
(deps_analyze_insn, remove_from_deps, get_dep_weak_1,
|
||||
estimate_dep_weak, ds_full_merge, ds_max_merge, ds_weak,
|
||||
ds_get_speculation_types, ds_get_max_dep_weak, sched_deps_init,
|
||||
sched_deps_finish, haifa_note_reg_set, haifa_note_reg_use,
|
||||
haifa_note_reg_clobber, maybe_extend_reg_info_p, deps_start_bb,
|
||||
ds_to_dt): Export.
|
||||
(rm_other_notes): Delete declaration.
|
||||
(schedule_block): Remove one argument.
|
||||
(cycle_issued_insns, issue_rate, dfa_lookahead, ready_sort,
|
||||
ready_element, ready_lastpos, sched_extend_ready_list,
|
||||
sched_finish_ready_list, sched_change_pattern, sched_speculate_insn,
|
||||
concat_note_lists): Export.
|
||||
(struct region): Move from sched-rgn.h.
|
||||
(nr_regions, rgn_table, rgn_bb_table, block_to_bb, containing_rgn,
|
||||
RGN_NR_BLOCKS, RGN_BLOCKS, RGN_DONT_CALC_DEPS, RGN_HAS_REAL_EBB,
|
||||
BLOCK_TO_BB, CONTAINING_RGN): Export.
|
||||
(ebb_head, BB_TO_BLOCK, EBB_FIRST_BB, EBB_LAST_BB, INSN_BB): Likewise.
|
||||
(current_nr_blocks, current_blocks, target_bb): Likewise.
|
||||
(dep_cost_1, sched_is_disabled_for_current_region_p, sched_rgn_init,
|
||||
sched_rgn_finish, rgn_setup_region, sched_rgn_compute_dependencies,
|
||||
sched_rgn_local_init, extend_regions,
|
||||
rgn_make_new_region_out_of_new_block, compute_priorities,
|
||||
debug_rgn_dependencies, free_rgn_deps, contributes_to_priority,
|
||||
extend_rgns, deps_join rgn_setup_common_sched_info,
|
||||
rgn_setup_sched_infos, debug_regions, debug_region, dump_region_dot,
|
||||
dump_region_dot_file, haifa_sched_init, haifa_sched_finish): Export.
|
||||
(get_rgn_sched_max_insns_priority, sel_add_to_insn_priority,
|
||||
increase_insn_priority): Likewise.
|
||||
* sched-rgn.c: Include sel-sched.h.
|
||||
(ref_counts): New static variable. Use it ...
|
||||
(INSN_REF_COUNT): ... here. Rewrite and move closer to uses.
|
||||
(FED_BY_SPEC_LOAD, IS_LOAD_INSN): Rewrite to use HID accessor macro.
|
||||
(sched_is_disabled_for_current_region_p): Delete static declaration.
|
||||
(struct region): Move to sched-int.h.
|
||||
(nr_regions, rgn_table, rgn_bb_table, block_to_bb, containing_rgn,
|
||||
ebb_head): Define and initialize.
|
||||
(RGN_NR_BLOCKS, RGN_BLOCKS, RGN_DONT_CALC_DEPS, RGN_HAS_REAL_EBB,
|
||||
BLOCK_TO_BB, CONTAINING_RGN, debug_regions, extend_regions,
|
||||
BB_TO_BLOCK, EBB_FIRST_BB, EBB_LAST_BB): Move to
|
||||
sched-int.h.
|
||||
(find_single_block_region): Add new argument to indicate that EBB
|
||||
regions should be constructed.
|
||||
(debug_live): Delete declaration.
|
||||
(current_nr_blocks, current_blocks, target_bb): Remove static qualifiers.
|
||||
(compute_dom_prob_ps, check_live, update_live, set_spec_fed): Delete
|
||||
declaration.
|
||||
(init_regions): Delete declaration.
|
||||
(debug_region, bb_in_region_p, dump_region_dot_file, dump_region_dot,
|
||||
rgn_estimate_number_of_insns): New.
|
||||
(too_large): Use estimate_number_of_insns.
|
||||
(haifa_find_rgns): New. Move the code from ...
|
||||
(find_rgns): ... here. Call either sel_find_rgns or haifa_find_rgns.
|
||||
(free_trg_info): New.
|
||||
(compute_trg_info): Allocate candidate tables here instead of ...
|
||||
(init_ready_list): ... here.
|
||||
(rgn_print_insn): Use const_rtx.
|
||||
(contributes_to_priority, extend_regions): Delete static declaration.
|
||||
(add_remove_insn, fix_recovery_cfg): Add rgn_ to function names.
|
||||
(add_block1): Rename to rgn_add_block.
|
||||
(debug_rgn_dependencies): Delete static qualifier.
|
||||
(new_ready): Use sched_deps_info. Simplify.
|
||||
(rgn_common_sched_info, rgn_const_sched_deps_info,
|
||||
rgn_const_sel_sched_deps_info, rgn_sched_deps_info, rgn_sched_info): New.
|
||||
(region_sched_info): Rename to rgn_const_sched_info.
|
||||
(deps_join): New, extracted from ...
|
||||
(propagate_deps): ... here.
|
||||
(compute_block_dependences, debug_dependencies): Update for selective
|
||||
scheduling.
|
||||
(free_rgn_deps, compute_priorities): New functions.
|
||||
(sched_rgn_init, sched_rgn_finish, rgn_setup_region,
|
||||
sched_rgn_compute_dependencies): New functions.
|
||||
(schedule_region): Use them.
|
||||
(sched_rgn_local_init, sched_rgn_local_free, sched_rgn_local_finish,
|
||||
rgn_setup_common_sched_info, rgn_setup_sched_infos):
|
||||
New functions.
|
||||
(schedule_insns): Call new functions that were split out.
|
||||
(rgn_make_new_region_out_of_new_block): New.
|
||||
(get_rgn_sched_max_insns_priority): New.
|
||||
(rest_of_handle_sched, rest_of_handle_sched2): Call selective
|
||||
scheduling when appropriate.
|
||||
* sched-vis.c: Include insn-attr.h.
|
||||
(print_value, print_pattern): Make global.
|
||||
(print_rtl_slim, debug_bb_slim, debug_bb_n_slim): New functions.
|
||||
* target-def.h (TARGET_SCHED_ADJUST_COST_2,
|
||||
TARGET_SCHED_ALLOC_SCHED_CONTEXT, TARGET_SCHED_INIT_SCHED_CONTEXT,
|
||||
TARGET_SCHED_SET_SCHED_CONTEXT, TARGET_SCHED_CLEAR_SCHED_CONTEXT,
|
||||
TARGET_SCHED_FREE_SCHED_CONTEXT, TARGET_SCHED_GET_INSN_CHECKED_DS,
|
||||
TARGET_SCHED_GET_INSN_SPEC_DS, TARGET_SCHED_SKIP_RTX_P): New target
|
||||
hooks. Initialize them to 0.
|
||||
(TARGET_SCHED_GEN_CHECK): Rename to TARGET_SCHED_GEN_SPEC_CHECK.
|
||||
* target.h (struct gcc_target): Add them. Rename gen_check field to
|
||||
gen_spec_check.
|
||||
* flags.h (sel_sched_switch_set): Declare.
|
||||
* opts.c (sel_sched_switch_set): New variable.
|
||||
(decode_options): Unset flag_sel_sched_pipelining_outer_loops if
|
||||
pipelining is disabled from command line.
|
||||
(common_handle_option): Record whether selective scheduling is
|
||||
requested from command line.
|
||||
* doc/invoke.texi: Document new flags and parameters.
|
||||
* doc/tm.texi: Document new target hooks.
|
||||
* config/ia64/ia64.c (TARGET_SCHED_GEN_SPEC_CHECK): Define to ia64_gen_check.
|
||||
(dfa_state_size): Do not declare locally.
|
||||
* config/ia64/ia64.opt (msched-ar-data-spec): Default to 0.
|
||||
* config/rs6000/rs6000.c (rs6000_init_sched_context,
|
||||
rs6000_alloc_sched_context, rs6000_set_sched_context,
|
||||
rs6000_free_sched_context): New functions.
|
||||
(struct _rs6000_sched_context): New.
|
||||
(rs6000_sched_reorder2): Do not modify INSN_PRIORITY for selective
|
||||
scheduling.
|
||||
(rs6000_sched_finish): Do not run for selective scheduling.
|
||||
|
||||
2008-08-31 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* frv.c (frv_rtx_costs): Update forward declaration.
|
||||
|
@ -803,7 +803,10 @@ OPTABS_H = optabs.h insn-codes.h
|
||||
REGS_H = regs.h varray.h $(MACHMODE_H) $(OBSTACK_H) $(BASIC_BLOCK_H) $(FUNCTION_H)
|
||||
RA_H = ra.h $(REGS_H)
|
||||
RESOURCE_H = resource.h hard-reg-set.h
|
||||
SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) $(DF_H)
|
||||
SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) $(DF_H) vecprim.h
|
||||
SEL_SCHED_IR_H = sel-sched-ir.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) \
|
||||
$(GGC_H) $(SCHED_INT_H)
|
||||
SEL_SCHED_DUMP_H = sel-sched-dump.h $(SEL_SCHED_IR_H)
|
||||
INTEGRATE_H = integrate.h $(VARRAY_H)
|
||||
CFGLAYOUT_H = cfglayout.h $(BASIC_BLOCK_H)
|
||||
CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(RTL_H) vecprim.h double-int.h
|
||||
@ -1163,6 +1166,9 @@ OBJS-common = \
|
||||
sched-vis.o \
|
||||
sdbout.o \
|
||||
see.o \
|
||||
sel-sched-ir.o \
|
||||
sel-sched-dump.o \
|
||||
sel-sched.o \
|
||||
simplify-rtx.o \
|
||||
sparseset.o \
|
||||
sreal.o \
|
||||
@ -2941,14 +2947,31 @@ sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
|
||||
$(FUNCTION_H) $(INSN_ATTR_H) $(TOPLEV_H) $(RECOG_H) except.h $(PARAMS_H) \
|
||||
$(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) tree-pass.h $(DBGCNT_H)
|
||||
$(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) tree-pass.h \
|
||||
$(DBGCNT_H)
|
||||
sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
|
||||
$(FUNCTION_H) $(INSN_ATTR_H) $(TOPLEV_H) $(RECOG_H) except.h $(TM_P_H) \
|
||||
$(PARAMS_H) $(CFGLAYOUT_H) $(TARGET_H) output.h
|
||||
sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(SCHED_INT_H) hard-reg-set.h $(BASIC_BLOCK_H) $(OBSTACK_H) \
|
||||
$(REAL_H) tree-pass.h
|
||||
$(REAL_H) tree-pass.h $(INSN_ATTR_H)
|
||||
sel-sched.o : sel-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
|
||||
$(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(PARAMS_H) \
|
||||
$(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) tree-pass.h \
|
||||
$(SCHED_INT_H) $(GGC_H) $(TREE_H) $(LANGHOOKS_DEF_H) \
|
||||
$(SEL_SCHED_IR_H) $(SEL_SCHED_DUMP_H) sel-sched.h
|
||||
sel-sched-dump.o : sel-sched-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
|
||||
$(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(PARAMS_H) \
|
||||
$(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) tree-pass.h \
|
||||
$(SEL_SCHED_DUMP_H) $(GGC_H) $(TREE_H) $(LANGHOOKS_DEF_H) $(SEL_SCHED_IR_H)
|
||||
sel-sched-ir.o : sel-sched-ir.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
|
||||
$(FUNCTION_H) $(INSN_ATTR_H) toplev.h $(RECOG_H) except.h $(PARAMS_H) \
|
||||
$(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) tree-pass.h \
|
||||
$(SCHED_INT_H) $(GGC_H) $(TREE_H) $(LANGHOOKS_DEF_H) $(SEL_SCHED_IR_H)
|
||||
final.o : final.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(TREE_H) $(FLAGS_H) intl.h $(REGS_H) $(RECOG_H) conditions.h \
|
||||
insn-config.h $(INSN_ATTR_H) $(FUNCTION_H) output.h hard-reg-set.h \
|
||||
|
@ -56,6 +56,18 @@ gimple_register_cfg_hooks (void)
|
||||
cfg_hooks = &gimple_cfg_hooks;
|
||||
}
|
||||
|
||||
struct cfg_hooks
|
||||
get_cfg_hooks (void)
|
||||
{
|
||||
return *cfg_hooks;
|
||||
}
|
||||
|
||||
void
|
||||
set_cfg_hooks (struct cfg_hooks new_cfg_hooks)
|
||||
{
|
||||
*cfg_hooks = new_cfg_hooks;
|
||||
}
|
||||
|
||||
/* Returns current ir type. */
|
||||
|
||||
enum ir_type
|
||||
@ -719,6 +731,8 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
|
||||
/* Redirect back edges we want to keep. */
|
||||
for (ei = ei_start (dummy->preds); (e = ei_safe_edge (ei)); )
|
||||
{
|
||||
basic_block e_src;
|
||||
|
||||
if (redirect_edge_p (e))
|
||||
{
|
||||
ei_next (&ei);
|
||||
@ -735,10 +749,21 @@ make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
|
||||
if (fallthru->count < 0)
|
||||
fallthru->count = 0;
|
||||
|
||||
e_src = e->src;
|
||||
jump = redirect_edge_and_branch_force (e, bb);
|
||||
if (jump != NULL
|
||||
&& new_bb_cbk != NULL)
|
||||
new_bb_cbk (jump);
|
||||
if (jump != NULL)
|
||||
{
|
||||
/* If we redirected the loop latch edge, the JUMP block now acts like
|
||||
the new latch of the loop. */
|
||||
if (current_loops != NULL
|
||||
&& dummy->loop_father != NULL
|
||||
&& dummy->loop_father->header == dummy
|
||||
&& dummy->loop_father->latch == e_src)
|
||||
dummy->loop_father->latch = jump;
|
||||
|
||||
if (new_bb_cbk != NULL)
|
||||
new_bb_cbk (jump);
|
||||
}
|
||||
}
|
||||
|
||||
if (dom_info_available_p (CDI_DOMINATORS))
|
||||
|
@ -190,5 +190,7 @@ extern enum ir_type current_ir_type (void);
|
||||
extern void rtl_register_cfg_hooks (void);
|
||||
extern void cfg_layout_rtl_register_cfg_hooks (void);
|
||||
extern void gimple_register_cfg_hooks (void);
|
||||
extern struct cfg_hooks get_cfg_hooks (void);
|
||||
extern void set_cfg_hooks (struct cfg_hooks);
|
||||
|
||||
#endif /* GCC_CFGHOOKS_H */
|
||||
|
@ -887,6 +887,19 @@ get_loop_body_in_dom_order (const struct loop *loop)
|
||||
return tovisit;
|
||||
}
|
||||
|
||||
/* Gets body of a LOOP sorted via provided BB_COMPARATOR. */
|
||||
|
||||
basic_block *
|
||||
get_loop_body_in_custom_order (const struct loop *loop,
|
||||
int (*bb_comparator) (const void *, const void *))
|
||||
{
|
||||
basic_block *bbs = get_loop_body (loop);
|
||||
|
||||
qsort (bbs, loop->num_nodes, sizeof (basic_block), bb_comparator);
|
||||
|
||||
return bbs;
|
||||
}
|
||||
|
||||
/* Get body of a LOOP in breadth first sort order. */
|
||||
|
||||
basic_block *
|
||||
|
@ -171,7 +171,8 @@ enum
|
||||
LOOPS_HAVE_RECORDED_EXITS = 8,
|
||||
LOOPS_MAY_HAVE_MULTIPLE_LATCHES = 16,
|
||||
LOOP_CLOSED_SSA = 32,
|
||||
LOOPS_NEED_FIXUP = 64
|
||||
LOOPS_NEED_FIXUP = 64,
|
||||
LOOPS_HAVE_FALLTHRU_PREHEADERS = 128
|
||||
};
|
||||
|
||||
#define LOOPS_NORMAL (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES \
|
||||
@ -235,6 +236,9 @@ extern unsigned get_loop_body_with_size (const struct loop *, basic_block *,
|
||||
unsigned);
|
||||
extern basic_block *get_loop_body_in_dom_order (const struct loop *);
|
||||
extern basic_block *get_loop_body_in_bfs_order (const struct loop *);
|
||||
extern basic_block *get_loop_body_in_custom_order (const struct loop *,
|
||||
int (*) (const void *, const void *));
|
||||
|
||||
extern VEC (edge, heap) *get_loop_exit_edges (const struct loop *);
|
||||
edge single_exit (const struct loop *);
|
||||
extern unsigned num_loop_branches (const struct loop *);
|
||||
@ -250,7 +254,8 @@ extern void delete_loop (struct loop *);
|
||||
|
||||
enum
|
||||
{
|
||||
CP_SIMPLE_PREHEADERS = 1
|
||||
CP_SIMPLE_PREHEADERS = 1,
|
||||
CP_FALLTHRU_PREHEADERS = 2
|
||||
};
|
||||
|
||||
basic_block create_preheader (struct loop *, int);
|
||||
|
@ -1102,9 +1102,26 @@ mfb_keep_just (edge e)
|
||||
return e != mfb_kj_edge;
|
||||
}
|
||||
|
||||
/* True when a candidate preheader BLOCK has predecessors from LOOP. */
|
||||
|
||||
static bool
|
||||
has_preds_from_loop (basic_block block, struct loop *loop)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
FOR_EACH_EDGE (e, ei, block->preds)
|
||||
if (e->src->loop_father == loop)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Creates a pre-header for a LOOP. Returns newly created block. Unless
|
||||
CP_SIMPLE_PREHEADERS is set in FLAGS, we only force LOOP to have single
|
||||
entry; otherwise we also force preheader block to have only one successor.
|
||||
When CP_FALLTHRU_PREHEADERS is set in FLAGS, we force the preheader block
|
||||
to be a fallthru predecessor to the loop header and to have only
|
||||
predecessors from outside of the loop.
|
||||
The function also updates dominators. */
|
||||
|
||||
basic_block
|
||||
@ -1131,13 +1148,27 @@ create_preheader (struct loop *loop, int flags)
|
||||
gcc_assert (nentry);
|
||||
if (nentry == 1)
|
||||
{
|
||||
if (/* We do not allow entry block to be the loop preheader, since we
|
||||
bool need_forwarder_block = false;
|
||||
|
||||
/* We do not allow entry block to be the loop preheader, since we
|
||||
cannot emit code there. */
|
||||
single_entry->src != ENTRY_BLOCK_PTR
|
||||
/* If we want simple preheaders, also force the preheader to have
|
||||
just a single successor. */
|
||||
&& !((flags & CP_SIMPLE_PREHEADERS)
|
||||
&& !single_succ_p (single_entry->src)))
|
||||
if (single_entry->src == ENTRY_BLOCK_PTR)
|
||||
need_forwarder_block = true;
|
||||
else
|
||||
{
|
||||
/* If we want simple preheaders, also force the preheader to have
|
||||
just a single successor. */
|
||||
if ((flags & CP_SIMPLE_PREHEADERS)
|
||||
&& !single_succ_p (single_entry->src))
|
||||
need_forwarder_block = true;
|
||||
/* If we want fallthru preheaders, also create forwarder block when
|
||||
preheader ends with a jump or has predecessors from loop. */
|
||||
else if ((flags & CP_FALLTHRU_PREHEADERS)
|
||||
&& (JUMP_P (BB_END (single_entry->src))
|
||||
|| has_preds_from_loop (single_entry->src, loop)))
|
||||
need_forwarder_block = true;
|
||||
}
|
||||
if (! need_forwarder_block)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1174,6 +1205,10 @@ create_preheader (struct loop *loop, int flags)
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Created preheader block for loop %i\n",
|
||||
loop->num);
|
||||
|
||||
if (flags & CP_FALLTHRU_PREHEADERS)
|
||||
gcc_assert ((single_succ_edge (dummy)->flags & EDGE_FALLTHRU)
|
||||
&& !JUMP_P (BB_END (dummy)));
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
@ -962,6 +962,29 @@ fschedule-insns2
|
||||
Common Report Var(flag_schedule_insns_after_reload) Optimization
|
||||
Reschedule instructions after register allocation
|
||||
|
||||
; This flag should be on when a target implements non-trivial
|
||||
; scheduling hooks, maybe saving some information for its own sake.
|
||||
; On IA64, for example, this is used for correct bundling.
|
||||
fselective-scheduling
|
||||
Common Report Var(flag_selective_scheduling) Optimization
|
||||
Schedule instructions using selective scheduling algorithm
|
||||
|
||||
fselective-scheduling2
|
||||
Common Report Var(flag_selective_scheduling2) Optimization
|
||||
Run selective scheduling after reload
|
||||
|
||||
fsel-sched-pipelining
|
||||
Common Report Var(flag_sel_sched_pipelining) Init(0) Optimization
|
||||
Perform software pipelining of inner loops during selective scheduling
|
||||
|
||||
fsel-sched-pipelining-outer-loops
|
||||
Common Report Var(flag_sel_sched_pipelining_outer_loops) Init(0) Optimization
|
||||
Perform software pipelining of outer loops during selective scheduling
|
||||
|
||||
fsel-sched-reschedule-pipelined
|
||||
Common Report Var(flag_sel_sched_reschedule_pipelined) Init(0) Optimization
|
||||
Reschedule pipelined regions without pipelining
|
||||
|
||||
; sched_stalled_insns means that insns can be moved prematurely from the queue
|
||||
; of stalled insns into the ready list.
|
||||
fsched-stalled-insns
|
||||
|
@ -382,8 +382,8 @@ static const struct attribute_spec ia64_attribute_table[] =
|
||||
#undef TARGET_SCHED_NEEDS_BLOCK_P
|
||||
#define TARGET_SCHED_NEEDS_BLOCK_P ia64_needs_block_p
|
||||
|
||||
#undef TARGET_SCHED_GEN_CHECK
|
||||
#define TARGET_SCHED_GEN_CHECK ia64_gen_check
|
||||
#undef TARGET_SCHED_GEN_SPEC_CHECK
|
||||
#define TARGET_SCHED_GEN_SPEC_CHECK ia64_gen_check
|
||||
|
||||
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC\
|
||||
@ -6278,10 +6278,6 @@ static rtx dfa_stop_insn;
|
||||
|
||||
static rtx last_scheduled_insn;
|
||||
|
||||
/* The following variable value is size of the DFA state. */
|
||||
|
||||
static size_t dfa_state_size;
|
||||
|
||||
/* The following variable value is pointer to a DFA state used as
|
||||
temporary variable. */
|
||||
|
||||
|
@ -101,7 +101,7 @@ Target Report Var(mflag_sched_br_data_spec) Init(0)
|
||||
Use data speculation before reload
|
||||
|
||||
msched-ar-data-spec
|
||||
Target Report Var(mflag_sched_ar_data_spec) Init(1)
|
||||
Target Report Var(mflag_sched_ar_data_spec) Init(0)
|
||||
Use data speculation after reload
|
||||
|
||||
msched-control-spec
|
||||
|
@ -857,6 +857,10 @@ static int rs6000_sched_reorder (FILE *, int, rtx *, int *, int);
|
||||
static int rs6000_sched_reorder2 (FILE *, int, rtx *, int *, int);
|
||||
static int rs6000_use_sched_lookahead (void);
|
||||
static int rs6000_use_sched_lookahead_guard (rtx);
|
||||
static void * rs6000_alloc_sched_context (void);
|
||||
static void rs6000_init_sched_context (void *, bool);
|
||||
static void rs6000_set_sched_context (void *);
|
||||
static void rs6000_free_sched_context (void *);
|
||||
static tree rs6000_builtin_reciprocal (unsigned int, bool, bool);
|
||||
static tree rs6000_builtin_mask_for_load (void);
|
||||
static tree rs6000_builtin_mul_widen_even (tree);
|
||||
@ -1131,6 +1135,15 @@ static const char alt_reg_names[][8] =
|
||||
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD rs6000_use_sched_lookahead_guard
|
||||
|
||||
#undef TARGET_SCHED_ALLOC_SCHED_CONTEXT
|
||||
#define TARGET_SCHED_ALLOC_SCHED_CONTEXT rs6000_alloc_sched_context
|
||||
#undef TARGET_SCHED_INIT_SCHED_CONTEXT
|
||||
#define TARGET_SCHED_INIT_SCHED_CONTEXT rs6000_init_sched_context
|
||||
#undef TARGET_SCHED_SET_SCHED_CONTEXT
|
||||
#define TARGET_SCHED_SET_SCHED_CONTEXT rs6000_set_sched_context
|
||||
#undef TARGET_SCHED_FREE_SCHED_CONTEXT
|
||||
#define TARGET_SCHED_FREE_SCHED_CONTEXT rs6000_free_sched_context
|
||||
|
||||
#undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
|
||||
#define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD rs6000_builtin_mask_for_load
|
||||
#undef TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN
|
||||
@ -19476,7 +19489,8 @@ rs6000_sched_reorder2 (FILE *dump, int sched_verbose, rtx *ready,
|
||||
for (i=pos; i<*pn_ready-1; i++)
|
||||
ready[i] = ready[i + 1];
|
||||
ready[*pn_ready-1] = tmp;
|
||||
if INSN_PRIORITY_KNOWN (tmp)
|
||||
|
||||
if (!sel_sched_p () && INSN_PRIORITY_KNOWN (tmp))
|
||||
INSN_PRIORITY (tmp)++;
|
||||
break;
|
||||
}
|
||||
@ -19493,7 +19507,8 @@ rs6000_sched_reorder2 (FILE *dump, int sched_verbose, rtx *ready,
|
||||
while (pos >= 0)
|
||||
{
|
||||
if (is_load_insn (ready[pos])
|
||||
&& INSN_PRIORITY_KNOWN (ready[pos]))
|
||||
&& !sel_sched_p ()
|
||||
&& INSN_PRIORITY_KNOWN (ready[pos]))
|
||||
{
|
||||
INSN_PRIORITY (ready[pos])++;
|
||||
|
||||
@ -19535,8 +19550,10 @@ rs6000_sched_reorder2 (FILE *dump, int sched_verbose, rtx *ready,
|
||||
for (i=pos; i<*pn_ready-1; i++)
|
||||
ready[i] = ready[i + 1];
|
||||
ready[*pn_ready-1] = tmp;
|
||||
if INSN_PRIORITY_KNOWN (tmp)
|
||||
|
||||
if (!sel_sched_p () && INSN_PRIORITY_KNOWN (tmp))
|
||||
INSN_PRIORITY (tmp)++;
|
||||
|
||||
first_store_pos = -1;
|
||||
|
||||
break;
|
||||
@ -19555,7 +19572,7 @@ rs6000_sched_reorder2 (FILE *dump, int sched_verbose, rtx *ready,
|
||||
for (i=first_store_pos; i<*pn_ready-1; i++)
|
||||
ready[i] = ready[i + 1];
|
||||
ready[*pn_ready-1] = tmp;
|
||||
if INSN_PRIORITY_KNOWN (tmp)
|
||||
if (!sel_sched_p () && INSN_PRIORITY_KNOWN (tmp))
|
||||
INSN_PRIORITY (tmp)++;
|
||||
}
|
||||
}
|
||||
@ -19569,7 +19586,8 @@ rs6000_sched_reorder2 (FILE *dump, int sched_verbose, rtx *ready,
|
||||
while (pos >= 0)
|
||||
{
|
||||
if (is_store_insn (ready[pos])
|
||||
&& INSN_PRIORITY_KNOWN (ready[pos]))
|
||||
&& !sel_sched_p ()
|
||||
&& INSN_PRIORITY_KNOWN (ready[pos]))
|
||||
{
|
||||
INSN_PRIORITY (ready[pos])++;
|
||||
|
||||
@ -20071,7 +20089,7 @@ pad_groups (FILE *dump, int sched_verbose, rtx prev_head_insn, rtx tail)
|
||||
if (group_end)
|
||||
{
|
||||
/* If the scheduler had marked group termination at this location
|
||||
(between insn and next_indn), and neither insn nor next_insn will
|
||||
(between insn and next_insn), and neither insn nor next_insn will
|
||||
force group termination, pad the group with nops to force group
|
||||
termination. */
|
||||
if (can_issue_more
|
||||
@ -20125,6 +20143,10 @@ rs6000_sched_finish (FILE *dump, int sched_verbose)
|
||||
|
||||
if (reload_completed && rs6000_sched_groups)
|
||||
{
|
||||
/* Do not run sched_finish hook when selective scheduling enabled. */
|
||||
if (sel_sched_p ())
|
||||
return;
|
||||
|
||||
if (rs6000_sched_insert_nops == sched_finish_none)
|
||||
return;
|
||||
|
||||
@ -20145,6 +20167,67 @@ rs6000_sched_finish (FILE *dump, int sched_verbose)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct _rs6000_sched_context
|
||||
{
|
||||
short cached_can_issue_more;
|
||||
rtx last_scheduled_insn;
|
||||
int load_store_pendulum;
|
||||
};
|
||||
|
||||
typedef struct _rs6000_sched_context rs6000_sched_context_def;
|
||||
typedef rs6000_sched_context_def *rs6000_sched_context_t;
|
||||
|
||||
/* Allocate store for new scheduling context. */
|
||||
static void *
|
||||
rs6000_alloc_sched_context (void)
|
||||
{
|
||||
return xmalloc (sizeof (rs6000_sched_context_def));
|
||||
}
|
||||
|
||||
/* If CLEAN_P is true then initializes _SC with clean data,
|
||||
and from the global context otherwise. */
|
||||
static void
|
||||
rs6000_init_sched_context (void *_sc, bool clean_p)
|
||||
{
|
||||
rs6000_sched_context_t sc = (rs6000_sched_context_t) _sc;
|
||||
|
||||
if (clean_p)
|
||||
{
|
||||
sc->cached_can_issue_more = 0;
|
||||
sc->last_scheduled_insn = NULL_RTX;
|
||||
sc->load_store_pendulum = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc->cached_can_issue_more = cached_can_issue_more;
|
||||
sc->last_scheduled_insn = last_scheduled_insn;
|
||||
sc->load_store_pendulum = load_store_pendulum;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sets the global scheduling context to the one pointed to by _SC. */
|
||||
static void
|
||||
rs6000_set_sched_context (void *_sc)
|
||||
{
|
||||
rs6000_sched_context_t sc = (rs6000_sched_context_t) _sc;
|
||||
|
||||
gcc_assert (sc != NULL);
|
||||
|
||||
cached_can_issue_more = sc->cached_can_issue_more;
|
||||
last_scheduled_insn = sc->last_scheduled_insn;
|
||||
load_store_pendulum = sc->load_store_pendulum;
|
||||
}
|
||||
|
||||
/* Free _SC. */
|
||||
static void
|
||||
rs6000_free_sched_context (void *_sc)
|
||||
{
|
||||
gcc_assert (_sc != NULL);
|
||||
|
||||
free (_sc);
|
||||
}
|
||||
|
||||
|
||||
/* Length in units of the trampoline for entering a nested function. */
|
||||
|
||||
|
96
gcc/cse.c
96
gcc/cse.c
@ -574,7 +574,7 @@ static rtx use_related_value (rtx, struct table_elt *);
|
||||
|
||||
static inline unsigned canon_hash (rtx, enum machine_mode);
|
||||
static inline unsigned safe_hash (rtx, enum machine_mode);
|
||||
static unsigned hash_rtx_string (const char *);
|
||||
static inline unsigned hash_rtx_string (const char *);
|
||||
|
||||
static rtx canon_reg (rtx, rtx);
|
||||
static enum rtx_code find_comparison_args (enum rtx_code, rtx *, rtx *,
|
||||
@ -2044,6 +2044,7 @@ use_related_value (rtx x, struct table_elt *elt)
|
||||
return plus_constant (q->exp, offset);
|
||||
}
|
||||
|
||||
|
||||
/* Hash a string. Just add its bytes up. */
|
||||
static inline unsigned
|
||||
hash_rtx_string (const char *ps)
|
||||
@ -2058,27 +2059,20 @@ hash_rtx_string (const char *ps)
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* Hash an rtx. We are careful to make sure the value is never negative.
|
||||
Equivalent registers hash identically.
|
||||
MODE is used in hashing for CONST_INTs only;
|
||||
otherwise the mode of X is used.
|
||||
|
||||
Store 1 in DO_NOT_RECORD_P if any subexpression is volatile.
|
||||
|
||||
If HASH_ARG_IN_MEMORY_P is not NULL, store 1 in it if X contains
|
||||
a MEM rtx which does not have the RTX_UNCHANGING_P bit set.
|
||||
|
||||
Note that cse_insn knows that the hash code of a MEM expression
|
||||
is just (int) MEM plus the hash code of the address. */
|
||||
/* Same as hash_rtx, but call CB on each rtx if it is not NULL.
|
||||
When the callback returns true, we continue with the new rtx. */
|
||||
|
||||
unsigned
|
||||
hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
int *hash_arg_in_memory_p, bool have_reg_qty)
|
||||
hash_rtx_cb (const_rtx x, enum machine_mode mode,
|
||||
int *do_not_record_p, int *hash_arg_in_memory_p,
|
||||
bool have_reg_qty, hash_rtx_callback_function cb)
|
||||
{
|
||||
int i, j;
|
||||
unsigned hash = 0;
|
||||
enum rtx_code code;
|
||||
const char *fmt;
|
||||
enum machine_mode newmode;
|
||||
rtx newx;
|
||||
|
||||
/* Used to turn recursion into iteration. We can't rely on GCC's
|
||||
tail-recursion elimination since we need to keep accumulating values
|
||||
@ -2087,6 +2081,15 @@ hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
if (x == 0)
|
||||
return hash;
|
||||
|
||||
/* Invoke the callback first. */
|
||||
if (cb != NULL
|
||||
&& ((*cb) (x, mode, &newx, &newmode)))
|
||||
{
|
||||
hash += hash_rtx_cb (newx, newmode, do_not_record_p,
|
||||
hash_arg_in_memory_p, have_reg_qty, cb);
|
||||
return hash;
|
||||
}
|
||||
|
||||
code = GET_CODE (x);
|
||||
switch (code)
|
||||
{
|
||||
@ -2094,7 +2097,7 @@ hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
{
|
||||
unsigned int regno = REGNO (x);
|
||||
|
||||
if (!reload_completed)
|
||||
if (do_not_record_p && !reload_completed)
|
||||
{
|
||||
/* On some machines, we can't record any non-fixed hard register,
|
||||
because extending its life will cause reload problems. We
|
||||
@ -2188,8 +2191,9 @@ hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
for (i = 0; i < units; ++i)
|
||||
{
|
||||
elt = CONST_VECTOR_ELT (x, i);
|
||||
hash += hash_rtx (elt, GET_MODE (elt), do_not_record_p,
|
||||
hash_arg_in_memory_p, have_reg_qty);
|
||||
hash += hash_rtx_cb (elt, GET_MODE (elt),
|
||||
do_not_record_p, hash_arg_in_memory_p,
|
||||
have_reg_qty, cb);
|
||||
}
|
||||
|
||||
return hash;
|
||||
@ -2223,7 +2227,7 @@ hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
case MEM:
|
||||
/* We don't record if marked volatile or if BLKmode since we don't
|
||||
know the size of the move. */
|
||||
if (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode)
|
||||
if (do_not_record_p && (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
|
||||
{
|
||||
*do_not_record_p = 1;
|
||||
return 0;
|
||||
@ -2270,11 +2274,16 @@ hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
case CC0:
|
||||
case CALL:
|
||||
case UNSPEC_VOLATILE:
|
||||
*do_not_record_p = 1;
|
||||
return 0;
|
||||
if (do_not_record_p) {
|
||||
*do_not_record_p = 1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return hash;
|
||||
break;
|
||||
|
||||
case ASM_OPERANDS:
|
||||
if (MEM_VOLATILE_P (x))
|
||||
if (do_not_record_p && MEM_VOLATILE_P (x))
|
||||
{
|
||||
*do_not_record_p = 1;
|
||||
return 0;
|
||||
@ -2291,12 +2300,12 @@ hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
{
|
||||
for (i = 1; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
|
||||
{
|
||||
hash += (hash_rtx (ASM_OPERANDS_INPUT (x, i),
|
||||
GET_MODE (ASM_OPERANDS_INPUT (x, i)),
|
||||
do_not_record_p, hash_arg_in_memory_p,
|
||||
have_reg_qty)
|
||||
hash += (hash_rtx_cb (ASM_OPERANDS_INPUT (x, i),
|
||||
GET_MODE (ASM_OPERANDS_INPUT (x, i)),
|
||||
do_not_record_p, hash_arg_in_memory_p,
|
||||
have_reg_qty, cb)
|
||||
+ hash_rtx_string
|
||||
(ASM_OPERANDS_INPUT_CONSTRAINT (x, i)));
|
||||
(ASM_OPERANDS_INPUT_CONSTRAINT (x, i)));
|
||||
}
|
||||
|
||||
hash += hash_rtx_string (ASM_OPERANDS_INPUT_CONSTRAINT (x, 0));
|
||||
@ -2329,15 +2338,17 @@ hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
x = XEXP (x, i);
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
hash += hash_rtx (XEXP (x, i), 0, do_not_record_p,
|
||||
hash_arg_in_memory_p, have_reg_qty);
|
||||
|
||||
hash += hash_rtx_cb (XEXP (x, i), 0, do_not_record_p,
|
||||
hash_arg_in_memory_p,
|
||||
have_reg_qty, cb);
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
for (j = 0; j < XVECLEN (x, i); j++)
|
||||
hash += hash_rtx (XVECEXP (x, i, j), 0, do_not_record_p,
|
||||
hash_arg_in_memory_p, have_reg_qty);
|
||||
hash += hash_rtx_cb (XVECEXP (x, i, j), 0, do_not_record_p,
|
||||
hash_arg_in_memory_p,
|
||||
have_reg_qty, cb);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
@ -2360,6 +2371,27 @@ hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* Hash an rtx. We are careful to make sure the value is never negative.
|
||||
Equivalent registers hash identically.
|
||||
MODE is used in hashing for CONST_INTs only;
|
||||
otherwise the mode of X is used.
|
||||
|
||||
Store 1 in DO_NOT_RECORD_P if any subexpression is volatile.
|
||||
|
||||
If HASH_ARG_IN_MEMORY_P is not NULL, store 1 in it if X contains
|
||||
a MEM rtx which does not have the RTX_UNCHANGING_P bit set.
|
||||
|
||||
Note that cse_insn knows that the hash code of a MEM expression
|
||||
is just (int) MEM plus the hash code of the address. */
|
||||
|
||||
unsigned
|
||||
hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
|
||||
int *hash_arg_in_memory_p, bool have_reg_qty)
|
||||
{
|
||||
return hash_rtx_cb (x, mode, do_not_record_p,
|
||||
hash_arg_in_memory_p, have_reg_qty, NULL);
|
||||
}
|
||||
|
||||
/* Hash an rtx X for cse via hash_rtx.
|
||||
Stores 1 in do_not_record if any subexpression is volatile.
|
||||
Stores 1 in hash_arg_in_memory if X contains a mem rtx which
|
||||
|
@ -172,6 +172,9 @@ DEBUG_COUNTER (sched_block)
|
||||
DEBUG_COUNTER (sched_func)
|
||||
DEBUG_COUNTER (sched_insn)
|
||||
DEBUG_COUNTER (sched_region)
|
||||
DEBUG_COUNTER (sel_sched_cnt)
|
||||
DEBUG_COUNTER (sel_sched_region_cnt)
|
||||
DEBUG_COUNTER (sel_sched_insn_cnt)
|
||||
DEBUG_COUNTER (sms_sched_loop)
|
||||
DEBUG_COUNTER (split_for_sched2)
|
||||
DEBUG_COUNTER (tail_call)
|
||||
|
@ -303,6 +303,7 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-feliminate-unused-debug-symbols -femit-class-debug-always @gol
|
||||
-fmem-report -fpre-ipa-mem-report -fpost-ipa-mem-report -fprofile-arcs @gol
|
||||
-frandom-seed=@var{string} -fsched-verbose=@var{n} @gol
|
||||
-fsel-sched-verbose -fsel-sched-dump-cfg -fsel-sched-pipelining-verbose @gol
|
||||
-ftest-coverage -ftime-report -fvar-tracking @gol
|
||||
-g -g@var{level} -gcoff -gdwarf-2 @gol
|
||||
-ggdb -gstabs -gstabs+ -gvms -gxcoff -gxcoff+ @gol
|
||||
@ -356,6 +357,8 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-fsched2-use-traces -fsched-spec-load -fsched-spec-load-dangerous @gol
|
||||
-fsched-stalled-insns-dep[=@var{n}] -fsched-stalled-insns[=@var{n}] @gol
|
||||
-fschedule-insns -fschedule-insns2 -fsection-anchors -fsee @gol
|
||||
-fselective-scheduling -fselective-scheduling2 @gol
|
||||
-fsel-sched-pipelining -fsel-sched-pipelining-outer-loops @gol
|
||||
-fsignaling-nans -fsingle-precision-constant -fsplit-ivs-in-unroller @gol
|
||||
-fsplit-wide-types -fstack-protector -fstack-protector-all @gol
|
||||
-fstrict-aliasing -fstrict-overflow -fthread-jumps -ftracer @gol
|
||||
@ -5829,6 +5832,27 @@ The modulo scheduling comes before the traditional scheduling, if a loop
|
||||
was modulo scheduled we may want to prevent the later scheduling passes
|
||||
from changing its schedule, we use this option to control that.
|
||||
|
||||
@item -fselective-scheduling
|
||||
@opindex fselective-scheduling
|
||||
Schedule instructions using selective scheduling algorithm. Selective
|
||||
scheduling runs instead of the first scheduler pass.
|
||||
|
||||
@item -fselective-scheduling2
|
||||
@opindex fselective-scheduling2
|
||||
Schedule instructions using selective scheduling algorithm. Selective
|
||||
scheduling runs instead of the second scheduler pass.
|
||||
|
||||
@item -fsel-sched-pipelining
|
||||
@opindex fsel-sched-pipelining
|
||||
Enable software pipelining of innermost loops during selective scheduling.
|
||||
This option has no effect until one of @option{-fselective-scheduling} or
|
||||
@option{-fselective-scheduling2} is turned on.
|
||||
|
||||
@item -fsel-sched-pipelining-outer-loops
|
||||
@opindex fsel-sched-pipelining-outer-loops
|
||||
When pipelining loops during selective scheduling, also pipeline outer loops.
|
||||
This option has no effect until @option{-fsel-sched-pipelining} is turned on.
|
||||
|
||||
@item -fcaller-saves
|
||||
@opindex fcaller-saves
|
||||
Enable values to be allocated in registers that will be clobbered by
|
||||
@ -7325,10 +7349,18 @@ with probably little benefit. The default value is 100.
|
||||
The maximum number of blocks in a region to be considered for
|
||||
interblock scheduling. The default value is 10.
|
||||
|
||||
@item max-pipeline-region-blocks
|
||||
The maximum number of blocks in a region to be considered for
|
||||
pipelining in the selective scheduler. The default value is 15.
|
||||
|
||||
@item max-sched-region-insns
|
||||
The maximum number of insns in a region to be considered for
|
||||
interblock scheduling. The default value is 100.
|
||||
|
||||
@item max-pipeline-region-insns
|
||||
The maximum number of insns in a region to be considered for
|
||||
pipelining in the selective scheduler. The default value is 200.
|
||||
|
||||
@item min-spec-prob
|
||||
The minimum probability (in percents) of reaching a source block
|
||||
for interblock speculative scheduling. The default value is 40.
|
||||
@ -7348,8 +7380,25 @@ The minimal probability of speculation success (in percents), so that
|
||||
speculative insn will be scheduled.
|
||||
The default value is 40.
|
||||
|
||||
@item max-last-value-rtl
|
||||
@item sched-mem-true-dep-cost
|
||||
Minimal distance (in CPU cycles) between store and load targeting same
|
||||
memory locations. The default value is 1.
|
||||
|
||||
@item selsched-max-lookahead
|
||||
The maximum size of the lookahead window of selective scheduling. It is a
|
||||
depth of search for available instructions.
|
||||
The default value is 50.
|
||||
|
||||
@item selsched-max-sched-times
|
||||
The maximum number of times that an instruction will be scheduled during
|
||||
selective scheduling. This is the limit on the number of iterations
|
||||
through which the instruction may be pipelined. The default value is 2.
|
||||
|
||||
@item selsched-max-insns-to-rename
|
||||
The maximum number of best instructions in the ready list that are considered
|
||||
for renaming in the selective scheduler. The default value is 2.
|
||||
|
||||
@item max-last-value-rtl
|
||||
The maximum size measured as number of RTLs that can be recorded in an expression
|
||||
in combiner for a pseudo register as last known value of that register. The default
|
||||
is 10000.
|
||||
|
@ -6356,6 +6356,29 @@ the instruction stream. The hook notifies a target backend to extend its
|
||||
per instruction data structures.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void * TARGET_SCHED_ALLOC_SCHED_CONTEXT (void)
|
||||
Return a pointer to a store large enough to hold target scheduling context.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_SCHED_INIT_SCHED_CONTEXT (void *@var{tc}, bool @var{clean_p})
|
||||
Initialize store pointed to by @var{tc} to hold target scheduling context.
|
||||
It @var{clean_p} is true then initialize @var{tc} as if scheduler is at the
|
||||
beginning of the block. Overwise, make a copy of the current context in
|
||||
@var{tc}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_SCHED_SET_SCHED_CONTEXT (void *@var{tc})
|
||||
Copy target scheduling context pointer to by @var{tc} to the current context.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_SCHED_CLEAR_SCHED_CONTEXT (void *@var{tc})
|
||||
Deallocate internal data in target scheduling context pointed to by @var{tc}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_SCHED_FREE_SCHED_CONTEXT (void *@var{tc})
|
||||
Deallocate a store for target scheduling context pointed to by @var{tc}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} int TARGET_SCHED_SPECULATE_INSN (rtx @var{insn}, int @var{request}, rtx *@var{new_pat})
|
||||
This hook is called by the insn scheduler when @var{insn} has only
|
||||
speculative dependencies and therefore can be scheduled speculatively.
|
||||
|
@ -3985,6 +3985,7 @@ emit_insn_after_1 (rtx first, rtx after, basic_block bb)
|
||||
|
||||
if (after == last_insn)
|
||||
last_insn = last;
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
|
@ -664,7 +664,7 @@ insn_current_reference_address (rtx branch)
|
||||
/* Compute branch alignments based on frequency information in the
|
||||
CFG. */
|
||||
|
||||
static unsigned int
|
||||
unsigned int
|
||||
compute_alignments (void)
|
||||
{
|
||||
int log, max_skip, max_log;
|
||||
@ -784,7 +784,10 @@ compute_alignments (void)
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
loop_optimizer_finalize ();
|
||||
{
|
||||
loop_optimizer_finalize ();
|
||||
free_dominance_info (CDI_DOMINATORS);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -228,6 +228,9 @@ extern int flag_evaluation_order;
|
||||
extern unsigned HOST_WIDE_INT g_switch_value;
|
||||
extern bool g_switch_set;
|
||||
|
||||
/* Same for selective scheduling. */
|
||||
extern bool sel_sched_switch_set;
|
||||
|
||||
/* Values of the -falign-* flags: how much to align labels in code.
|
||||
0 means `use default', 1 means `don't align'.
|
||||
For each variable, there is an _log variant which is the power
|
||||
|
@ -184,6 +184,10 @@ main (int argc, char **argv)
|
||||
printf (" Use the function if bypass_p returns nonzero for\n");
|
||||
printf (" the 1st insn. */\n");
|
||||
printf ("extern int insn_latency (rtx, rtx);\n\n");
|
||||
printf ("/* Maximal insn latency time possible of all bypasses for this insn.\n");
|
||||
printf (" Use the function if bypass_p returns nonzero for\n");
|
||||
printf (" the 1st insn. */\n");
|
||||
printf ("extern int maximal_insn_latency (rtx);\n\n");
|
||||
printf ("\n#if AUTOMATON_ALTS\n");
|
||||
printf ("/* The following function returns number of alternative\n");
|
||||
printf (" reservations of given insn. It may be used for better\n");
|
||||
|
@ -8076,13 +8076,13 @@ output_min_insn_conflict_delay_func (void)
|
||||
fprintf (output_file, "}\n\n");
|
||||
}
|
||||
|
||||
/* Output function `internal_insn_latency'. */
|
||||
/* Output the array holding default latency values. These are used in
|
||||
insn_latency and maximal_insn_latency function implementations. */
|
||||
static void
|
||||
output_internal_insn_latency_func (void)
|
||||
output_default_latencies (void)
|
||||
{
|
||||
decl_t decl;
|
||||
struct bypass_decl *bypass;
|
||||
int i, j, col;
|
||||
decl_t decl;
|
||||
const char *tabletype = "unsigned char";
|
||||
|
||||
/* Find the smallest integer type that can hold all the default
|
||||
@ -8098,18 +8098,6 @@ output_internal_insn_latency_func (void)
|
||||
tabletype = "int";
|
||||
}
|
||||
|
||||
fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
|
||||
INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
|
||||
INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
|
||||
INSN2_PARAMETER_NAME);
|
||||
fprintf (output_file, "{\n");
|
||||
|
||||
if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
|
||||
{
|
||||
fputs (" return 0;\n}\n\n", output_file);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf (output_file, " static const %s default_latencies[] =\n {",
|
||||
tabletype);
|
||||
|
||||
@ -8126,6 +8114,27 @@ output_internal_insn_latency_func (void)
|
||||
}
|
||||
gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
|
||||
fputs ("\n };\n", output_file);
|
||||
}
|
||||
|
||||
/* Output function `internal_insn_latency'. */
|
||||
static void
|
||||
output_internal_insn_latency_func (void)
|
||||
{
|
||||
int i;
|
||||
decl_t decl;
|
||||
struct bypass_decl *bypass;
|
||||
|
||||
fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
|
||||
INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
|
||||
INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
|
||||
INSN2_PARAMETER_NAME);
|
||||
fprintf (output_file, "{\n");
|
||||
|
||||
if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
|
||||
{
|
||||
fputs (" return 0;\n}\n\n", output_file);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
|
||||
INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
|
||||
@ -8171,6 +8180,50 @@ output_internal_insn_latency_func (void)
|
||||
INTERNAL_INSN_CODE_NAME);
|
||||
}
|
||||
|
||||
/* Output function `internal_maximum_insn_latency'. */
|
||||
static void
|
||||
output_internal_maximal_insn_latency_func (void)
|
||||
{
|
||||
decl_t decl;
|
||||
struct bypass_decl *bypass;
|
||||
int i;
|
||||
int max;
|
||||
|
||||
fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
|
||||
"internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
|
||||
INSN_PARAMETER_NAME);
|
||||
fprintf (output_file, "{\n");
|
||||
|
||||
if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
|
||||
{
|
||||
fputs (" return 0;\n}\n\n", output_file);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
|
||||
for (i = 0; i < description->decls_num; i++)
|
||||
if (description->decls[i]->mode == dm_insn_reserv
|
||||
&& DECL_INSN_RESERV (description->decls[i])->bypass_list)
|
||||
{
|
||||
decl = description->decls [i];
|
||||
max = DECL_INSN_RESERV (decl)->default_latency;
|
||||
fprintf (output_file,
|
||||
" case %d: {",
|
||||
DECL_INSN_RESERV (decl)->insn_num);
|
||||
for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
|
||||
bypass != NULL;
|
||||
bypass = bypass->next)
|
||||
{
|
||||
if (bypass->latency > max)
|
||||
max = bypass->latency;
|
||||
}
|
||||
fprintf (output_file, " return %d; }\n break;\n", max);
|
||||
}
|
||||
|
||||
fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
|
||||
INTERNAL_INSN_CODE_NAME);
|
||||
}
|
||||
|
||||
/* The function outputs PHR interface function `insn_latency'. */
|
||||
static void
|
||||
output_insn_latency_func (void)
|
||||
@ -8189,6 +8242,21 @@ output_insn_latency_func (void)
|
||||
INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
|
||||
}
|
||||
|
||||
/* The function outputs PHR interface function `maximal_insn_latency'. */
|
||||
static void
|
||||
output_maximal_insn_latency_func (void)
|
||||
{
|
||||
fprintf (output_file, "int\n%s (rtx %s)\n",
|
||||
"maximal_insn_latency", INSN_PARAMETER_NAME);
|
||||
fprintf (output_file, "{\n int %s;\n",
|
||||
INTERNAL_INSN_CODE_NAME);
|
||||
output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
|
||||
INTERNAL_INSN_CODE_NAME, 0);
|
||||
fprintf (output_file, " return %s (%s, %s);\n}\n\n",
|
||||
"internal_maximal_insn_latency",
|
||||
INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
|
||||
}
|
||||
|
||||
/* The function outputs PHR interface function `print_reservation'. */
|
||||
static void
|
||||
output_print_reservation_func (void)
|
||||
@ -9179,8 +9247,11 @@ write_automata (void)
|
||||
output_internal_reset_func ();
|
||||
output_reset_func ();
|
||||
output_min_insn_conflict_delay_func ();
|
||||
output_default_latencies ();
|
||||
output_internal_insn_latency_func ();
|
||||
output_insn_latency_func ();
|
||||
output_internal_maximal_insn_latency_func ();
|
||||
output_maximal_insn_latency_func ();
|
||||
output_print_reservation_func ();
|
||||
/* Output function get_cpu_unit_code. */
|
||||
fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
|
||||
|
1609
gcc/haifa-sched.c
1609
gcc/haifa-sched.c
File diff suppressed because it is too large
Load Diff
@ -89,6 +89,8 @@ typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS];
|
||||
hard_reg_set_intersect_p (X, Y), which returns true if X and Y intersect.
|
||||
hard_reg_set_empty_p (X), which returns true if X is empty. */
|
||||
|
||||
#define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT)
|
||||
|
||||
#ifdef HARD_REG_SET
|
||||
|
||||
#define SET_HARD_REG_BIT(SET, BIT) \
|
||||
@ -135,8 +137,6 @@ hard_reg_set_empty_p (const HARD_REG_SET x)
|
||||
|
||||
#else
|
||||
|
||||
#define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT)
|
||||
|
||||
#define SET_HARD_REG_BIT(SET, BIT) \
|
||||
((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \
|
||||
|= HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT))
|
||||
@ -479,6 +479,100 @@ hard_reg_set_empty_p (const HARD_REG_SET x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Iterator for hard register sets. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Pointer to the current element. */
|
||||
HARD_REG_ELT_TYPE *pelt;
|
||||
|
||||
/* The length of the set. */
|
||||
unsigned short length;
|
||||
|
||||
/* Word within the current element. */
|
||||
unsigned short word_no;
|
||||
|
||||
/* Contents of the actually processed word. When finding next bit
|
||||
it is shifted right, so that the actual bit is always the least
|
||||
significant bit of ACTUAL. */
|
||||
HARD_REG_ELT_TYPE bits;
|
||||
} hard_reg_set_iterator;
|
||||
|
||||
#define HARD_REG_ELT_BITS UHOST_BITS_PER_WIDE_INT
|
||||
|
||||
/* The implementation of the iterator functions is fully analogous to
|
||||
the bitmap iterators. */
|
||||
static inline void
|
||||
hard_reg_set_iter_init (hard_reg_set_iterator *iter, HARD_REG_SET set,
|
||||
unsigned min, unsigned *regno)
|
||||
{
|
||||
#ifdef HARD_REG_SET_LONGS
|
||||
iter->pelt = set;
|
||||
iter->length = HARD_REG_SET_LONGS;
|
||||
#else
|
||||
iter->pelt = &set;
|
||||
iter->length = 1;
|
||||
#endif
|
||||
iter->word_no = min / HARD_REG_ELT_BITS;
|
||||
if (iter->word_no < iter->length)
|
||||
{
|
||||
iter->bits = iter->pelt[iter->word_no];
|
||||
iter->bits >>= min % HARD_REG_ELT_BITS;
|
||||
|
||||
/* This is required for correct search of the next bit. */
|
||||
min += !iter->bits;
|
||||
}
|
||||
*regno = min;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hard_reg_set_iter_set (hard_reg_set_iterator *iter, unsigned *regno)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
/* Return false when we're advanced past the end of the set. */
|
||||
if (iter->word_no >= iter->length)
|
||||
return false;
|
||||
|
||||
if (iter->bits)
|
||||
{
|
||||
/* Find the correct bit and return it. */
|
||||
while (!(iter->bits & 1))
|
||||
{
|
||||
iter->bits >>= 1;
|
||||
*regno += 1;
|
||||
}
|
||||
return (*regno < FIRST_PSEUDO_REGISTER);
|
||||
}
|
||||
|
||||
/* Round to the beginning of the next word. */
|
||||
*regno = (*regno + HARD_REG_ELT_BITS - 1);
|
||||
*regno -= *regno % HARD_REG_ELT_BITS;
|
||||
|
||||
/* Find the next non-zero word. */
|
||||
while (++iter->word_no < iter->length)
|
||||
{
|
||||
iter->bits = iter->pelt[iter->word_no];
|
||||
if (iter->bits)
|
||||
break;
|
||||
*regno += HARD_REG_ELT_BITS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno)
|
||||
{
|
||||
iter->bits >>= 1;
|
||||
*regno += 1;
|
||||
}
|
||||
|
||||
#define EXECUTE_IF_SET_IN_HARD_REG_SET(SET, MIN, REGNUM, ITER) \
|
||||
for (hard_reg_set_iter_init (&(ITER), (SET), (MIN), &(REGNUM)); \
|
||||
hard_reg_set_iter_set (&(ITER), &(REGNUM)); \
|
||||
hard_reg_set_iter_next (&(ITER), &(REGNUM)))
|
||||
|
||||
|
||||
/* Define some standard sets of registers. */
|
||||
|
||||
/* Indexed by hard register number, contains 1 for registers
|
||||
|
26
gcc/lists.c
26
gcc/lists.c
@ -188,4 +188,30 @@ remove_free_INSN_LIST_elem (rtx elem, rtx *listp)
|
||||
free_INSN_LIST_node (remove_list_elem (elem, listp));
|
||||
}
|
||||
|
||||
/* Remove and free the first node in the INSN_LIST pointed to by LISTP. */
|
||||
rtx
|
||||
remove_free_INSN_LIST_node (rtx *listp)
|
||||
{
|
||||
rtx node = *listp;
|
||||
rtx elem = XEXP (node, 0);
|
||||
|
||||
remove_list_node (listp);
|
||||
free_INSN_LIST_node (node);
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
/* Remove and free the first node in the EXPR_LIST pointed to by LISTP. */
|
||||
rtx
|
||||
remove_free_EXPR_LIST_node (rtx *listp)
|
||||
{
|
||||
rtx node = *listp;
|
||||
rtx elem = XEXP (node, 0);
|
||||
|
||||
remove_list_node (listp);
|
||||
free_EXPR_LIST_node (node);
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
#include "gt-lists.h"
|
||||
|
@ -66,7 +66,14 @@ loop_optimizer_init (unsigned flags)
|
||||
|
||||
/* Create pre-headers. */
|
||||
if (flags & LOOPS_HAVE_PREHEADERS)
|
||||
create_preheaders (CP_SIMPLE_PREHEADERS);
|
||||
{
|
||||
int cp_flags = CP_SIMPLE_PREHEADERS;
|
||||
|
||||
if (flags & LOOPS_HAVE_FALLTHRU_PREHEADERS)
|
||||
cp_flags |= CP_FALLTHRU_PREHEADERS;
|
||||
|
||||
create_preheaders (cp_flags);
|
||||
}
|
||||
|
||||
/* Force all latches to have only single successor. */
|
||||
if (flags & LOOPS_HAVE_SIMPLE_LATCHES)
|
||||
@ -118,7 +125,10 @@ loop_optimizer_finalize (void)
|
||||
|
||||
/* Checking. */
|
||||
#ifdef ENABLE_CHECKING
|
||||
verify_flow_info ();
|
||||
/* FIXME: no point to verify flow info after bundling on ia64. Use this
|
||||
hack for achieving this. */
|
||||
if (!reload_completed)
|
||||
verify_flow_info ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -187,13 +187,6 @@ static int compute_split_row (sbitmap, int, int, int, ddg_node_ptr);
|
||||
/* This page defines constants and structures for the modulo scheduling
|
||||
driver. */
|
||||
|
||||
/* As in haifa-sched.c: */
|
||||
/* issue_rate is the number of insns that can be scheduled in the same
|
||||
machine cycle. It can be defined in the config/mach/mach.h file,
|
||||
otherwise we set it to 1. */
|
||||
|
||||
static int issue_rate;
|
||||
|
||||
static int sms_order_nodes (ddg_ptr, int, int *, int *);
|
||||
static void set_node_sched_params (ddg_ptr);
|
||||
static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int, int *);
|
||||
@ -242,7 +235,7 @@ typedef struct node_sched_params
|
||||
code in order to use sched_analyze() for computing the dependencies.
|
||||
They are used when initializing the sched_info structure. */
|
||||
static const char *
|
||||
sms_print_insn (rtx insn, int aligned ATTRIBUTE_UNUSED)
|
||||
sms_print_insn (const_rtx insn, int aligned ATTRIBUTE_UNUSED)
|
||||
{
|
||||
static char tmp[80];
|
||||
|
||||
@ -258,7 +251,17 @@ compute_jump_reg_dependencies (rtx insn ATTRIBUTE_UNUSED,
|
||||
{
|
||||
}
|
||||
|
||||
static struct sched_info sms_sched_info =
|
||||
static struct common_sched_info_def sms_common_sched_info;
|
||||
|
||||
static struct sched_deps_info_def sms_sched_deps_info =
|
||||
{
|
||||
compute_jump_reg_dependencies,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
0, 0, 0
|
||||
};
|
||||
|
||||
static struct haifa_sched_info sms_sched_info =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
@ -267,16 +270,14 @@ static struct sched_info sms_sched_info =
|
||||
NULL,
|
||||
sms_print_insn,
|
||||
NULL,
|
||||
compute_jump_reg_dependencies,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
0, 0, 0,
|
||||
0, 0,
|
||||
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/* Given HEAD and TAIL which are the first and last insns in a loop;
|
||||
return the register which controls the loop. Return zero if it has
|
||||
more than one occurrence in the loop besides the control part or the
|
||||
@ -856,6 +857,19 @@ canon_loop (struct loop *loop)
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup infos. */
|
||||
static void
|
||||
setup_sched_infos (void)
|
||||
{
|
||||
memcpy (&sms_common_sched_info, &haifa_common_sched_info,
|
||||
sizeof (sms_common_sched_info));
|
||||
sms_common_sched_info.sched_pass_id = SCHED_SMS_PASS;
|
||||
common_sched_info = &sms_common_sched_info;
|
||||
|
||||
sched_deps_info = &sms_sched_deps_info;
|
||||
current_sched_info = &sms_sched_info;
|
||||
}
|
||||
|
||||
/* Probability in % that the sms-ed loop rolls enough so that optimized
|
||||
version may be entered. Just a guess. */
|
||||
#define PROB_SMS_ENOUGH_ITERATIONS 80
|
||||
@ -901,16 +915,8 @@ sms_schedule (void)
|
||||
issue_rate = 1;
|
||||
|
||||
/* Initialize the scheduler. */
|
||||
current_sched_info = &sms_sched_info;
|
||||
|
||||
/* Init Data Flow analysis, to be used in interloop dep calculation. */
|
||||
df_set_flags (DF_LR_RUN_DCE);
|
||||
df_rd_add_problem ();
|
||||
df_note_add_problem ();
|
||||
df_chain_add_problem (DF_DU_CHAIN + DF_UD_CHAIN);
|
||||
df_analyze ();
|
||||
regstat_compute_calls_crossed ();
|
||||
sched_init ();
|
||||
setup_sched_infos ();
|
||||
haifa_sched_init ();
|
||||
|
||||
/* Allocate memory to hold the DDG array one entry for each loop.
|
||||
We use loop->num as index into this array. */
|
||||
@ -1242,11 +1248,10 @@ sms_schedule (void)
|
||||
free_ddg (g);
|
||||
}
|
||||
|
||||
regstat_free_calls_crossed ();
|
||||
free (g_arr);
|
||||
|
||||
/* Release scheduler data, needed until now because of DFA. */
|
||||
sched_finish ();
|
||||
haifa_sched_finish ();
|
||||
loop_optimizer_finalize ();
|
||||
}
|
||||
|
||||
|
13
gcc/opts.c
13
gcc/opts.c
@ -47,6 +47,9 @@ along with GCC; see the file COPYING3. If not see
|
||||
unsigned HOST_WIDE_INT g_switch_value;
|
||||
bool g_switch_set;
|
||||
|
||||
/* Same for selective scheduling. */
|
||||
bool sel_sched_switch_set;
|
||||
|
||||
/* True if we should exit after parsing options. */
|
||||
bool exit_after_options;
|
||||
|
||||
@ -1087,6 +1090,11 @@ decode_options (unsigned int argc, const char **argv)
|
||||
flag_reorder_blocks = 1;
|
||||
}
|
||||
|
||||
/* Pipelining of outer loops is only possible when general pipelining
|
||||
capabilities are requested. */
|
||||
if (!flag_sel_sched_pipelining)
|
||||
flag_sel_sched_pipelining_outer_loops = 0;
|
||||
|
||||
#ifndef IRA_COVER_CLASSES
|
||||
if (flag_ira)
|
||||
{
|
||||
@ -1870,6 +1878,11 @@ common_handle_option (size_t scode, const char *arg, int value,
|
||||
set_random_seed (arg);
|
||||
break;
|
||||
|
||||
case OPT_fselective_scheduling:
|
||||
case OPT_fselective_scheduling2:
|
||||
sel_sched_switch_set = true;
|
||||
break;
|
||||
|
||||
case OPT_fsched_verbose_:
|
||||
#ifdef INSN_SCHEDULING
|
||||
fix_sched_param ("verbose", arg);
|
||||
|
@ -557,6 +557,16 @@ DEFPARAM(PARAM_MAX_SCHED_REGION_INSNS,
|
||||
"The maximum number of insns in a region to be considered for interblock scheduling",
|
||||
100, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_MAX_PIPELINE_REGION_BLOCKS,
|
||||
"max-pipeline-region-blocks",
|
||||
"The maximum number of blocks in a region to be considered for interblock scheduling",
|
||||
15, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_MAX_PIPELINE_REGION_INSNS,
|
||||
"max-pipeline-region-insns",
|
||||
"The maximum number of insns in a region to be considered for interblock scheduling",
|
||||
200, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_MIN_SPEC_PROB,
|
||||
"min-spec-prob",
|
||||
"The minimum probability of reaching a source block for interblock speculative scheduling",
|
||||
@ -577,6 +587,26 @@ DEFPARAM(PARAM_SCHED_SPEC_PROB_CUTOFF,
|
||||
"The minimal probability of speculation success (in percents), so that speculative insn will be scheduled.",
|
||||
40, 0, 100)
|
||||
|
||||
DEFPARAM(PARAM_SELSCHED_MAX_LOOKAHEAD,
|
||||
"selsched-max-lookahead",
|
||||
"The maximum size of the lookahead window of selective scheduling",
|
||||
50, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_SELSCHED_MAX_SCHED_TIMES,
|
||||
"selsched-max-sched-times",
|
||||
"Maximum number of times that an insn could be scheduled",
|
||||
2, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_SELSCHED_INSNS_TO_RENAME,
|
||||
"selsched-insns-to-rename",
|
||||
"Maximum number of instructions in the ready list that are considered eligible for renaming",
|
||||
2, 0, 0)
|
||||
|
||||
DEFPARAM (PARAM_SCHED_MEM_TRUE_DEP_COST,
|
||||
"sched-mem-true-dep-cost",
|
||||
"Minimal distance between possibly conflicting store and load",
|
||||
1, 0, 0)
|
||||
|
||||
DEFPARAM(PARAM_MAX_LAST_VALUE_RTL,
|
||||
"max-last-value-rtl",
|
||||
"The maximum number of RTL nodes that can be recorded as combiner's last value",
|
||||
|
199
gcc/recog.c
199
gcc/recog.c
@ -69,7 +69,7 @@ get_attr_enabled (rtx insn ATTRIBUTE_UNUSED)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx);
|
||||
static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx, bool);
|
||||
static void validate_replace_src_1 (rtx *, void *);
|
||||
static rtx split_insn (rtx);
|
||||
|
||||
@ -513,88 +513,17 @@ cancel_changes (int num)
|
||||
num_changes = num;
|
||||
}
|
||||
|
||||
/* Replace every occurrence of FROM in X with TO. Mark each change with
|
||||
validate_change passing OBJECT. */
|
||||
/* A subroutine of validate_replace_rtx_1 that tries to simplify the resulting
|
||||
rtx. */
|
||||
|
||||
static void
|
||||
validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
|
||||
simplify_while_replacing (rtx *loc, rtx to, rtx object,
|
||||
enum machine_mode op0_mode)
|
||||
{
|
||||
int i, j;
|
||||
const char *fmt;
|
||||
rtx x = *loc;
|
||||
enum rtx_code code;
|
||||
enum machine_mode op0_mode = VOIDmode;
|
||||
int prev_changes = num_changes;
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
rtx new_rtx;
|
||||
|
||||
if (!x)
|
||||
return;
|
||||
|
||||
code = GET_CODE (x);
|
||||
fmt = GET_RTX_FORMAT (code);
|
||||
if (fmt[0] == 'e')
|
||||
op0_mode = GET_MODE (XEXP (x, 0));
|
||||
|
||||
/* X matches FROM if it is the same rtx or they are both referring to the
|
||||
same register in the same mode. Avoid calling rtx_equal_p unless the
|
||||
operands look similar. */
|
||||
|
||||
if (x == from
|
||||
|| (REG_P (x) && REG_P (from)
|
||||
&& GET_MODE (x) == GET_MODE (from)
|
||||
&& REGNO (x) == REGNO (from))
|
||||
|| (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
|
||||
&& rtx_equal_p (x, from)))
|
||||
{
|
||||
validate_unshare_change (object, loc, to, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call ourself recursively to perform the replacements.
|
||||
We must not replace inside already replaced expression, otherwise we
|
||||
get infinite recursion for replacements like (reg X)->(subreg (reg X))
|
||||
done by regmove, so we must special case shared ASM_OPERANDS. */
|
||||
|
||||
if (GET_CODE (x) == PARALLEL)
|
||||
{
|
||||
for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
|
||||
{
|
||||
if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
|
||||
&& GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
|
||||
{
|
||||
/* Verify that operands are really shared. */
|
||||
gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0)))
|
||||
== ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP
|
||||
(x, 0, j))));
|
||||
validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
|
||||
from, to, object);
|
||||
}
|
||||
else
|
||||
validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object);
|
||||
}
|
||||
}
|
||||
else
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'e')
|
||||
validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
|
||||
else if (fmt[i] == 'E')
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
|
||||
}
|
||||
|
||||
/* If we didn't substitute, there is nothing more to do. */
|
||||
if (num_changes == prev_changes)
|
||||
return;
|
||||
|
||||
/* Allow substituted expression to have different mode. This is used by
|
||||
regmove to change mode of pseudo register. */
|
||||
if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
|
||||
op0_mode = GET_MODE (XEXP (x, 0));
|
||||
|
||||
/* Do changes needed to keep rtx consistent. Don't do any other
|
||||
simplifications, as it is not our job. */
|
||||
|
||||
if (SWAPPABLE_OPERANDS_P (x)
|
||||
&& swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
|
||||
{
|
||||
@ -715,22 +644,132 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object)
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace every occurrence of FROM in X with TO. Mark each change with
|
||||
validate_change passing OBJECT. */
|
||||
|
||||
static void
|
||||
validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object,
|
||||
bool simplify)
|
||||
{
|
||||
int i, j;
|
||||
const char *fmt;
|
||||
rtx x = *loc;
|
||||
enum rtx_code code;
|
||||
enum machine_mode op0_mode = VOIDmode;
|
||||
int prev_changes = num_changes;
|
||||
|
||||
if (!x)
|
||||
return;
|
||||
|
||||
code = GET_CODE (x);
|
||||
fmt = GET_RTX_FORMAT (code);
|
||||
if (fmt[0] == 'e')
|
||||
op0_mode = GET_MODE (XEXP (x, 0));
|
||||
|
||||
/* X matches FROM if it is the same rtx or they are both referring to the
|
||||
same register in the same mode. Avoid calling rtx_equal_p unless the
|
||||
operands look similar. */
|
||||
|
||||
if (x == from
|
||||
|| (REG_P (x) && REG_P (from)
|
||||
&& GET_MODE (x) == GET_MODE (from)
|
||||
&& REGNO (x) == REGNO (from))
|
||||
|| (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
|
||||
&& rtx_equal_p (x, from)))
|
||||
{
|
||||
validate_unshare_change (object, loc, to, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Call ourself recursively to perform the replacements.
|
||||
We must not replace inside already replaced expression, otherwise we
|
||||
get infinite recursion for replacements like (reg X)->(subreg (reg X))
|
||||
done by regmove, so we must special case shared ASM_OPERANDS. */
|
||||
|
||||
if (GET_CODE (x) == PARALLEL)
|
||||
{
|
||||
for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
|
||||
{
|
||||
if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
|
||||
&& GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
|
||||
{
|
||||
/* Verify that operands are really shared. */
|
||||
gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0)))
|
||||
== ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP
|
||||
(x, 0, j))));
|
||||
validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
|
||||
from, to, object, simplify);
|
||||
}
|
||||
else
|
||||
validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object,
|
||||
simplify);
|
||||
}
|
||||
}
|
||||
else
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'e')
|
||||
validate_replace_rtx_1 (&XEXP (x, i), from, to, object, simplify);
|
||||
else if (fmt[i] == 'E')
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object,
|
||||
simplify);
|
||||
}
|
||||
|
||||
/* If we didn't substitute, there is nothing more to do. */
|
||||
if (num_changes == prev_changes)
|
||||
return;
|
||||
|
||||
/* Allow substituted expression to have different mode. This is used by
|
||||
regmove to change mode of pseudo register. */
|
||||
if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
|
||||
op0_mode = GET_MODE (XEXP (x, 0));
|
||||
|
||||
/* Do changes needed to keep rtx consistent. Don't do any other
|
||||
simplifications, as it is not our job. */
|
||||
if (simplify)
|
||||
simplify_while_replacing (loc, to, object, op0_mode);
|
||||
}
|
||||
|
||||
/* Try replacing every occurrence of FROM in INSN with TO. After all
|
||||
changes have been made, validate by seeing if INSN is still valid. */
|
||||
|
||||
int
|
||||
validate_replace_rtx (rtx from, rtx to, rtx insn)
|
||||
{
|
||||
validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
|
||||
validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
|
||||
return apply_change_group ();
|
||||
}
|
||||
|
||||
/* Try replacing every occurrence of FROM in WHERE with TO. Assume that WHERE
|
||||
is a part of INSN. After all changes have been made, validate by seeing if
|
||||
INSN is still valid.
|
||||
validate_replace_rtx (from, to, insn) is equivalent to
|
||||
validate_replace_rtx_part (from, to, &PATTERN (insn), insn). */
|
||||
|
||||
int
|
||||
validate_replace_rtx_part (rtx from, rtx to, rtx *where, rtx insn)
|
||||
{
|
||||
validate_replace_rtx_1 (where, from, to, insn, true);
|
||||
return apply_change_group ();
|
||||
}
|
||||
|
||||
/* Same as above, but do not simplify rtx afterwards. */
|
||||
int
|
||||
validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where,
|
||||
rtx insn)
|
||||
{
|
||||
validate_replace_rtx_1 (where, from, to, insn, false);
|
||||
return apply_change_group ();
|
||||
|
||||
}
|
||||
|
||||
/* Try replacing every occurrence of FROM in INSN with TO. */
|
||||
|
||||
void
|
||||
validate_replace_rtx_group (rtx from, rtx to, rtx insn)
|
||||
{
|
||||
validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
|
||||
validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
|
||||
}
|
||||
|
||||
/* Function called by note_uses to replace used subexpressions. */
|
||||
@ -747,7 +786,7 @@ validate_replace_src_1 (rtx *x, void *data)
|
||||
struct validate_replace_src_data *d
|
||||
= (struct validate_replace_src_data *) data;
|
||||
|
||||
validate_replace_rtx_1 (x, d->from, d->to, d->insn);
|
||||
validate_replace_rtx_1 (x, d->from, d->to, d->insn, true);
|
||||
}
|
||||
|
||||
/* Try replacing every occurrence of FROM in INSN with TO, avoiding
|
||||
|
@ -87,6 +87,8 @@ extern int constrain_operands_cached (int);
|
||||
extern int memory_address_p (enum machine_mode, rtx);
|
||||
extern int strict_memory_address_p (enum machine_mode, rtx);
|
||||
extern int validate_replace_rtx (rtx, rtx, rtx);
|
||||
extern int validate_replace_rtx_part (rtx, rtx, rtx *, rtx);
|
||||
extern int validate_replace_rtx_part_nosimplify (rtx, rtx, rtx *, rtx);
|
||||
extern void validate_replace_rtx_group (rtx, rtx, rtx);
|
||||
extern void validate_replace_src_group (rtx, rtx, rtx);
|
||||
extern bool validate_simplify_insn (rtx insn);
|
||||
|
27
gcc/rtl.c
27
gcc/rtl.c
@ -333,22 +333,29 @@ int generating_concat_p;
|
||||
int currently_expanding_to_rtl;
|
||||
|
||||
|
||||
/* Return 1 if X and Y are identical-looking rtx's.
|
||||
This is the Lisp function EQUAL for rtx arguments. */
|
||||
|
||||
/* Same as rtx_equal_p, but call CB on each pair of rtx if CB is not NULL.
|
||||
When the callback returns true, we continue with the new pair. */
|
||||
|
||||
int
|
||||
rtx_equal_p (const_rtx x, const_rtx y)
|
||||
rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
enum rtx_code code;
|
||||
const char *fmt;
|
||||
rtx nx, ny;
|
||||
|
||||
if (x == y)
|
||||
return 1;
|
||||
if (x == 0 || y == 0)
|
||||
return 0;
|
||||
|
||||
/* Invoke the callback first. */
|
||||
if (cb != NULL
|
||||
&& ((*cb) (&x, &y, &nx, &ny)))
|
||||
return rtx_equal_p_cb (nx, ny, cb);
|
||||
|
||||
code = GET_CODE (x);
|
||||
/* Rtx's of different codes cannot be equal. */
|
||||
if (code != GET_CODE (y))
|
||||
@ -409,12 +416,13 @@ rtx_equal_p (const_rtx x, const_rtx y)
|
||||
|
||||
/* And the corresponding elements must match. */
|
||||
for (j = 0; j < XVECLEN (x, i); j++)
|
||||
if (rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0)
|
||||
if (rtx_equal_p_cb (XVECEXP (x, i, j),
|
||||
XVECEXP (y, i, j), cb) == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0)
|
||||
if (rtx_equal_p_cb (XEXP (x, i), XEXP (y, i), cb) == 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
@ -444,6 +452,15 @@ rtx_equal_p (const_rtx x, const_rtx y)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return 1 if X and Y are identical-looking rtx's.
|
||||
This is the Lisp function EQUAL for rtx arguments. */
|
||||
|
||||
int
|
||||
rtx_equal_p (const_rtx x, const_rtx y)
|
||||
{
|
||||
return rtx_equal_p_cb (x, y, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
dump_rtx_statistics (void)
|
||||
{
|
||||
|
41
gcc/rtl.h
41
gcc/rtl.h
@ -1774,8 +1774,20 @@ extern int replace_label (rtx *, void *);
|
||||
extern int rtx_referenced_p (rtx, rtx);
|
||||
extern bool tablejump_p (const_rtx, rtx *, rtx *);
|
||||
extern int computed_jump_p (const_rtx);
|
||||
|
||||
typedef int (*rtx_function) (rtx *, void *);
|
||||
extern int for_each_rtx (rtx *, rtx_function, void *);
|
||||
|
||||
typedef int (*rtx_equal_p_callback_function) (const_rtx *, const_rtx *,
|
||||
rtx *, rtx *);
|
||||
extern int rtx_equal_p_cb (const_rtx, const_rtx,
|
||||
rtx_equal_p_callback_function);
|
||||
|
||||
typedef int (*hash_rtx_callback_function) (const_rtx, enum machine_mode, rtx *,
|
||||
enum machine_mode *);
|
||||
extern unsigned hash_rtx_cb (const_rtx, enum machine_mode, int *, int *,
|
||||
bool, hash_rtx_callback_function);
|
||||
|
||||
extern rtx regno_use_in (unsigned int, rtx);
|
||||
extern int auto_inc_p (const_rtx);
|
||||
extern int in_expr_list_p (const_rtx, const_rtx);
|
||||
@ -1796,14 +1808,17 @@ extern rtx get_condition (rtx, rtx *, int, int);
|
||||
|
||||
/* lists.c */
|
||||
|
||||
void free_EXPR_LIST_list (rtx *);
|
||||
void free_INSN_LIST_list (rtx *);
|
||||
void free_EXPR_LIST_node (rtx);
|
||||
void free_INSN_LIST_node (rtx);
|
||||
rtx alloc_INSN_LIST (rtx, rtx);
|
||||
rtx alloc_EXPR_LIST (int, rtx, rtx);
|
||||
void remove_free_INSN_LIST_elem (rtx, rtx *);
|
||||
rtx remove_list_elem (rtx, rtx *);
|
||||
extern void free_EXPR_LIST_list (rtx *);
|
||||
extern void free_INSN_LIST_list (rtx *);
|
||||
extern void free_EXPR_LIST_node (rtx);
|
||||
extern void free_INSN_LIST_node (rtx);
|
||||
extern rtx alloc_INSN_LIST (rtx, rtx);
|
||||
extern rtx alloc_EXPR_LIST (int, rtx, rtx);
|
||||
extern void remove_free_INSN_LIST_elem (rtx, rtx *);
|
||||
extern rtx remove_list_elem (rtx, rtx *);
|
||||
extern rtx remove_free_INSN_LIST_node (rtx *);
|
||||
extern rtx remove_free_EXPR_LIST_node (rtx *);
|
||||
|
||||
|
||||
/* regclass.c */
|
||||
|
||||
@ -2133,7 +2148,9 @@ extern void dump_combine_total_stats (FILE *);
|
||||
extern void delete_dead_jumptables (void);
|
||||
|
||||
/* In sched-vis.c. */
|
||||
extern void print_insn (char *, rtx, int);
|
||||
extern void debug_bb_n_slim (int);
|
||||
extern void debug_bb_slim (struct basic_block_def *);
|
||||
extern void print_rtl_slim (FILE *, rtx, rtx, int, int);
|
||||
extern void print_rtl_slim_with_bb (FILE *, rtx, int);
|
||||
extern void dump_insn_slim (FILE *f, rtx x);
|
||||
extern void debug_insn_slim (rtx x);
|
||||
@ -2147,6 +2164,9 @@ extern void schedule_ebbs (void);
|
||||
/* In haifa-sched.c. */
|
||||
extern void fix_sched_param (const char *, const char *);
|
||||
|
||||
/* In sel-sched-dump.c. */
|
||||
extern void sel_sched_fix_param (const char *param, const char *val);
|
||||
|
||||
/* In print-rtl.c */
|
||||
extern const char *print_rtx_head;
|
||||
extern void debug_rtx (const_rtx);
|
||||
@ -2311,6 +2331,9 @@ extern rtx compare_and_jump_seq (rtx, rtx, enum rtx_code, rtx, int, rtx);
|
||||
/* In loop-iv.c */
|
||||
extern rtx canon_condition (rtx);
|
||||
extern void simplify_using_condition (rtx, rtx *, struct bitmap_head_def *);
|
||||
|
||||
/* In final.c */
|
||||
extern unsigned int compute_alignments (void);
|
||||
|
||||
struct rtl_hooks
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
RTL_HOOKS_GEN_LOWPART_NO_EMIT, \
|
||||
RTL_HOOKS_REG_NONZERO_REG_BITS, \
|
||||
RTL_HOOKS_REG_NUM_SIGN_BIT_COPIES, \
|
||||
RTL_HOOKS_REG_TRUNCATED_TO_MODE, \
|
||||
RTL_HOOKS_REG_TRUNCATED_TO_MODE \
|
||||
}
|
||||
|
||||
extern rtx gen_lowpart_general (enum machine_mode, rtx);
|
||||
|
1364
gcc/sched-deps.c
1364
gcc/sched-deps.c
File diff suppressed because it is too large
Load Diff
141
gcc/sched-ebb.c
141
gcc/sched-ebb.c
@ -46,11 +46,11 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
#ifdef INSN_SCHEDULING
|
||||
|
||||
/* The number of insns scheduled so far. */
|
||||
static int sched_n_insns;
|
||||
|
||||
/* The number of insns to be scheduled in total. */
|
||||
static int n_insns;
|
||||
static int rgn_n_insns;
|
||||
|
||||
/* The number of insns scheduled so far. */
|
||||
static int sched_rgn_n_insns;
|
||||
|
||||
/* Set of blocks, that already have their dependencies calculated. */
|
||||
static bitmap_head dont_calc_deps;
|
||||
@ -62,25 +62,25 @@ static basic_block last_bb;
|
||||
static void init_ready_list (void);
|
||||
static void begin_schedule_ready (rtx, rtx);
|
||||
static int schedule_more_p (void);
|
||||
static const char *ebb_print_insn (rtx, int);
|
||||
static const char *ebb_print_insn (const_rtx, int);
|
||||
static int rank (rtx, rtx);
|
||||
static int contributes_to_priority (rtx, rtx);
|
||||
static void compute_jump_reg_dependencies (rtx, regset, regset, regset);
|
||||
static int ebb_contributes_to_priority (rtx, rtx);
|
||||
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);
|
||||
static void debug_ebb_dependencies (rtx, rtx);
|
||||
|
||||
static void add_remove_insn (rtx, int);
|
||||
static void add_block1 (basic_block, basic_block);
|
||||
static void ebb_add_remove_insn (rtx, int);
|
||||
static void ebb_add_block (basic_block, basic_block);
|
||||
static basic_block advance_target_bb (basic_block, rtx);
|
||||
static void fix_recovery_cfg (int, int, int);
|
||||
static void ebb_fix_recovery_cfg (int, int, int);
|
||||
|
||||
/* Return nonzero if there are more insns that should be scheduled. */
|
||||
|
||||
static int
|
||||
schedule_more_p (void)
|
||||
{
|
||||
return sched_n_insns < n_insns;
|
||||
return sched_rgn_n_insns < rgn_n_insns;
|
||||
}
|
||||
|
||||
/* Print dependency information about ebb between HEAD and TAIL. */
|
||||
@ -107,7 +107,7 @@ init_ready_list (void)
|
||||
rtx next_tail = current_sched_info->next_tail;
|
||||
rtx insn;
|
||||
|
||||
sched_n_insns = 0;
|
||||
sched_rgn_n_insns = 0;
|
||||
|
||||
/* Print debugging information. */
|
||||
if (sched_verbose >= 5)
|
||||
@ -121,14 +121,14 @@ init_ready_list (void)
|
||||
n++;
|
||||
}
|
||||
|
||||
gcc_assert (n == n_insns);
|
||||
gcc_assert (n == rgn_n_insns);
|
||||
}
|
||||
|
||||
/* INSN is being scheduled after LAST. Update counters. */
|
||||
static void
|
||||
begin_schedule_ready (rtx insn, rtx last)
|
||||
{
|
||||
sched_n_insns++;
|
||||
sched_rgn_n_insns++;
|
||||
|
||||
if (BLOCK_FOR_INSN (insn) == last_bb
|
||||
/* INSN is a jump in the last block, ... */
|
||||
@ -184,7 +184,8 @@ begin_schedule_ready (rtx insn, rtx last)
|
||||
current_sched_info->next_tail = NEXT_INSN (BB_END (bb));
|
||||
gcc_assert (current_sched_info->next_tail);
|
||||
|
||||
add_block (bb, last_bb);
|
||||
/* Append new basic block to the end of the ebb. */
|
||||
sched_init_only_bb (bb, last_bb);
|
||||
gcc_assert (last_bb == bb);
|
||||
}
|
||||
}
|
||||
@ -195,11 +196,16 @@ begin_schedule_ready (rtx insn, rtx last)
|
||||
to be formatted so that multiple output lines will line up nicely. */
|
||||
|
||||
static const char *
|
||||
ebb_print_insn (rtx insn, int aligned ATTRIBUTE_UNUSED)
|
||||
ebb_print_insn (const_rtx insn, int aligned ATTRIBUTE_UNUSED)
|
||||
{
|
||||
static char tmp[80];
|
||||
|
||||
sprintf (tmp, "%4d", INSN_UID (insn));
|
||||
/* '+' before insn means it is a new cycle start. */
|
||||
if (GET_MODE (insn) == TImode)
|
||||
sprintf (tmp, "+ %4d", INSN_UID (insn));
|
||||
else
|
||||
sprintf (tmp, " %4d", INSN_UID (insn));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@ -227,8 +233,8 @@ rank (rtx insn1, rtx insn2)
|
||||
calculations. */
|
||||
|
||||
static int
|
||||
contributes_to_priority (rtx next ATTRIBUTE_UNUSED,
|
||||
rtx insn ATTRIBUTE_UNUSED)
|
||||
ebb_contributes_to_priority (rtx next ATTRIBUTE_UNUSED,
|
||||
rtx insn ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -238,9 +244,9 @@ contributes_to_priority (rtx next ATTRIBUTE_UNUSED,
|
||||
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 cond_set, regset used,
|
||||
regset set)
|
||||
void
|
||||
ebb_compute_jump_reg_dependencies (rtx insn, regset cond_set, regset used,
|
||||
regset set)
|
||||
{
|
||||
basic_block b = BLOCK_FOR_INSN (insn);
|
||||
edge e;
|
||||
@ -261,7 +267,17 @@ compute_jump_reg_dependencies (rtx insn, regset cond_set, regset used,
|
||||
/* Used in schedule_insns to initialize current_sched_info for scheduling
|
||||
regions (or single basic blocks). */
|
||||
|
||||
static struct sched_info ebb_sched_info =
|
||||
static struct common_sched_info_def ebb_common_sched_info;
|
||||
|
||||
static struct sched_deps_info_def ebb_sched_deps_info =
|
||||
{
|
||||
ebb_compute_jump_reg_dependencies,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
1, 0, 0
|
||||
};
|
||||
|
||||
static struct haifa_sched_info ebb_sched_info =
|
||||
{
|
||||
init_ready_list,
|
||||
NULL,
|
||||
@ -269,18 +285,15 @@ static struct sched_info ebb_sched_info =
|
||||
NULL,
|
||||
rank,
|
||||
ebb_print_insn,
|
||||
contributes_to_priority,
|
||||
compute_jump_reg_dependencies,
|
||||
ebb_contributes_to_priority,
|
||||
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
0, 1, 0,
|
||||
1, 0,
|
||||
|
||||
add_remove_insn,
|
||||
ebb_add_remove_insn,
|
||||
begin_schedule_ready,
|
||||
add_block1,
|
||||
advance_target_bb,
|
||||
fix_recovery_cfg,
|
||||
SCHED_EBB
|
||||
/* We can create new blocks in begin_schedule_ready (). */
|
||||
| NEW_BBS
|
||||
@ -482,44 +495,29 @@ schedule_ebb (rtx head, rtx tail)
|
||||
|
||||
/* Set priorities. */
|
||||
current_sched_info->sched_max_insns_priority = 0;
|
||||
n_insns = set_priorities (head, tail);
|
||||
rgn_n_insns = set_priorities (head, tail);
|
||||
current_sched_info->sched_max_insns_priority++;
|
||||
|
||||
current_sched_info->prev_head = PREV_INSN (head);
|
||||
current_sched_info->next_tail = NEXT_INSN (tail);
|
||||
|
||||
/* rm_other_notes only removes notes which are _inside_ the
|
||||
block---that is, it won't remove notes before the first real insn
|
||||
or after the last real insn of the block. So if the first insn
|
||||
has a REG_SAVE_NOTE which would otherwise be emitted before the
|
||||
insn, it is redundant with the note before the start of the
|
||||
block, and so we have to take it out. */
|
||||
if (INSN_P (head))
|
||||
{
|
||||
rtx note;
|
||||
|
||||
for (note = REG_NOTES (head); note; note = XEXP (note, 1))
|
||||
if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
|
||||
remove_note (head, note);
|
||||
}
|
||||
|
||||
/* Remove remaining note insns from the block, save them in
|
||||
note_list. These notes are restored at the end of
|
||||
schedule_block (). */
|
||||
rm_other_notes (head, tail);
|
||||
remove_notes (head, tail);
|
||||
|
||||
unlink_bb_notes (first_bb, last_bb);
|
||||
|
||||
current_sched_info->queue_must_finish_empty = 1;
|
||||
|
||||
target_bb = first_bb;
|
||||
schedule_block (&target_bb, n_insns);
|
||||
|
||||
/* Make ready list big enough to hold all the instructions from the ebb. */
|
||||
sched_extend_ready_list (rgn_n_insns);
|
||||
schedule_block (&target_bb);
|
||||
/* Free ready list. */
|
||||
sched_finish_ready_list ();
|
||||
|
||||
/* We might pack all instructions into fewer blocks,
|
||||
so we may made some of them empty. Can't assert (b == last_bb). */
|
||||
|
||||
/* Sanity check: verify that all region insns were scheduled. */
|
||||
gcc_assert (sched_n_insns == n_insns);
|
||||
gcc_assert (sched_rgn_n_insns == rgn_n_insns);
|
||||
|
||||
/* Free dependencies. */
|
||||
sched_free_deps (current_sched_info->head, current_sched_info->tail, true);
|
||||
@ -559,16 +557,21 @@ schedule_ebbs (void)
|
||||
if (n_basic_blocks == NUM_FIXED_BLOCKS)
|
||||
return;
|
||||
|
||||
/* We need current_sched_info in init_dependency_caches, which is
|
||||
invoked via sched_init. */
|
||||
current_sched_info = &ebb_sched_info;
|
||||
/* Setup infos. */
|
||||
{
|
||||
memcpy (&ebb_common_sched_info, &haifa_common_sched_info,
|
||||
sizeof (ebb_common_sched_info));
|
||||
|
||||
df_set_flags (DF_LR_RUN_DCE);
|
||||
df_note_add_problem ();
|
||||
df_analyze ();
|
||||
df_clear_flags (DF_LR_RUN_DCE);
|
||||
regstat_compute_calls_crossed ();
|
||||
sched_init ();
|
||||
ebb_common_sched_info.fix_recovery_cfg = ebb_fix_recovery_cfg;
|
||||
ebb_common_sched_info.add_block = ebb_add_block;
|
||||
ebb_common_sched_info.sched_pass_id = SCHED_EBB_PASS;
|
||||
|
||||
common_sched_info = &ebb_common_sched_info;
|
||||
sched_deps_info = &ebb_sched_deps_info;
|
||||
current_sched_info = &ebb_sched_info;
|
||||
}
|
||||
|
||||
haifa_sched_init ();
|
||||
|
||||
compute_bb_for_insn ();
|
||||
|
||||
@ -622,23 +625,22 @@ schedule_ebbs (void)
|
||||
if (reload_completed)
|
||||
reposition_prologue_and_epilogue_notes ();
|
||||
|
||||
sched_finish ();
|
||||
regstat_free_calls_crossed ();
|
||||
haifa_sched_finish ();
|
||||
}
|
||||
|
||||
/* INSN has been added to/removed from current ebb. */
|
||||
static void
|
||||
add_remove_insn (rtx insn ATTRIBUTE_UNUSED, int remove_p)
|
||||
ebb_add_remove_insn (rtx insn ATTRIBUTE_UNUSED, int remove_p)
|
||||
{
|
||||
if (!remove_p)
|
||||
n_insns++;
|
||||
rgn_n_insns++;
|
||||
else
|
||||
n_insns--;
|
||||
rgn_n_insns--;
|
||||
}
|
||||
|
||||
/* BB was added to ebb after AFTER. */
|
||||
static void
|
||||
add_block1 (basic_block bb, basic_block after)
|
||||
ebb_add_block (basic_block bb, basic_block after)
|
||||
{
|
||||
/* Recovery blocks are always bounded by BARRIERS,
|
||||
therefore, they always form single block EBB,
|
||||
@ -691,7 +693,8 @@ advance_target_bb (basic_block bb, rtx insn)
|
||||
For parameter meaning please refer to
|
||||
sched-int.h: struct sched_info: fix_recovery_cfg. */
|
||||
static void
|
||||
fix_recovery_cfg (int bbi ATTRIBUTE_UNUSED, int jump_bbi, int jump_bb_nexti)
|
||||
ebb_fix_recovery_cfg (int bbi ATTRIBUTE_UNUSED, int jump_bbi,
|
||||
int jump_bb_nexti)
|
||||
{
|
||||
gcc_assert (last_bb->index != bbi);
|
||||
|
||||
|
545
gcc/sched-int.h
545
gcc/sched-int.h
@ -26,18 +26,196 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
/* For state_t. */
|
||||
#include "insn-attr.h"
|
||||
/* For regset_head. */
|
||||
#include "basic-block.h"
|
||||
/* For reg_note. */
|
||||
#include "rtl.h"
|
||||
#include "df.h"
|
||||
#include "basic-block.h"
|
||||
|
||||
/* For VEC (int, heap). */
|
||||
#include "vecprim.h"
|
||||
|
||||
/* Identificator of a scheduler pass. */
|
||||
enum sched_pass_id_t { SCHED_PASS_UNKNOWN, SCHED_RGN_PASS, SCHED_EBB_PASS,
|
||||
SCHED_SMS_PASS, SCHED_SEL_PASS };
|
||||
|
||||
typedef VEC (basic_block, heap) *bb_vec_t;
|
||||
typedef VEC (rtx, heap) *insn_vec_t;
|
||||
typedef VEC(rtx, heap) *rtx_vec_t;
|
||||
|
||||
struct sched_scan_info_def
|
||||
{
|
||||
/* This hook notifies scheduler frontend to extend its internal per basic
|
||||
block data structures. This hook should be called once before a series of
|
||||
calls to bb_init (). */
|
||||
void (*extend_bb) (void);
|
||||
|
||||
/* This hook makes scheduler frontend to initialize its internal data
|
||||
structures for the passed basic block. */
|
||||
void (*init_bb) (basic_block);
|
||||
|
||||
/* This hook notifies scheduler frontend to extend its internal per insn data
|
||||
structures. This hook should be called once before a series of calls to
|
||||
insn_init (). */
|
||||
void (*extend_insn) (void);
|
||||
|
||||
/* This hook makes scheduler frontend to initialize its internal data
|
||||
structures for the passed insn. */
|
||||
void (*init_insn) (rtx);
|
||||
};
|
||||
|
||||
extern const struct sched_scan_info_def *sched_scan_info;
|
||||
|
||||
extern void sched_scan (const struct sched_scan_info_def *,
|
||||
bb_vec_t, basic_block, insn_vec_t, rtx);
|
||||
|
||||
extern void sched_init_bbs (void);
|
||||
|
||||
extern void sched_init_luids (bb_vec_t, basic_block, insn_vec_t, rtx);
|
||||
extern void sched_finish_luids (void);
|
||||
|
||||
extern void sched_extend_target (void);
|
||||
|
||||
extern void haifa_init_h_i_d (bb_vec_t, basic_block, insn_vec_t, rtx);
|
||||
extern void haifa_finish_h_i_d (void);
|
||||
|
||||
/* Hooks that are common to all the schedulers. */
|
||||
struct common_sched_info_def
|
||||
{
|
||||
/* Called after blocks were rearranged due to movement of jump instruction.
|
||||
The first parameter - index of basic block, in which jump currently is.
|
||||
The second parameter - index of basic block, in which jump used
|
||||
to be.
|
||||
The third parameter - index of basic block, that follows the second
|
||||
parameter. */
|
||||
void (*fix_recovery_cfg) (int, int, int);
|
||||
|
||||
/* Called to notify frontend, that new basic block is being added.
|
||||
The first parameter - new basic block.
|
||||
The second parameter - block, after which new basic block is being added,
|
||||
or EXIT_BLOCK_PTR, if recovery block is being added,
|
||||
or NULL, if standalone block is being added. */
|
||||
void (*add_block) (basic_block, basic_block);
|
||||
|
||||
/* Estimate number of insns in the basic block. */
|
||||
int (*estimate_number_of_insns) (basic_block);
|
||||
|
||||
/* Given a non-insn (!INSN_P (x)) return
|
||||
-1 - if this rtx don't need a luid.
|
||||
0 - if it should have the same luid as the previous insn.
|
||||
1 - if it needs a separate luid. */
|
||||
int (*luid_for_non_insn) (rtx);
|
||||
|
||||
/* Scheduler pass identifier. It is preferably used in assertions. */
|
||||
enum sched_pass_id_t sched_pass_id;
|
||||
};
|
||||
|
||||
extern struct common_sched_info_def *common_sched_info;
|
||||
|
||||
extern const struct common_sched_info_def haifa_common_sched_info;
|
||||
|
||||
/* Return true if selective scheduling pass is working. */
|
||||
static inline bool
|
||||
sel_sched_p (void)
|
||||
{
|
||||
return common_sched_info->sched_pass_id == SCHED_SEL_PASS;
|
||||
}
|
||||
|
||||
/* Returns maximum priority that an insn was assigned to. */
|
||||
extern int get_rgn_sched_max_insns_priority (void);
|
||||
|
||||
/* Increases effective priority for INSN by AMOUNT. */
|
||||
extern void sel_add_to_insn_priority (rtx, int);
|
||||
|
||||
/* True if during selective scheduling we need to emulate some of haifa
|
||||
scheduler behaviour. */
|
||||
extern int sched_emulate_haifa_p;
|
||||
|
||||
/* Mapping from INSN_UID to INSN_LUID. In the end all other per insn data
|
||||
structures should be indexed by luid. */
|
||||
extern VEC (int, heap) *sched_luids;
|
||||
#define INSN_LUID(INSN) (VEC_index (int, sched_luids, INSN_UID (INSN)))
|
||||
#define LUID_BY_UID(UID) (VEC_index (int, sched_luids, UID))
|
||||
|
||||
#define SET_INSN_LUID(INSN, LUID) \
|
||||
(VEC_replace (int, sched_luids, INSN_UID (INSN), (LUID)))
|
||||
|
||||
/* The highest INSN_LUID. */
|
||||
extern int sched_max_luid;
|
||||
|
||||
extern int insn_luid (rtx);
|
||||
|
||||
/* This list holds ripped off notes from the current block. These notes will
|
||||
be attached to the beginning of the block when its scheduling is
|
||||
finished. */
|
||||
extern rtx note_list;
|
||||
|
||||
extern void remove_notes (rtx, rtx);
|
||||
extern rtx restore_other_notes (rtx, basic_block);
|
||||
extern void sched_insns_init (rtx);
|
||||
extern void sched_insns_finish (void);
|
||||
|
||||
extern void *xrecalloc (void *, size_t, size_t, size_t);
|
||||
extern rtx bb_note (basic_block);
|
||||
|
||||
extern void reemit_notes (rtx);
|
||||
|
||||
/* Functions in sched-vis.c. */
|
||||
extern void print_insn (char *, const_rtx, int);
|
||||
extern void print_pattern (char *, const_rtx, int);
|
||||
extern void print_value (char *, const_rtx, int);
|
||||
|
||||
/* Functions in haifa-sched.c. */
|
||||
extern int haifa_classify_insn (const_rtx);
|
||||
|
||||
/* Functions in sel-sched-ir.c. */
|
||||
extern void sel_find_rgns (void);
|
||||
extern void sel_mark_hard_insn (rtx);
|
||||
|
||||
extern size_t dfa_state_size;
|
||||
|
||||
extern void advance_state (state_t);
|
||||
|
||||
extern void setup_sched_dump (void);
|
||||
extern void sched_init (void);
|
||||
extern void sched_finish (void);
|
||||
|
||||
extern bool sel_insn_is_speculation_check (rtx);
|
||||
|
||||
/* Describe the ready list of the scheduler.
|
||||
VEC holds space enough for all insns in the current region. VECLEN
|
||||
says how many exactly.
|
||||
FIRST is the index of the element with the highest priority; i.e. the
|
||||
last one in the ready list, since elements are ordered by ascending
|
||||
priority.
|
||||
N_READY determines how many insns are on the ready list. */
|
||||
struct ready_list
|
||||
{
|
||||
rtx *vec;
|
||||
int veclen;
|
||||
int first;
|
||||
int n_ready;
|
||||
};
|
||||
|
||||
extern char *ready_try;
|
||||
extern struct ready_list ready;
|
||||
|
||||
extern int max_issue (struct ready_list *, int, state_t, int *);
|
||||
|
||||
extern void ebb_compute_jump_reg_dependencies (rtx, regset, regset, regset);
|
||||
|
||||
extern edge find_fallthru_edge (basic_block);
|
||||
|
||||
extern void (* sched_init_only_bb) (basic_block, basic_block);
|
||||
extern basic_block (* sched_split_block) (basic_block, rtx);
|
||||
extern basic_block sched_split_block_1 (basic_block, rtx);
|
||||
extern basic_block (* sched_create_empty_bb) (basic_block);
|
||||
extern basic_block sched_create_empty_bb_1 (basic_block);
|
||||
|
||||
extern basic_block sched_create_recovery_block (basic_block *);
|
||||
extern void sched_create_recovery_edges (basic_block, basic_block,
|
||||
basic_block);
|
||||
|
||||
/* Pointer to data describing the current DFA state. */
|
||||
extern state_t curr_state;
|
||||
|
||||
/* Forward declaration. */
|
||||
struct ready_list;
|
||||
|
||||
/* Type to represent status of a dependence. */
|
||||
typedef int ds_t;
|
||||
|
||||
@ -242,6 +420,16 @@ struct _dep_node
|
||||
#define DEP_NODE_DEP(N) (&(N)->dep)
|
||||
#define DEP_NODE_FORW(N) (&(N)->forw)
|
||||
|
||||
/* The following enumeration values tell us what dependencies we
|
||||
should use to implement the barrier. We use true-dependencies for
|
||||
TRUE_BARRIER and anti-dependencies for MOVE_BARRIER. */
|
||||
enum reg_pending_barrier_mode
|
||||
{
|
||||
NOT_A_BARRIER = 0,
|
||||
MOVE_BARRIER,
|
||||
TRUE_BARRIER
|
||||
};
|
||||
|
||||
/* Describe state of dependencies used during sched_analyze phase. */
|
||||
struct deps
|
||||
{
|
||||
@ -330,14 +518,23 @@ struct deps
|
||||
|
||||
/* Element N is set for each register that is conditionally set. */
|
||||
regset_head reg_conditional_sets;
|
||||
|
||||
/* Shows the last value of reg_pending_barrier associated with the insn. */
|
||||
enum reg_pending_barrier_mode last_reg_pending_barrier;
|
||||
|
||||
/* True when this context should be treated as a readonly by
|
||||
the analysis. */
|
||||
BOOL_BITFIELD readonly : 1;
|
||||
};
|
||||
|
||||
typedef struct deps *deps_t;
|
||||
|
||||
/* This structure holds some state of the current scheduling pass, and
|
||||
contains some function pointers that abstract out some of the non-generic
|
||||
functionality from functions such as schedule_block or schedule_insn.
|
||||
There is one global variable, current_sched_info, which points to the
|
||||
sched_info structure currently in use. */
|
||||
struct sched_info
|
||||
struct haifa_sched_info
|
||||
{
|
||||
/* Add all insns that are initially ready to the ready list. Called once
|
||||
before scheduling a set of insns. */
|
||||
@ -361,14 +558,10 @@ struct sched_info
|
||||
necessary to identify this insn in an output. It's valid to use a
|
||||
static buffer for this. The ALIGNED parameter should cause the string
|
||||
to be formatted so that multiple output lines will line up nicely. */
|
||||
const char *(*print_insn) (rtx, int);
|
||||
const char *(*print_insn) (const_rtx, int);
|
||||
/* Return nonzero if an insn should be included in priority
|
||||
calculations. */
|
||||
int (*contributes_to_priority) (rtx, rtx);
|
||||
/* Called when computing dependencies for a JUMP_INSN. This function
|
||||
should store the set of registers that must be considered as set by
|
||||
the jump in the regset. */
|
||||
void (*compute_jump_reg_dependencies) (rtx, regset, regset, regset);
|
||||
|
||||
/* The boundaries of the set of insns to be scheduled. */
|
||||
rtx prev_head, next_tail;
|
||||
@ -379,11 +572,6 @@ struct sched_info
|
||||
|
||||
/* If nonzero, enables an additional sanity check in schedule_block. */
|
||||
unsigned int queue_must_finish_empty:1;
|
||||
/* Nonzero if we should use cselib for better alias analysis. This
|
||||
must be 0 if the dependency information is used after sched_analyze
|
||||
has completed, e.g. if we're using it to initialize state for successor
|
||||
blocks in region scheduling. */
|
||||
unsigned int use_cselib:1;
|
||||
|
||||
/* Maximum priority that has been assigned to an insn. */
|
||||
int sched_max_insns_priority;
|
||||
@ -399,27 +587,12 @@ struct sched_info
|
||||
last scheduled instruction. */
|
||||
void (*begin_schedule_ready) (rtx, rtx);
|
||||
|
||||
/* Called to notify frontend, that new basic block is being added.
|
||||
The first parameter - new basic block.
|
||||
The second parameter - block, after which new basic block is being added,
|
||||
or EXIT_BLOCK_PTR, if recovery block is being added,
|
||||
or NULL, if standalone block is being added. */
|
||||
void (*add_block) (basic_block, basic_block);
|
||||
|
||||
/* If the second parameter is not NULL, return nonnull value, if the
|
||||
basic block should be advanced.
|
||||
If the second parameter is NULL, return the next basic block in EBB.
|
||||
The first parameter is the current basic block in EBB. */
|
||||
basic_block (*advance_target_bb) (basic_block, rtx);
|
||||
|
||||
/* Called after blocks were rearranged due to movement of jump instruction.
|
||||
The first parameter - index of basic block, in which jump currently is.
|
||||
The second parameter - index of basic block, in which jump used
|
||||
to be.
|
||||
The third parameter - index of basic block, that follows the second
|
||||
parameter. */
|
||||
void (*fix_recovery_cfg) (int, int, int);
|
||||
|
||||
/* ??? FIXME: should use straight bitfields inside sched_info instead of
|
||||
this flag field. */
|
||||
unsigned int flags;
|
||||
@ -438,23 +611,40 @@ struct spec_info_def
|
||||
|
||||
/* Minimal cumulative weakness of speculative instruction's
|
||||
dependencies, so that insn will be scheduled. */
|
||||
dw_t weakness_cutoff;
|
||||
dw_t data_weakness_cutoff;
|
||||
|
||||
/* Minimal usefulness of speculative instruction to be considered for
|
||||
scheduling. */
|
||||
int control_weakness_cutoff;
|
||||
|
||||
/* Flags from the enum SPEC_SCHED_FLAGS. */
|
||||
int flags;
|
||||
};
|
||||
typedef struct spec_info_def *spec_info_t;
|
||||
|
||||
extern struct sched_info *current_sched_info;
|
||||
extern spec_info_t spec_info;
|
||||
|
||||
extern struct haifa_sched_info *current_sched_info;
|
||||
|
||||
/* Indexed by INSN_UID, the collection of all data associated with
|
||||
a single instruction. */
|
||||
|
||||
struct haifa_insn_data
|
||||
struct _haifa_deps_insn_data
|
||||
{
|
||||
/* We can't place 'struct _deps_list' into h_i_d instead of deps_list_t
|
||||
because when h_i_d extends, addresses of the deps_list->first
|
||||
change without updating deps_list->first->next->prev_nextp. */
|
||||
/* The number of incoming edges in the forward dependency graph.
|
||||
As scheduling proceeds, counts are decreased. An insn moves to
|
||||
the ready queue when its counter reaches zero. */
|
||||
int dep_count;
|
||||
|
||||
/* Nonzero if instruction has internal dependence
|
||||
(e.g. add_dependence was invoked with (insn == elem)). */
|
||||
unsigned int has_internal_dep;
|
||||
|
||||
/* NB: We can't place 'struct _deps_list' here instead of deps_list_t into
|
||||
h_i_d because when h_i_d extends, addresses of the deps_list->first
|
||||
change without updating deps_list->first->next->prev_nextp. Thus
|
||||
BACK_DEPS and RESOLVED_BACK_DEPS are allocated on the heap and FORW_DEPS
|
||||
list is allocated on the obstack. */
|
||||
|
||||
/* A list of hard backward dependencies. The insn is a consumer of all the
|
||||
deps mentioned here. */
|
||||
@ -476,7 +666,17 @@ struct haifa_insn_data
|
||||
from 'forw_deps' to 'resolved_forw_deps' while scheduling to fasten the
|
||||
search in 'forw_deps'. */
|
||||
deps_list_t resolved_forw_deps;
|
||||
|
||||
|
||||
/* Some insns (e.g. call) are not allowed to move across blocks. */
|
||||
unsigned int cant_move : 1;
|
||||
};
|
||||
|
||||
struct _haifa_insn_data
|
||||
{
|
||||
/* We can't place 'struct _deps_list' into h_i_d instead of deps_list_t
|
||||
because when h_i_d extends, addresses of the deps_list->first
|
||||
change without updating deps_list->first->next->prev_nextp. */
|
||||
|
||||
/* Logical uid gives the original ordering of the insns. */
|
||||
int luid;
|
||||
|
||||
@ -503,9 +703,6 @@ struct haifa_insn_data
|
||||
register pressure. */
|
||||
short reg_weight;
|
||||
|
||||
/* Some insns (e.g. call) are not allowed to move across blocks. */
|
||||
unsigned int cant_move : 1;
|
||||
|
||||
/* Set if there's DEF-USE dependence between some speculatively
|
||||
moved load insn and this one. */
|
||||
unsigned int fed_by_spec_load : 1;
|
||||
@ -516,14 +713,12 @@ struct haifa_insn_data
|
||||
'< 0' if priority in invalid and should be recomputed. */
|
||||
signed char priority_status;
|
||||
|
||||
/* Nonzero if instruction has internal dependence
|
||||
(e.g. add_dependence was invoked with (insn == elem)). */
|
||||
unsigned int has_internal_dep : 1;
|
||||
|
||||
/* What speculations are necessary to apply to schedule the instruction. */
|
||||
ds_t todo_spec;
|
||||
|
||||
/* What speculations were already applied. */
|
||||
ds_t done_spec;
|
||||
|
||||
/* What speculations are checked by this instruction. */
|
||||
ds_t check_spec;
|
||||
|
||||
@ -534,33 +729,56 @@ struct haifa_insn_data
|
||||
rtx orig_pat;
|
||||
};
|
||||
|
||||
extern struct haifa_insn_data *h_i_d;
|
||||
typedef struct _haifa_insn_data haifa_insn_data_def;
|
||||
typedef haifa_insn_data_def *haifa_insn_data_t;
|
||||
|
||||
DEF_VEC_O (haifa_insn_data_def);
|
||||
DEF_VEC_ALLOC_O (haifa_insn_data_def, heap);
|
||||
|
||||
extern VEC(haifa_insn_data_def, heap) *h_i_d;
|
||||
|
||||
#define HID(INSN) (VEC_index (haifa_insn_data_def, h_i_d, INSN_UID (INSN)))
|
||||
|
||||
/* Accessor macros for h_i_d. There are more in haifa-sched.c and
|
||||
sched-rgn.c. */
|
||||
#define INSN_PRIORITY(INSN) (HID (INSN)->priority)
|
||||
#define INSN_REG_WEIGHT(INSN) (HID (INSN)->reg_weight)
|
||||
#define INSN_PRIORITY_STATUS(INSN) (HID (INSN)->priority_status)
|
||||
|
||||
#define INSN_HARD_BACK_DEPS(INSN) (h_i_d[INSN_UID (INSN)].hard_back_deps)
|
||||
#define INSN_SPEC_BACK_DEPS(INSN) (h_i_d[INSN_UID (INSN)].spec_back_deps)
|
||||
#define INSN_FORW_DEPS(INSN) (h_i_d[INSN_UID (INSN)].forw_deps)
|
||||
#define INSN_RESOLVED_BACK_DEPS(INSN) \
|
||||
(h_i_d[INSN_UID (INSN)].resolved_back_deps)
|
||||
#define INSN_RESOLVED_FORW_DEPS(INSN) \
|
||||
(h_i_d[INSN_UID (INSN)].resolved_forw_deps)
|
||||
#define INSN_LUID(INSN) (h_i_d[INSN_UID (INSN)].luid)
|
||||
#define CANT_MOVE(insn) (h_i_d[INSN_UID (insn)].cant_move)
|
||||
#define INSN_PRIORITY(INSN) (h_i_d[INSN_UID (INSN)].priority)
|
||||
#define INSN_PRIORITY_STATUS(INSN) (h_i_d[INSN_UID (INSN)].priority_status)
|
||||
typedef struct _haifa_deps_insn_data haifa_deps_insn_data_def;
|
||||
typedef haifa_deps_insn_data_def *haifa_deps_insn_data_t;
|
||||
|
||||
DEF_VEC_O (haifa_deps_insn_data_def);
|
||||
DEF_VEC_ALLOC_O (haifa_deps_insn_data_def, heap);
|
||||
|
||||
extern VEC(haifa_deps_insn_data_def, heap) *h_d_i_d;
|
||||
|
||||
#define HDID(INSN) (VEC_index (haifa_deps_insn_data_def, h_d_i_d, \
|
||||
INSN_LUID (INSN)))
|
||||
#define INSN_DEP_COUNT(INSN) (HDID (INSN)->dep_count)
|
||||
#define HAS_INTERNAL_DEP(INSN) (HDID (INSN)->has_internal_dep)
|
||||
#define INSN_FORW_DEPS(INSN) (HDID (INSN)->forw_deps)
|
||||
#define INSN_RESOLVED_BACK_DEPS(INSN) (HDID (INSN)->resolved_back_deps)
|
||||
#define INSN_RESOLVED_FORW_DEPS(INSN) (HDID (INSN)->resolved_forw_deps)
|
||||
#define INSN_HARD_BACK_DEPS(INSN) (HDID (INSN)->hard_back_deps)
|
||||
#define INSN_SPEC_BACK_DEPS(INSN) (HDID (INSN)->spec_back_deps)
|
||||
#define CANT_MOVE(INSN) (HDID (INSN)->cant_move)
|
||||
#define CANT_MOVE_BY_LUID(LUID) (VEC_index (haifa_deps_insn_data_def, h_d_i_d, \
|
||||
LUID)->cant_move)
|
||||
|
||||
|
||||
#define INSN_PRIORITY(INSN) (HID (INSN)->priority)
|
||||
#define INSN_PRIORITY_STATUS(INSN) (HID (INSN)->priority_status)
|
||||
#define INSN_PRIORITY_KNOWN(INSN) (INSN_PRIORITY_STATUS (INSN) > 0)
|
||||
#define INSN_REG_WEIGHT(INSN) (h_i_d[INSN_UID (INSN)].reg_weight)
|
||||
#define HAS_INTERNAL_DEP(INSN) (h_i_d[INSN_UID (INSN)].has_internal_dep)
|
||||
#define TODO_SPEC(INSN) (h_i_d[INSN_UID (INSN)].todo_spec)
|
||||
#define DONE_SPEC(INSN) (h_i_d[INSN_UID (INSN)].done_spec)
|
||||
#define CHECK_SPEC(INSN) (h_i_d[INSN_UID (INSN)].check_spec)
|
||||
#define RECOVERY_BLOCK(INSN) (h_i_d[INSN_UID (INSN)].recovery_block)
|
||||
#define ORIG_PAT(INSN) (h_i_d[INSN_UID (INSN)].orig_pat)
|
||||
#define TODO_SPEC(INSN) (HID (INSN)->todo_spec)
|
||||
#define DONE_SPEC(INSN) (HID (INSN)->done_spec)
|
||||
#define CHECK_SPEC(INSN) (HID (INSN)->check_spec)
|
||||
#define RECOVERY_BLOCK(INSN) (HID (INSN)->recovery_block)
|
||||
#define ORIG_PAT(INSN) (HID (INSN)->orig_pat)
|
||||
|
||||
/* INSN is either a simple or a branchy speculation check. */
|
||||
#define IS_SPECULATION_CHECK_P(INSN) (RECOVERY_BLOCK (INSN) != NULL)
|
||||
#define IS_SPECULATION_CHECK_P(INSN) \
|
||||
(sel_sched_p () ? sel_insn_is_speculation_check (INSN) : RECOVERY_BLOCK (INSN) != NULL)
|
||||
|
||||
/* INSN is a speculation check that will simply reexecute the speculatively
|
||||
scheduled instruction if the speculation fails. */
|
||||
@ -706,14 +924,16 @@ enum SCHED_FLAGS {
|
||||
DO_SPECULATION = USE_DEPS_LIST << 1,
|
||||
SCHED_RGN = DO_SPECULATION << 1,
|
||||
SCHED_EBB = SCHED_RGN << 1,
|
||||
/* Scheduler can possible create new basic blocks. Used for assertions. */
|
||||
NEW_BBS = SCHED_EBB << 1
|
||||
/* Scheduler can possibly create new basic blocks. Used for assertions. */
|
||||
NEW_BBS = SCHED_EBB << 1,
|
||||
SEL_SCHED = NEW_BBS << 1
|
||||
};
|
||||
|
||||
enum SPEC_SCHED_FLAGS {
|
||||
COUNT_SPEC_IN_CRITICAL_PATH = 1,
|
||||
PREFER_NON_DATA_SPEC = COUNT_SPEC_IN_CRITICAL_PATH << 1,
|
||||
PREFER_NON_CONTROL_SPEC = PREFER_NON_DATA_SPEC << 1
|
||||
PREFER_NON_CONTROL_SPEC = PREFER_NON_DATA_SPEC << 1,
|
||||
SEL_SCHED_SPEC_DONT_CHECK_CONTROL = PREFER_NON_CONTROL_SPEC << 1
|
||||
};
|
||||
|
||||
#define NOTE_NOT_BB_P(NOTE) (NOTE_P (NOTE) && (NOTE_KIND (NOTE) \
|
||||
@ -803,23 +1023,104 @@ enum INSN_TRAP_CLASS
|
||||
#define HAIFA_INLINE __inline
|
||||
#endif
|
||||
|
||||
struct sched_deps_info_def
|
||||
{
|
||||
/* Called when computing dependencies for a JUMP_INSN. This function
|
||||
should store the set of registers that must be considered as set by
|
||||
the jump in the regset. */
|
||||
void (*compute_jump_reg_dependencies) (rtx, regset, regset, regset);
|
||||
|
||||
/* Start analyzing insn. */
|
||||
void (*start_insn) (rtx);
|
||||
|
||||
/* Finish analyzing insn. */
|
||||
void (*finish_insn) (void);
|
||||
|
||||
/* Start analyzing insn LHS (Left Hand Side). */
|
||||
void (*start_lhs) (rtx);
|
||||
|
||||
/* Finish analyzing insn LHS. */
|
||||
void (*finish_lhs) (void);
|
||||
|
||||
/* Start analyzing insn RHS (Right Hand Side). */
|
||||
void (*start_rhs) (rtx);
|
||||
|
||||
/* Finish analyzing insn RHS. */
|
||||
void (*finish_rhs) (void);
|
||||
|
||||
/* Note set of the register. */
|
||||
void (*note_reg_set) (int);
|
||||
|
||||
/* Note clobber of the register. */
|
||||
void (*note_reg_clobber) (int);
|
||||
|
||||
/* Note use of the register. */
|
||||
void (*note_reg_use) (int);
|
||||
|
||||
/* Note memory dependence of type DS between MEM1 and MEM2 (which is
|
||||
in the INSN2). */
|
||||
void (*note_mem_dep) (rtx mem1, rtx mem2, rtx insn2, ds_t ds);
|
||||
|
||||
/* Note a dependence of type DS from the INSN. */
|
||||
void (*note_dep) (rtx insn, ds_t ds);
|
||||
|
||||
/* Nonzero if we should use cselib for better alias analysis. This
|
||||
must be 0 if the dependency information is used after sched_analyze
|
||||
has completed, e.g. if we're using it to initialize state for successor
|
||||
blocks in region scheduling. */
|
||||
unsigned int use_cselib : 1;
|
||||
|
||||
/* If set, generate links between instruction as DEPS_LIST.
|
||||
Otherwise, generate usual INSN_LIST links. */
|
||||
unsigned int use_deps_list : 1;
|
||||
|
||||
/* Generate data and control speculative dependencies.
|
||||
Requires USE_DEPS_LIST set. */
|
||||
unsigned int generate_spec_deps : 1;
|
||||
};
|
||||
|
||||
extern struct sched_deps_info_def *sched_deps_info;
|
||||
|
||||
|
||||
/* Functions in sched-deps.c. */
|
||||
extern bool sched_insns_conditions_mutex_p (const_rtx, const_rtx);
|
||||
extern bool sched_insn_is_legitimate_for_speculation_p (const_rtx, ds_t);
|
||||
extern void add_dependence (rtx, rtx, enum reg_note);
|
||||
extern void sched_analyze (struct deps *, rtx, rtx);
|
||||
extern bool deps_pools_are_empty_p (void);
|
||||
extern void sched_free_deps (rtx, rtx, bool);
|
||||
extern void init_deps (struct deps *);
|
||||
extern void free_deps (struct deps *);
|
||||
extern void init_deps_global (void);
|
||||
extern void finish_deps_global (void);
|
||||
extern void init_dependency_caches (int);
|
||||
extern void free_dependency_caches (void);
|
||||
extern void extend_dependency_caches (int, bool);
|
||||
extern void deps_analyze_insn (struct deps *, rtx);
|
||||
extern void remove_from_deps (struct deps *, rtx);
|
||||
|
||||
extern dw_t get_dep_weak_1 (ds_t, ds_t);
|
||||
extern dw_t get_dep_weak (ds_t, ds_t);
|
||||
extern ds_t set_dep_weak (ds_t, ds_t, dw_t);
|
||||
extern dw_t estimate_dep_weak (rtx, rtx);
|
||||
extern ds_t ds_merge (ds_t, ds_t);
|
||||
extern ds_t ds_full_merge (ds_t, ds_t, rtx, rtx);
|
||||
extern ds_t ds_max_merge (ds_t, ds_t);
|
||||
extern dw_t ds_weak (ds_t);
|
||||
extern ds_t ds_get_speculation_types (ds_t);
|
||||
extern ds_t ds_get_max_dep_weak (ds_t);
|
||||
|
||||
extern void sched_deps_init (bool);
|
||||
extern void sched_deps_finish (void);
|
||||
|
||||
extern void haifa_note_reg_set (int);
|
||||
extern void haifa_note_reg_clobber (int);
|
||||
extern void haifa_note_reg_use (int);
|
||||
|
||||
extern void maybe_extend_reg_info_p (void);
|
||||
|
||||
extern void deps_start_bb (struct deps *, rtx);
|
||||
extern enum reg_note ds_to_dt (ds_t);
|
||||
|
||||
extern bool deps_pools_are_empty_p (void);
|
||||
extern void sched_free_deps (rtx, rtx, bool);
|
||||
extern void extend_dependency_caches (int, bool);
|
||||
|
||||
extern void debug_ds (ds_t);
|
||||
|
||||
/* Functions in haifa-sched.c. */
|
||||
@ -827,25 +1128,105 @@ extern int haifa_classify_insn (const_rtx);
|
||||
extern void get_ebb_head_tail (basic_block, basic_block, rtx *, rtx *);
|
||||
extern int no_real_insns_p (const_rtx, const_rtx);
|
||||
|
||||
extern void rm_other_notes (rtx, rtx);
|
||||
|
||||
extern int insn_cost (rtx);
|
||||
extern int dep_cost_1 (dep_t, dw_t);
|
||||
extern int dep_cost (dep_t);
|
||||
extern int set_priorities (rtx, rtx);
|
||||
|
||||
extern void schedule_block (basic_block *, int);
|
||||
extern void sched_init (void);
|
||||
extern void sched_finish (void);
|
||||
extern void schedule_block (basic_block *);
|
||||
|
||||
extern int cycle_issued_insns;
|
||||
extern int issue_rate;
|
||||
extern int dfa_lookahead;
|
||||
|
||||
extern void ready_sort (struct ready_list *);
|
||||
extern rtx ready_element (struct ready_list *, int);
|
||||
extern rtx *ready_lastpos (struct ready_list *);
|
||||
|
||||
extern int try_ready (rtx);
|
||||
extern void * xrecalloc (void *, size_t, size_t, size_t);
|
||||
extern void sched_extend_ready_list (int);
|
||||
extern void sched_finish_ready_list (void);
|
||||
extern void sched_change_pattern (rtx, rtx);
|
||||
extern int sched_speculate_insn (rtx, ds_t, rtx *);
|
||||
extern void unlink_bb_notes (basic_block, basic_block);
|
||||
extern void add_block (basic_block, basic_block);
|
||||
extern rtx bb_note (basic_block);
|
||||
extern void concat_note_lists (rtx, rtx *);
|
||||
|
||||
|
||||
/* Functions in sched-rgn.c. */
|
||||
/* Types and functions in sched-rgn.c. */
|
||||
|
||||
/* A region is the main entity for interblock scheduling: insns
|
||||
are allowed to move between blocks in the same region, along
|
||||
control flow graph edges, in the 'up' direction. */
|
||||
typedef struct
|
||||
{
|
||||
/* Number of extended basic blocks in region. */
|
||||
int rgn_nr_blocks;
|
||||
/* cblocks in the region (actually index in rgn_bb_table). */
|
||||
int rgn_blocks;
|
||||
/* Dependencies for this region are already computed. Basically, indicates,
|
||||
that this is a recovery block. */
|
||||
unsigned int dont_calc_deps : 1;
|
||||
/* This region has at least one non-trivial ebb. */
|
||||
unsigned int has_real_ebb : 1;
|
||||
}
|
||||
region;
|
||||
|
||||
extern int nr_regions;
|
||||
extern region *rgn_table;
|
||||
extern int *rgn_bb_table;
|
||||
extern int *block_to_bb;
|
||||
extern int *containing_rgn;
|
||||
|
||||
#define RGN_NR_BLOCKS(rgn) (rgn_table[rgn].rgn_nr_blocks)
|
||||
#define RGN_BLOCKS(rgn) (rgn_table[rgn].rgn_blocks)
|
||||
#define RGN_DONT_CALC_DEPS(rgn) (rgn_table[rgn].dont_calc_deps)
|
||||
#define RGN_HAS_REAL_EBB(rgn) (rgn_table[rgn].has_real_ebb)
|
||||
#define BLOCK_TO_BB(block) (block_to_bb[block])
|
||||
#define CONTAINING_RGN(block) (containing_rgn[block])
|
||||
|
||||
/* The mapping from ebb to block. */
|
||||
extern int *ebb_head;
|
||||
#define BB_TO_BLOCK(ebb) (rgn_bb_table[ebb_head[ebb]])
|
||||
#define EBB_FIRST_BB(ebb) BASIC_BLOCK (BB_TO_BLOCK (ebb))
|
||||
#define EBB_LAST_BB(ebb) BASIC_BLOCK (rgn_bb_table[ebb_head[ebb + 1] - 1])
|
||||
#define INSN_BB(INSN) (BLOCK_TO_BB (BLOCK_NUM (INSN)))
|
||||
|
||||
extern int current_nr_blocks;
|
||||
extern int current_blocks;
|
||||
extern int target_bb;
|
||||
|
||||
extern bool sched_is_disabled_for_current_region_p (void);
|
||||
extern void sched_rgn_init (bool);
|
||||
extern void sched_rgn_finish (void);
|
||||
extern void rgn_setup_region (int);
|
||||
extern void sched_rgn_compute_dependencies (int);
|
||||
extern void sched_rgn_local_init (int);
|
||||
extern void sched_rgn_local_finish (void);
|
||||
extern void sched_rgn_local_free (void);
|
||||
extern void extend_regions (void);
|
||||
extern void rgn_make_new_region_out_of_new_block (basic_block);
|
||||
|
||||
extern void compute_priorities (void);
|
||||
extern void increase_insn_priority (rtx, int);
|
||||
extern void debug_rgn_dependencies (int);
|
||||
extern void debug_dependencies (rtx, rtx);
|
||||
extern void free_rgn_deps (void);
|
||||
extern int contributes_to_priority (rtx, rtx);
|
||||
extern void extend_rgns (int *, int *, sbitmap, int *);
|
||||
extern void deps_join (struct deps *, struct deps *);
|
||||
|
||||
extern void rgn_setup_common_sched_info (void);
|
||||
extern void rgn_setup_sched_infos (void);
|
||||
|
||||
extern void debug_regions (void);
|
||||
extern void debug_region (int);
|
||||
extern void dump_region_dot (FILE *, int);
|
||||
extern void dump_region_dot_file (const char *, int);
|
||||
|
||||
extern void haifa_sched_init (void);
|
||||
extern void haifa_sched_finish (void);
|
||||
|
||||
/* sched-deps.c interface to walk, add, search, update, resolve, delete
|
||||
and debug instruction dependencies. */
|
||||
|
1141
gcc/sched-rgn.c
1141
gcc/sched-rgn.c
File diff suppressed because it is too large
Load Diff
@ -29,13 +29,11 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "hard-reg-set.h"
|
||||
#include "basic-block.h"
|
||||
#include "real.h"
|
||||
#include "insn-attr.h"
|
||||
#include "sched-int.h"
|
||||
#include "tree-pass.h"
|
||||
|
||||
static char *safe_concat (char *, char *, const char *);
|
||||
static void print_exp (char *, const_rtx, int);
|
||||
static void print_value (char *, const_rtx, int);
|
||||
static void print_pattern (char *, const_rtx, int);
|
||||
|
||||
#define BUF_LEN 2048
|
||||
|
||||
@ -425,7 +423,7 @@ print_exp (char *buf, const_rtx x, int verbose)
|
||||
/* Prints rtxes, I customarily classified as values. They're constants,
|
||||
registers, labels, symbols and memory accesses. */
|
||||
|
||||
static void
|
||||
void
|
||||
print_value (char *buf, const_rtx x, int verbose)
|
||||
{
|
||||
char t[BUF_LEN];
|
||||
@ -532,7 +530,7 @@ print_value (char *buf, const_rtx x, int verbose)
|
||||
|
||||
/* The next step in insn detalization, its pattern recognition. */
|
||||
|
||||
static void
|
||||
void
|
||||
print_pattern (char *buf, const_rtx x, int verbose)
|
||||
{
|
||||
char t1[BUF_LEN], t2[BUF_LEN], t3[BUF_LEN];
|
||||
@ -643,10 +641,10 @@ print_pattern (char *buf, const_rtx x, int verbose)
|
||||
depends now on sched.c inner variables ...) */
|
||||
|
||||
void
|
||||
print_insn (char *buf, rtx x, int verbose)
|
||||
print_insn (char *buf, const_rtx x, int verbose)
|
||||
{
|
||||
char t[BUF_LEN];
|
||||
rtx insn = x;
|
||||
const_rtx insn = x;
|
||||
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
@ -681,7 +679,7 @@ print_insn (char *buf, rtx x, int verbose)
|
||||
strcpy (t, "call <...>");
|
||||
#ifdef INSN_SCHEDULING
|
||||
if (verbose && current_sched_info)
|
||||
sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (x, 1), t);
|
||||
sprintf (buf, "%s: %s", (*current_sched_info->print_insn) (insn, 1), t);
|
||||
else
|
||||
#endif
|
||||
sprintf (buf, " %4d %s", INSN_UID (insn), t);
|
||||
@ -702,7 +700,6 @@ print_insn (char *buf, rtx x, int verbose)
|
||||
}
|
||||
} /* print_insn */
|
||||
|
||||
|
||||
/* Emit a slim dump of X (an insn) to the file F, including any register
|
||||
note attached to the instruction. */
|
||||
void
|
||||
@ -736,10 +733,21 @@ debug_insn_slim (rtx x)
|
||||
void
|
||||
print_rtl_slim_with_bb (FILE *f, rtx first, int flags)
|
||||
{
|
||||
basic_block current_bb = NULL;
|
||||
rtx insn;
|
||||
print_rtl_slim (f, first, NULL, -1, flags);
|
||||
}
|
||||
|
||||
for (insn = first; NULL != insn; insn = NEXT_INSN (insn))
|
||||
/* Same as above, but stop at LAST or when COUNT == 0.
|
||||
If COUNT < 0 it will stop only at LAST or NULL rtx. */
|
||||
void
|
||||
print_rtl_slim (FILE *f, rtx first, rtx last, int count, int flags)
|
||||
{
|
||||
basic_block current_bb = NULL;
|
||||
rtx insn, tail;
|
||||
|
||||
tail = last ? NEXT_INSN (last) : NULL_RTX;
|
||||
for (insn = first;
|
||||
(insn != NULL) && (insn != tail) && (count != 0);
|
||||
insn = NEXT_INSN (insn))
|
||||
{
|
||||
if ((flags & TDF_BLOCKS)
|
||||
&& (INSN_P (insn) || GET_CODE (insn) == NOTE)
|
||||
@ -759,6 +767,21 @@ print_rtl_slim_with_bb (FILE *f, rtx first, int flags)
|
||||
dump_bb_info (current_bb, false, true, flags, ";; ", f);
|
||||
current_bb = NULL;
|
||||
}
|
||||
if (count > 0)
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
debug_bb_slim (struct basic_block_def *bb)
|
||||
{
|
||||
print_rtl_slim (stderr, BB_HEAD (bb), BB_END (bb), -1, 32);
|
||||
}
|
||||
|
||||
void
|
||||
debug_bb_n_slim (int n)
|
||||
{
|
||||
struct basic_block_def *bb = BASIC_BLOCK (n);
|
||||
debug_bb_slim (bb);
|
||||
}
|
||||
|
||||
|
945
gcc/sel-sched-dump.c
Normal file
945
gcc/sel-sched-dump.c
Normal file
@ -0,0 +1,945 @@
|
||||
/* Instruction scheduling pass. Log dumping infrastructure.
|
||||
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "toplev.h"
|
||||
#include "rtl.h"
|
||||
#include "tm_p.h"
|
||||
#include "hard-reg-set.h"
|
||||
#include "regs.h"
|
||||
#include "function.h"
|
||||
#include "flags.h"
|
||||
#include "insn-config.h"
|
||||
#include "insn-attr.h"
|
||||
#include "params.h"
|
||||
#include "output.h"
|
||||
#include "basic-block.h"
|
||||
#include "cselib.h"
|
||||
#include "sel-sched-ir.h"
|
||||
#include "sel-sched-dump.h"
|
||||
|
||||
|
||||
/* These variables control high-level pretty printing. */
|
||||
static int sel_dump_cfg_flags = SEL_DUMP_CFG_FLAGS;
|
||||
static int sel_debug_cfg_flags = SEL_DUMP_CFG_FLAGS;
|
||||
|
||||
/* True when a cfg should be dumped. */
|
||||
static bool sel_dump_cfg_p;
|
||||
|
||||
/* Variables that are used to build the cfg dump file name. */
|
||||
static const char * const sel_debug_cfg_root = "./";
|
||||
static const char * const sel_debug_cfg_root_postfix_default = "";
|
||||
static const char *sel_debug_cfg_root_postfix = "";
|
||||
static int sel_dump_cfg_fileno = -1;
|
||||
static int sel_debug_cfg_fileno = -1;
|
||||
|
||||
/* When this flag is on, we are dumping to the .dot file.
|
||||
When it is off, we are dumping to log.
|
||||
This is useful to differentiate formatting between log and .dot
|
||||
files. */
|
||||
bool sched_dump_to_dot_p = false;
|
||||
|
||||
/* Controls how insns from a fence list should be dumped. */
|
||||
static int dump_flist_insn_flags = (DUMP_INSN_UID | DUMP_INSN_BBN
|
||||
| DUMP_INSN_SEQNO);
|
||||
|
||||
|
||||
/* The variable used to hold the value of sched_dump when temporarily
|
||||
switching dump output to the other source, e.g. the .dot file. */
|
||||
static FILE *saved_sched_dump = NULL;
|
||||
|
||||
/* Switch sched_dump to TO. It must not be called twice. */
|
||||
static void
|
||||
switch_dump (FILE *to)
|
||||
{
|
||||
gcc_assert (saved_sched_dump == NULL);
|
||||
|
||||
saved_sched_dump = sched_dump;
|
||||
sched_dump = to;
|
||||
}
|
||||
|
||||
/* Restore previously switched dump. */
|
||||
static void
|
||||
restore_dump (void)
|
||||
{
|
||||
sched_dump = saved_sched_dump;
|
||||
saved_sched_dump = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Functions for dumping instructions, av sets, and exprs. */
|
||||
|
||||
/* Default flags for dumping insns. */
|
||||
static int dump_insn_rtx_flags = DUMP_INSN_RTX_PATTERN;
|
||||
|
||||
/* Default flags for dumping vinsns. */
|
||||
static int dump_vinsn_flags = (DUMP_VINSN_INSN_RTX | DUMP_VINSN_TYPE
|
||||
| DUMP_VINSN_COUNT);
|
||||
|
||||
/* Default flags for dumping expressions. */
|
||||
static int dump_expr_flags = DUMP_EXPR_ALL;
|
||||
|
||||
/* Default flags for dumping insns when debugging. */
|
||||
static int debug_insn_rtx_flags = DUMP_INSN_RTX_ALL;
|
||||
|
||||
/* Default flags for dumping vinsns when debugging. */
|
||||
static int debug_vinsn_flags = DUMP_VINSN_ALL;
|
||||
|
||||
/* Default flags for dumping expressions when debugging. */
|
||||
static int debug_expr_flags = DUMP_EXPR_ALL;
|
||||
|
||||
/* Controls how an insn from stream should be dumped when debugging. */
|
||||
static int debug_insn_flags = DUMP_INSN_ALL;
|
||||
|
||||
/* Print an rtx X. */
|
||||
void
|
||||
sel_print_rtl (rtx x)
|
||||
{
|
||||
print_rtl_single (sched_dump, x);
|
||||
}
|
||||
|
||||
/* Dump insn INSN honoring FLAGS. */
|
||||
void
|
||||
dump_insn_rtx_1 (rtx insn, int flags)
|
||||
{
|
||||
int all;
|
||||
|
||||
/* flags == -1 also means dumping all. */
|
||||
all = (flags & 1);;
|
||||
if (all)
|
||||
flags |= DUMP_INSN_RTX_ALL;
|
||||
|
||||
sel_print ("(");
|
||||
|
||||
if (flags & DUMP_INSN_RTX_UID)
|
||||
sel_print ("%d;", INSN_UID (insn));
|
||||
|
||||
if (flags & DUMP_INSN_RTX_PATTERN)
|
||||
{
|
||||
char buf[2048];
|
||||
|
||||
print_insn (buf, insn, 0);
|
||||
sel_print ("%s;", buf);
|
||||
}
|
||||
|
||||
if (flags & DUMP_INSN_RTX_BBN)
|
||||
{
|
||||
basic_block bb = BLOCK_FOR_INSN (insn);
|
||||
|
||||
sel_print ("bb:%d;", bb != NULL ? bb->index : -1);
|
||||
}
|
||||
|
||||
sel_print (")");
|
||||
}
|
||||
|
||||
|
||||
/* Dump INSN with default flags. */
|
||||
void
|
||||
dump_insn_rtx (rtx insn)
|
||||
{
|
||||
dump_insn_rtx_1 (insn, dump_insn_rtx_flags);
|
||||
}
|
||||
|
||||
|
||||
/* Dump INSN to stderr. */
|
||||
void
|
||||
debug_insn_rtx (rtx insn)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_insn_rtx_1 (insn, debug_insn_rtx_flags);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Dump vinsn VI honoring flags. */
|
||||
void
|
||||
dump_vinsn_1 (vinsn_t vi, int flags)
|
||||
{
|
||||
int all;
|
||||
|
||||
/* flags == -1 also means dumping all. */
|
||||
all = flags & 1;
|
||||
if (all)
|
||||
flags |= DUMP_VINSN_ALL;
|
||||
|
||||
sel_print ("(");
|
||||
|
||||
if (flags & DUMP_VINSN_INSN_RTX)
|
||||
dump_insn_rtx_1 (VINSN_INSN_RTX (vi), dump_insn_rtx_flags | all);
|
||||
|
||||
if (flags & DUMP_VINSN_TYPE)
|
||||
sel_print ("type:%s;", GET_RTX_NAME (VINSN_TYPE (vi)));
|
||||
|
||||
if (flags & DUMP_VINSN_COUNT)
|
||||
sel_print ("count:%d;", VINSN_COUNT (vi));
|
||||
|
||||
if (flags & DUMP_VINSN_COST)
|
||||
{
|
||||
int cost = vi->cost;
|
||||
|
||||
if (cost != -1)
|
||||
sel_print ("cost:%d;", cost);
|
||||
}
|
||||
|
||||
sel_print (")");
|
||||
}
|
||||
|
||||
/* Dump vinsn VI with default flags. */
|
||||
void
|
||||
dump_vinsn (vinsn_t vi)
|
||||
{
|
||||
dump_vinsn_1 (vi, dump_vinsn_flags);
|
||||
}
|
||||
|
||||
/* Dump vinsn VI to stderr. */
|
||||
void
|
||||
debug_vinsn (vinsn_t vi)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_vinsn_1 (vi, debug_vinsn_flags);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Dump EXPR honoring flags. */
|
||||
void
|
||||
dump_expr_1 (expr_t expr, int flags)
|
||||
{
|
||||
int all;
|
||||
|
||||
/* flags == -1 also means dumping all. */
|
||||
all = flags & 1;
|
||||
if (all)
|
||||
flags |= DUMP_EXPR_ALL;
|
||||
|
||||
sel_print ("[");
|
||||
|
||||
if (flags & DUMP_EXPR_VINSN)
|
||||
dump_vinsn_1 (EXPR_VINSN (expr), dump_vinsn_flags | all);
|
||||
|
||||
if (flags & DUMP_EXPR_SPEC)
|
||||
{
|
||||
int spec = EXPR_SPEC (expr);
|
||||
|
||||
if (spec != 0)
|
||||
sel_print ("spec:%d;", spec);
|
||||
}
|
||||
|
||||
if (flags & DUMP_EXPR_USEFULNESS)
|
||||
{
|
||||
int use = EXPR_USEFULNESS (expr);
|
||||
|
||||
if (use != REG_BR_PROB_BASE)
|
||||
sel_print ("use:%d;", use);
|
||||
}
|
||||
|
||||
if (flags & DUMP_EXPR_PRIORITY)
|
||||
sel_print ("prio:%d;", EXPR_PRIORITY (expr));
|
||||
|
||||
if (flags & DUMP_EXPR_SCHED_TIMES)
|
||||
{
|
||||
int times = EXPR_SCHED_TIMES (expr);
|
||||
|
||||
if (times != 0)
|
||||
sel_print ("times:%d;", times);
|
||||
}
|
||||
|
||||
if (flags & DUMP_EXPR_SPEC_DONE_DS)
|
||||
{
|
||||
ds_t spec_done_ds = EXPR_SPEC_DONE_DS (expr);
|
||||
|
||||
if (spec_done_ds != 0)
|
||||
sel_print ("ds:%d;", spec_done_ds);
|
||||
}
|
||||
|
||||
if (flags & DUMP_EXPR_ORIG_BB)
|
||||
{
|
||||
int orig_bb = EXPR_ORIG_BB_INDEX (expr);
|
||||
|
||||
if (orig_bb != 0)
|
||||
sel_print ("orig_bb:%d;", orig_bb);
|
||||
}
|
||||
|
||||
if (EXPR_TARGET_AVAILABLE (expr) < 1)
|
||||
sel_print ("target:%d;", EXPR_TARGET_AVAILABLE (expr));
|
||||
sel_print ("]");
|
||||
}
|
||||
|
||||
/* Dump expression EXPR with default flags. */
|
||||
void
|
||||
dump_expr (expr_t expr)
|
||||
{
|
||||
dump_expr_1 (expr, dump_expr_flags);
|
||||
}
|
||||
|
||||
/* Dump expression EXPR to stderr. */
|
||||
void
|
||||
debug_expr (expr_t expr)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_expr_1 (expr, debug_expr_flags);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Dump insn I honoring FLAGS. */
|
||||
void
|
||||
dump_insn_1 (insn_t i, int flags)
|
||||
{
|
||||
int all;
|
||||
|
||||
all = flags & 1;
|
||||
if (all)
|
||||
flags |= DUMP_INSN_ALL;
|
||||
|
||||
if (!sched_dump_to_dot_p)
|
||||
sel_print ("(");
|
||||
|
||||
if (flags & DUMP_INSN_EXPR)
|
||||
{
|
||||
dump_expr_1 (INSN_EXPR (i), dump_expr_flags | all);
|
||||
sel_print (";");
|
||||
}
|
||||
else if (flags & DUMP_INSN_PATTERN)
|
||||
{
|
||||
dump_insn_rtx_1 (i, DUMP_INSN_RTX_PATTERN | all);
|
||||
sel_print (";");
|
||||
}
|
||||
else if (flags & DUMP_INSN_UID)
|
||||
sel_print ("uid:%d;", INSN_UID (i));
|
||||
|
||||
if (flags & DUMP_INSN_SEQNO)
|
||||
sel_print ("seqno:%d;", INSN_SEQNO (i));
|
||||
|
||||
if (flags & DUMP_INSN_SCHED_CYCLE)
|
||||
{
|
||||
int cycle = INSN_SCHED_CYCLE (i);
|
||||
|
||||
if (cycle != 0)
|
||||
sel_print ("cycle:%d;", cycle);
|
||||
}
|
||||
|
||||
if (!sched_dump_to_dot_p)
|
||||
sel_print (")");
|
||||
}
|
||||
|
||||
/* Dump insn I with default flags. */
|
||||
void
|
||||
dump_insn (insn_t i)
|
||||
{
|
||||
dump_insn_1 (i, DUMP_INSN_EXPR | DUMP_INSN_SCHED_CYCLE);
|
||||
}
|
||||
|
||||
/* Dump INSN to stderr. */
|
||||
void
|
||||
debug_insn (insn_t insn)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_insn_1 (insn, debug_insn_flags);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Dumps av_set AV. */
|
||||
void
|
||||
dump_av_set (av_set_t av)
|
||||
{
|
||||
av_set_iterator i;
|
||||
expr_t expr;
|
||||
|
||||
if (!sched_dump_to_dot_p)
|
||||
sel_print ("{");
|
||||
|
||||
FOR_EACH_EXPR (expr, i, av)
|
||||
{
|
||||
dump_expr (expr);
|
||||
if (!sched_dump_to_dot_p)
|
||||
sel_print (" ");
|
||||
else
|
||||
sel_print ("\n");
|
||||
}
|
||||
|
||||
if (!sched_dump_to_dot_p)
|
||||
sel_print ("}");
|
||||
}
|
||||
|
||||
/* Dumps lvset LV. */
|
||||
void
|
||||
dump_lv_set (regset lv)
|
||||
{
|
||||
sel_print ("{");
|
||||
|
||||
/* This code was adapted from flow.c: dump_regset (). */
|
||||
if (lv == NULL)
|
||||
sel_print ("nil");
|
||||
else
|
||||
{
|
||||
unsigned i;
|
||||
reg_set_iterator rsi;
|
||||
int count = 0;
|
||||
|
||||
EXECUTE_IF_SET_IN_REG_SET (lv, 0, i, rsi)
|
||||
{
|
||||
sel_print (" %d", i);
|
||||
if (i < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
sel_print (" [%s]", reg_names[i]);
|
||||
++count;
|
||||
}
|
||||
|
||||
++count;
|
||||
|
||||
if (sched_dump_to_dot_p && count == 12)
|
||||
{
|
||||
count = 0;
|
||||
sel_print ("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sel_print ("}\n");
|
||||
}
|
||||
|
||||
/* Dumps a list of instructions pointed to by P. */
|
||||
static void
|
||||
dump_ilist (ilist_t p)
|
||||
{
|
||||
while (p)
|
||||
{
|
||||
dump_insn (ILIST_INSN (p));
|
||||
p = ILIST_NEXT (p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dumps a list of boundaries pointed to by BNDS. */
|
||||
void
|
||||
dump_blist (blist_t bnds)
|
||||
{
|
||||
for (; bnds; bnds = BLIST_NEXT (bnds))
|
||||
{
|
||||
bnd_t bnd = BLIST_BND (bnds);
|
||||
|
||||
sel_print ("[to: %d; ptr: ", INSN_UID (BND_TO (bnd)));
|
||||
dump_ilist (BND_PTR (bnd));
|
||||
sel_print ("] ");
|
||||
}
|
||||
}
|
||||
|
||||
/* Dumps a list of fences pointed to by L. */
|
||||
void
|
||||
dump_flist (flist_t l)
|
||||
{
|
||||
while (l)
|
||||
{
|
||||
dump_insn_1 (FENCE_INSN (FLIST_FENCE (l)), dump_flist_insn_flags);
|
||||
sel_print (" ");
|
||||
l = FLIST_NEXT (l);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dumps an insn vector SUCCS. */
|
||||
void
|
||||
dump_insn_vector (rtx_vec_t succs)
|
||||
{
|
||||
int i;
|
||||
rtx succ;
|
||||
|
||||
for (i = 0; VEC_iterate (rtx, succs, i, succ); i++)
|
||||
if (succ)
|
||||
dump_insn (succ);
|
||||
else
|
||||
sel_print ("NULL ");
|
||||
}
|
||||
|
||||
/* Dumps a hard reg set SET to FILE using PREFIX. */
|
||||
static void
|
||||
print_hard_reg_set (FILE *file, const char *prefix, HARD_REG_SET set)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf (file, "%s{ ", prefix);
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
{
|
||||
if (TEST_HARD_REG_BIT (set, i))
|
||||
fprintf (file, "%d ", i);
|
||||
}
|
||||
fprintf (file, "}\n");
|
||||
}
|
||||
|
||||
/* Dumps a hard reg set SET using PREFIX. */
|
||||
void
|
||||
dump_hard_reg_set (const char *prefix, HARD_REG_SET set)
|
||||
{
|
||||
print_hard_reg_set (sched_dump, prefix, set);
|
||||
}
|
||||
|
||||
/* Pretty print INSN. This is used as a hook. */
|
||||
const char *
|
||||
sel_print_insn (const_rtx insn, int aligned ATTRIBUTE_UNUSED)
|
||||
{
|
||||
static char buf[80];
|
||||
|
||||
/* '+' before insn means it is a new cycle start and it's not been
|
||||
scheduled yet. '>' - has been scheduled. */
|
||||
if (s_i_d && INSN_LUID (insn) > 0)
|
||||
if (GET_MODE (insn) == TImode)
|
||||
sprintf (buf, "%s %4d",
|
||||
INSN_SCHED_TIMES (insn) > 0 ? "> " : "< ",
|
||||
INSN_UID (insn));
|
||||
else
|
||||
sprintf (buf, "%s %4d",
|
||||
INSN_SCHED_TIMES (insn) > 0 ? "! " : " ",
|
||||
INSN_UID (insn));
|
||||
else
|
||||
if (GET_MODE (insn) == TImode)
|
||||
sprintf (buf, "+ %4d", INSN_UID (insn));
|
||||
else
|
||||
sprintf (buf, " %4d", INSN_UID (insn));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/* Functions for pretty printing of CFG. */
|
||||
|
||||
/* Replace all occurencies of STR1 to STR2 in BUF.
|
||||
The BUF must be large enough to hold the result. */
|
||||
static void
|
||||
replace_str_in_buf (char *buf, const char *str1, const char *str2)
|
||||
{
|
||||
int buf_len = strlen (buf);
|
||||
int str1_len = strlen (str1);
|
||||
int str2_len = strlen (str2);
|
||||
int diff = str2_len - str1_len;
|
||||
|
||||
char *p = buf;
|
||||
do
|
||||
{
|
||||
p = strstr (p, str1);
|
||||
if (p)
|
||||
{
|
||||
char *p1 = p + str1_len;
|
||||
/* Copy the rest of buf and '\0'. */
|
||||
int n = buf + buf_len - p1;
|
||||
int i;
|
||||
|
||||
/* Shift str by DIFF chars. */
|
||||
if (diff > 0)
|
||||
for (i = n; i >= 0; i--)
|
||||
p1[i + diff] = p1[i];
|
||||
else
|
||||
for (i = 0; i <= n; i++)
|
||||
p1[i + diff] = p1[i];
|
||||
|
||||
/* Copy str2. */
|
||||
for (i = 0; i < str2_len; i++)
|
||||
p[i] = str2[i];
|
||||
|
||||
p += str2_len;
|
||||
buf_len += diff;
|
||||
}
|
||||
|
||||
}
|
||||
while (p);
|
||||
}
|
||||
|
||||
/* Replace characters in BUF that have special meaning in .dot file. */
|
||||
void
|
||||
sel_prepare_string_for_dot_label (char *buf)
|
||||
{
|
||||
static char specials_from[7][2] = { "<", ">", "{", "|", "}", "\"",
|
||||
"\n" };
|
||||
static char specials_to[7][3] = { "\\<", "\\>", "\\{", "\\|", "\\}",
|
||||
"\\\"", "\\l" };
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
replace_str_in_buf (buf, specials_from[i], specials_to[i]);
|
||||
}
|
||||
|
||||
/* Dump INSN with FLAGS. */
|
||||
static void
|
||||
sel_dump_cfg_insn (insn_t insn, int flags)
|
||||
{
|
||||
int insn_flags = DUMP_INSN_UID | DUMP_INSN_PATTERN;
|
||||
|
||||
if (sched_luids != NULL && INSN_LUID (insn) > 0)
|
||||
{
|
||||
if (flags & SEL_DUMP_CFG_INSN_SEQNO)
|
||||
insn_flags |= DUMP_INSN_SEQNO | DUMP_INSN_SCHED_CYCLE | DUMP_INSN_EXPR;
|
||||
}
|
||||
|
||||
dump_insn_1 (insn, insn_flags);
|
||||
}
|
||||
|
||||
/* Dump E to the dot file F. */
|
||||
static void
|
||||
sel_dump_cfg_edge (FILE *f, edge e)
|
||||
{
|
||||
int w;
|
||||
const char *color;
|
||||
|
||||
if (e->flags & EDGE_FALLTHRU)
|
||||
{
|
||||
w = 10;
|
||||
color = ", color = red";
|
||||
}
|
||||
else if (e->src->next_bb == e->dest)
|
||||
{
|
||||
w = 3;
|
||||
color = ", color = blue";
|
||||
}
|
||||
else
|
||||
{
|
||||
w = 1;
|
||||
color = "";
|
||||
}
|
||||
|
||||
fprintf (f, "\tbb%d -> bb%d [weight = %d%s];\n",
|
||||
e->src->index, e->dest->index, w, color);
|
||||
}
|
||||
|
||||
|
||||
/* Return true if BB has a predesessor from current region.
|
||||
TODO: Either make this function to trace back through empty block
|
||||
or just remove those empty blocks. */
|
||||
static bool
|
||||
has_preds_in_current_region_p (basic_block bb)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
gcc_assert (!in_current_region_p (bb));
|
||||
|
||||
FOR_EACH_EDGE (e, ei, bb->preds)
|
||||
if (in_current_region_p (e->src))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Dump a cfg region to the dot file F honoring FLAGS. */
|
||||
static void
|
||||
sel_dump_cfg_2 (FILE *f, int flags)
|
||||
{
|
||||
basic_block bb;
|
||||
|
||||
sched_dump_to_dot_p = true;
|
||||
switch_dump (f);
|
||||
|
||||
fprintf (f, "digraph G {\n"
|
||||
"\tratio = 2.25;\n"
|
||||
"\tnode [shape = record, fontsize = 9];\n");
|
||||
|
||||
if (flags & SEL_DUMP_CFG_FUNCTION_NAME)
|
||||
fprintf (f, "function [label = \"%s\"];\n", current_function_name ());
|
||||
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
insn_t insn = BB_HEAD (bb);
|
||||
insn_t next_tail = NEXT_INSN (BB_END (bb));
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
bool in_region_p = ((flags & SEL_DUMP_CFG_CURRENT_REGION)
|
||||
&& in_current_region_p (bb));
|
||||
bool full_p = (!(flags & SEL_DUMP_CFG_CURRENT_REGION)
|
||||
|| in_region_p);
|
||||
bool some_p = full_p || has_preds_in_current_region_p (bb);
|
||||
const char *color;
|
||||
const char *style;
|
||||
|
||||
if (!some_p)
|
||||
continue;
|
||||
|
||||
if ((flags & SEL_DUMP_CFG_CURRENT_REGION)
|
||||
&& in_current_region_p (bb)
|
||||
&& BLOCK_TO_BB (bb->index) == 0)
|
||||
color = "color = green, ";
|
||||
else
|
||||
color = "";
|
||||
|
||||
if ((flags & SEL_DUMP_CFG_FENCES)
|
||||
&& in_region_p)
|
||||
{
|
||||
style = "";
|
||||
|
||||
if (!sel_bb_empty_p (bb))
|
||||
{
|
||||
bool first_p = true;
|
||||
insn_t tail = BB_END (bb);
|
||||
insn_t cur_insn;
|
||||
|
||||
cur_insn = bb_note (bb);
|
||||
|
||||
do
|
||||
{
|
||||
fence_t fence;
|
||||
|
||||
cur_insn = NEXT_INSN (cur_insn);
|
||||
fence = flist_lookup (fences, cur_insn);
|
||||
|
||||
if (fence != NULL)
|
||||
{
|
||||
if (!FENCE_SCHEDULED_P (fence))
|
||||
{
|
||||
if (first_p)
|
||||
color = "color = red, ";
|
||||
else
|
||||
color = "color = yellow, ";
|
||||
}
|
||||
else
|
||||
color = "color = blue, ";
|
||||
}
|
||||
|
||||
first_p = false;
|
||||
}
|
||||
while (cur_insn != tail);
|
||||
}
|
||||
}
|
||||
else if (!full_p)
|
||||
style = "style = dashed, ";
|
||||
else
|
||||
style = "";
|
||||
|
||||
fprintf (f, "\tbb%d [%s%slabel = \"{Basic block %d", bb->index,
|
||||
style, color, bb->index);
|
||||
|
||||
if ((flags & SEL_DUMP_CFG_BB_LOOP)
|
||||
&& bb->loop_father != NULL)
|
||||
fprintf (f, ", loop %d", bb->loop_father->num);
|
||||
|
||||
if (full_p
|
||||
&& (flags & SEL_DUMP_CFG_BB_NOTES_LIST))
|
||||
{
|
||||
insn_t notes = BB_NOTE_LIST (bb);
|
||||
|
||||
if (notes != NULL_RTX)
|
||||
{
|
||||
fprintf (f, "|");
|
||||
|
||||
/* For simplicity, we dump notes from note_list in reversed order
|
||||
to that what they will appear in the code. */
|
||||
while (notes != NULL_RTX)
|
||||
{
|
||||
sel_dump_cfg_insn (notes, flags);
|
||||
fprintf (f, "\\l");
|
||||
|
||||
notes = PREV_INSN (notes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (full_p
|
||||
&& (flags & SEL_DUMP_CFG_AV_SET)
|
||||
&& in_current_region_p (bb)
|
||||
&& !sel_bb_empty_p (bb))
|
||||
{
|
||||
fprintf (f, "|");
|
||||
|
||||
if (BB_AV_SET_VALID_P (bb))
|
||||
dump_av_set (BB_AV_SET (bb));
|
||||
else if (BB_AV_LEVEL (bb) == -1)
|
||||
fprintf (f, "AV_SET needs update");
|
||||
}
|
||||
|
||||
if ((flags & SEL_DUMP_CFG_LV_SET)
|
||||
&& !sel_bb_empty_p (bb))
|
||||
{
|
||||
fprintf (f, "|");
|
||||
|
||||
if (BB_LV_SET_VALID_P (bb))
|
||||
dump_lv_set (BB_LV_SET (bb));
|
||||
else
|
||||
fprintf (f, "LV_SET needs update");
|
||||
}
|
||||
|
||||
if (full_p
|
||||
&& (flags & SEL_DUMP_CFG_BB_INSNS))
|
||||
{
|
||||
fprintf (f, "|");
|
||||
while (insn != next_tail)
|
||||
{
|
||||
sel_dump_cfg_insn (insn, flags);
|
||||
fprintf (f, "\\l");
|
||||
|
||||
insn = NEXT_INSN (insn);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (f, "}\"];\n");
|
||||
|
||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||
if (full_p || in_current_region_p (e->dest))
|
||||
sel_dump_cfg_edge (f, e);
|
||||
}
|
||||
|
||||
fprintf (f, "}");
|
||||
|
||||
restore_dump ();
|
||||
sched_dump_to_dot_p = false;
|
||||
}
|
||||
|
||||
/* Dump a cfg region to the file specified by TAG honoring flags.
|
||||
The file is created by the function. */
|
||||
static void
|
||||
sel_dump_cfg_1 (const char *tag, int flags)
|
||||
{
|
||||
char *buf;
|
||||
int i;
|
||||
FILE *f;
|
||||
|
||||
++sel_dump_cfg_fileno;
|
||||
|
||||
if (!sel_dump_cfg_p)
|
||||
return;
|
||||
|
||||
i = 1 + snprintf (NULL, 0, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
|
||||
sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
|
||||
buf = XNEWVEC (char, i);
|
||||
snprintf (buf, i, "%s/%s%05d-%s.dot", sel_debug_cfg_root,
|
||||
sel_debug_cfg_root_postfix, sel_dump_cfg_fileno, tag);
|
||||
|
||||
f = fopen (buf, "w");
|
||||
|
||||
if (f == NULL)
|
||||
fprintf (stderr, "Can't create file: %s.\n", buf);
|
||||
else
|
||||
{
|
||||
sel_dump_cfg_2 (f, flags);
|
||||
|
||||
fclose (f);
|
||||
}
|
||||
|
||||
free (buf);
|
||||
}
|
||||
|
||||
/* Setup cfg dumping flags. Used for debugging. */
|
||||
void
|
||||
setup_dump_cfg_params (void)
|
||||
{
|
||||
sel_dump_cfg_flags = SEL_DUMP_CFG_FLAGS;
|
||||
sel_dump_cfg_p = 0;
|
||||
sel_debug_cfg_root_postfix = sel_debug_cfg_root_postfix_default;
|
||||
}
|
||||
|
||||
/* Debug a cfg region with FLAGS. */
|
||||
void
|
||||
sel_debug_cfg_1 (int flags)
|
||||
{
|
||||
bool t1 = sel_dump_cfg_p;
|
||||
int t2 = sel_dump_cfg_fileno;
|
||||
|
||||
sel_dump_cfg_p = true;
|
||||
sel_dump_cfg_fileno = ++sel_debug_cfg_fileno;
|
||||
|
||||
sel_dump_cfg_1 ("sel-debug-cfg", flags);
|
||||
|
||||
sel_dump_cfg_fileno = t2;
|
||||
sel_dump_cfg_p = t1;
|
||||
}
|
||||
|
||||
/* Dumps av_set AV to stderr. */
|
||||
void
|
||||
debug_av_set (av_set_t av)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_av_set (av);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Dump LV to stderr. */
|
||||
void
|
||||
debug_lv_set (regset lv)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_lv_set (lv);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Dump an instruction list P to stderr. */
|
||||
void
|
||||
debug_ilist (ilist_t p)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_ilist (p);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Dump a boundary list BNDS to stderr. */
|
||||
void
|
||||
debug_blist (blist_t bnds)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_blist (bnds);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Dump an insn vector SUCCS. */
|
||||
void
|
||||
debug_insn_vector (rtx_vec_t succs)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_insn_vector (succs);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Dump a hard reg set SET to stderr. */
|
||||
void
|
||||
debug_hard_reg_set (HARD_REG_SET set)
|
||||
{
|
||||
switch_dump (stderr);
|
||||
dump_hard_reg_set ("", set);
|
||||
sel_print ("\n");
|
||||
restore_dump ();
|
||||
}
|
||||
|
||||
/* Debug a cfg region with default flags. */
|
||||
void
|
||||
sel_debug_cfg (void)
|
||||
{
|
||||
sel_debug_cfg_1 (sel_debug_cfg_flags);
|
||||
}
|
||||
|
||||
/* Print a current cselib value for X's address to stderr. */
|
||||
rtx
|
||||
debug_mem_addr_value (rtx x)
|
||||
{
|
||||
rtx t, addr;
|
||||
|
||||
gcc_assert (MEM_P (x));
|
||||
t = shallow_copy_rtx (x);
|
||||
if (cselib_lookup (XEXP (t, 0), Pmode, 0))
|
||||
XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
|
||||
|
||||
t = canon_rtx (t);
|
||||
addr = get_addr (XEXP (t, 0));
|
||||
debug_rtx (t);
|
||||
debug_rtx (addr);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
241
gcc/sel-sched-dump.h
Normal file
241
gcc/sel-sched-dump.h
Normal file
@ -0,0 +1,241 @@
|
||||
/* Instruction scheduling pass. Log dumping infrastructure.
|
||||
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
#ifndef GCC_SEL_SCHED_DUMP_H
|
||||
#define GCC_SEL_SCHED_DUMP_H
|
||||
|
||||
#include "sel-sched-ir.h"
|
||||
|
||||
|
||||
/* These values control the dumping of control flow graph to the .dot file. */
|
||||
enum sel_dump_cfg_def
|
||||
{
|
||||
/* Dump only current region. */
|
||||
SEL_DUMP_CFG_CURRENT_REGION = 2,
|
||||
|
||||
/* Dump note_list for this bb. */
|
||||
SEL_DUMP_CFG_BB_NOTES_LIST = 4,
|
||||
|
||||
/* Dump availability set from the bb header. */
|
||||
SEL_DUMP_CFG_AV_SET = 8,
|
||||
|
||||
/* Dump liveness set from the bb header. */
|
||||
SEL_DUMP_CFG_LV_SET = 16,
|
||||
|
||||
/* Dump insns of the given block. */
|
||||
SEL_DUMP_CFG_BB_INSNS = 32,
|
||||
|
||||
/* Show current fences when dumping cfg. */
|
||||
SEL_DUMP_CFG_FENCES = 64,
|
||||
|
||||
/* Show insn's seqnos when dumping cfg. */
|
||||
SEL_DUMP_CFG_INSN_SEQNO = 128,
|
||||
|
||||
/* Dump function name when dumping cfg. */
|
||||
SEL_DUMP_CFG_FUNCTION_NAME = 256,
|
||||
|
||||
/* Dump loop father number of the given bb. */
|
||||
SEL_DUMP_CFG_BB_LOOP = 512,
|
||||
|
||||
/* The default flags for cfg dumping. */
|
||||
SEL_DUMP_CFG_FLAGS = (SEL_DUMP_CFG_CURRENT_REGION
|
||||
| SEL_DUMP_CFG_BB_NOTES_LIST
|
||||
| SEL_DUMP_CFG_AV_SET
|
||||
| SEL_DUMP_CFG_LV_SET
|
||||
| SEL_DUMP_CFG_BB_INSNS
|
||||
| SEL_DUMP_CFG_FENCES
|
||||
| SEL_DUMP_CFG_INSN_SEQNO
|
||||
| SEL_DUMP_CFG_BB_LOOP)
|
||||
};
|
||||
|
||||
/* These values control the dumping of insns containing in expressions. */
|
||||
enum dump_insn_rtx_def
|
||||
{
|
||||
/* Dump insn's UID. */
|
||||
DUMP_INSN_RTX_UID = 2,
|
||||
|
||||
/* Dump insn's pattern. */
|
||||
DUMP_INSN_RTX_PATTERN = 4,
|
||||
|
||||
/* Dump insn's basic block number. */
|
||||
DUMP_INSN_RTX_BBN = 8,
|
||||
|
||||
/* Dump all of the above. */
|
||||
DUMP_INSN_RTX_ALL = (DUMP_INSN_RTX_UID | DUMP_INSN_RTX_PATTERN
|
||||
| DUMP_INSN_RTX_BBN)
|
||||
};
|
||||
|
||||
extern void dump_insn_rtx_1 (rtx, int);
|
||||
extern void dump_insn_rtx (rtx);
|
||||
extern void debug_insn_rtx (rtx);
|
||||
|
||||
/* These values control dumping of vinsns. The meaning of different fields
|
||||
of a vinsn is explained in sel-sched-ir.h. */
|
||||
enum dump_vinsn_def
|
||||
{
|
||||
/* Dump the insn behind this vinsn. */
|
||||
DUMP_VINSN_INSN_RTX = 2,
|
||||
|
||||
/* Dump vinsn's type. */
|
||||
DUMP_VINSN_TYPE = 4,
|
||||
|
||||
/* Dump vinsn's count. */
|
||||
DUMP_VINSN_COUNT = 8,
|
||||
|
||||
/* Dump the cost (default latency) of the insn behind this vinsn. */
|
||||
DUMP_VINSN_COST = 16,
|
||||
|
||||
/* Dump all of the above. */
|
||||
DUMP_VINSN_ALL = (DUMP_VINSN_INSN_RTX | DUMP_VINSN_TYPE | DUMP_VINSN_COUNT
|
||||
| DUMP_VINSN_COST)
|
||||
};
|
||||
|
||||
extern void dump_vinsn_1 (vinsn_t, int);
|
||||
extern void dump_vinsn (vinsn_t);
|
||||
extern void debug_vinsn (vinsn_t);
|
||||
|
||||
/* These values control dumping of expressions. The meaning of the fields
|
||||
is explained in sel-sched-ir.h. */
|
||||
enum dump_expr_def
|
||||
{
|
||||
/* Dump the vinsn behind this expression. */
|
||||
DUMP_EXPR_VINSN = 2,
|
||||
|
||||
/* Dump expression's SPEC parameter. */
|
||||
DUMP_EXPR_SPEC = 4,
|
||||
|
||||
/* Dump expression's priority. */
|
||||
DUMP_EXPR_PRIORITY = 8,
|
||||
|
||||
/* Dump the number of times this expression was scheduled. */
|
||||
DUMP_EXPR_SCHED_TIMES = 16,
|
||||
|
||||
/* Dump speculative status of the expression. */
|
||||
DUMP_EXPR_SPEC_DONE_DS = 32,
|
||||
|
||||
/* Dump the basic block number which originated this expression. */
|
||||
DUMP_EXPR_ORIG_BB = 64,
|
||||
|
||||
/* Dump expression's usefulness. */
|
||||
DUMP_EXPR_USEFULNESS = 128,
|
||||
|
||||
/* Dump all of the above. */
|
||||
DUMP_EXPR_ALL = (DUMP_EXPR_VINSN | DUMP_EXPR_SPEC | DUMP_EXPR_PRIORITY
|
||||
| DUMP_EXPR_SCHED_TIMES | DUMP_EXPR_SPEC_DONE_DS
|
||||
| DUMP_EXPR_ORIG_BB | DUMP_EXPR_USEFULNESS)
|
||||
};
|
||||
|
||||
extern void dump_expr_1 (expr_t, int);
|
||||
extern void dump_expr (expr_t);
|
||||
extern void debug_expr (expr_t);
|
||||
|
||||
/* A enumeration for dumping flags of an insn. The difference from
|
||||
dump_insn_rtx_def is that these fields are for insns in stream only. */
|
||||
enum dump_insn_def
|
||||
{
|
||||
/* Dump expression of this insn. */
|
||||
DUMP_INSN_EXPR = 2,
|
||||
|
||||
/* Dump insn's seqno. */
|
||||
DUMP_INSN_SEQNO = 4,
|
||||
|
||||
/* Dump the cycle on which insn was scheduled. */
|
||||
DUMP_INSN_SCHED_CYCLE = 8,
|
||||
|
||||
/* Dump insn's UID. */
|
||||
DUMP_INSN_UID = 16,
|
||||
|
||||
/* Dump insn's pattern. */
|
||||
DUMP_INSN_PATTERN = 32,
|
||||
|
||||
/* Dump insn's basic block number. */
|
||||
DUMP_INSN_BBN = 64,
|
||||
|
||||
/* Dump all of the above. */
|
||||
DUMP_INSN_ALL = (DUMP_INSN_EXPR | DUMP_INSN_SEQNO | DUMP_INSN_BBN
|
||||
| DUMP_INSN_SCHED_CYCLE | DUMP_INSN_UID | DUMP_INSN_PATTERN)
|
||||
};
|
||||
|
||||
extern void dump_insn_1 (insn_t, int);
|
||||
extern void dump_insn (insn_t);
|
||||
extern void debug_insn (insn_t);
|
||||
|
||||
extern void sel_prepare_string_for_dot_label (char *);
|
||||
|
||||
/* When this flag is on, we are dumping to the .dot file.
|
||||
When it is off, we are dumping to log. */
|
||||
extern bool sched_dump_to_dot_p;
|
||||
|
||||
/* This macro acts like printf but dumps information to the .dot file.
|
||||
Used when dumping control flow. */
|
||||
#define sel_print_to_dot(...) \
|
||||
do { \
|
||||
int __j = 1 + 2 * snprintf (NULL, 0, __VA_ARGS__); \
|
||||
char *__s = XALLOCAVEC (char, __j); \
|
||||
snprintf (__s, __j, __VA_ARGS__); \
|
||||
sel_prepare_string_for_dot_label (__s); \
|
||||
fprintf (sched_dump, "%s", __s); \
|
||||
} while (0)
|
||||
|
||||
/* This macro acts like printf but dumps to the sched_dump file. */
|
||||
#define sel_print(...) \
|
||||
do { \
|
||||
if (sched_dump_to_dot_p) \
|
||||
sel_print_to_dot (__VA_ARGS__); \
|
||||
else \
|
||||
fprintf (sched_dump, __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Functions from sel-sched-dump.c. */
|
||||
extern const char * sel_print_insn (const_rtx, int);
|
||||
extern void free_sel_dump_data (void);
|
||||
|
||||
extern void block_start (void);
|
||||
extern void block_finish (void);
|
||||
extern int get_print_blocks_num (void);
|
||||
extern void line_start (void);
|
||||
extern void line_finish (void);
|
||||
|
||||
extern void sel_print_rtl (rtx x);
|
||||
extern void dump_insn_1 (insn_t, int);
|
||||
extern void dump_insn (insn_t);
|
||||
extern void dump_insn_vector (rtx_vec_t);
|
||||
extern void dump_expr (expr_t);
|
||||
extern void dump_used_regs (bitmap);
|
||||
extern void dump_av_set (av_set_t);
|
||||
extern void dump_lv_set (regset);
|
||||
extern void dump_blist (blist_t);
|
||||
extern void dump_flist (flist_t);
|
||||
extern void dump_hard_reg_set (const char *, HARD_REG_SET);
|
||||
extern void sel_debug_cfg_1 (int);
|
||||
extern void sel_debug_cfg (void);
|
||||
extern void setup_dump_cfg_params (void);
|
||||
|
||||
/* Debug functions. */
|
||||
extern void debug_expr (expr_t);
|
||||
extern void debug_av_set (av_set_t);
|
||||
extern void debug_lv_set (regset);
|
||||
extern void debug_ilist (ilist_t);
|
||||
extern void debug_blist (blist_t);
|
||||
extern void debug_insn_vector (rtx_vec_t);
|
||||
extern void debug_hard_reg_set (HARD_REG_SET);
|
||||
extern rtx debug_mem_addr_value (rtx);
|
||||
#endif
|
6049
gcc/sel-sched-ir.c
Normal file
6049
gcc/sel-sched-ir.c
Normal file
File diff suppressed because it is too large
Load Diff
1627
gcc/sel-sched-ir.h
Normal file
1627
gcc/sel-sched-ir.h
Normal file
File diff suppressed because it is too large
Load Diff
7327
gcc/sel-sched.c
Normal file
7327
gcc/sel-sched.c
Normal file
File diff suppressed because it is too large
Load Diff
27
gcc/sel-sched.h
Normal file
27
gcc/sel-sched.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* Instruction scheduling pass.
|
||||
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_SEL_SCHED_H
|
||||
#define GCC_SEL_SCHED_H
|
||||
|
||||
/* The main entry point. */
|
||||
extern void run_selective_scheduling (void);
|
||||
extern bool maybe_skip_selective_scheduling (void);
|
||||
|
||||
#endif /* GCC_SEL_SCHED_H */
|
@ -316,12 +316,21 @@
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD 0
|
||||
#define TARGET_SCHED_DFA_NEW_CYCLE 0
|
||||
#define TARGET_SCHED_IS_COSTLY_DEPENDENCE 0
|
||||
#define TARGET_SCHED_ADJUST_COST_2 0
|
||||
#define TARGET_SCHED_H_I_D_EXTENDED 0
|
||||
#define TARGET_SCHED_ALLOC_SCHED_CONTEXT 0
|
||||
#define TARGET_SCHED_INIT_SCHED_CONTEXT 0
|
||||
#define TARGET_SCHED_SET_SCHED_CONTEXT 0
|
||||
#define TARGET_SCHED_CLEAR_SCHED_CONTEXT 0
|
||||
#define TARGET_SCHED_FREE_SCHED_CONTEXT 0
|
||||
#define TARGET_SCHED_SPECULATE_INSN 0
|
||||
#define TARGET_SCHED_NEEDS_BLOCK_P 0
|
||||
#define TARGET_SCHED_GEN_CHECK 0
|
||||
#define TARGET_SCHED_GEN_SPEC_CHECK 0
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC 0
|
||||
#define TARGET_SCHED_SET_SCHED_FLAGS 0
|
||||
#define TARGET_SCHED_GET_INSN_SPEC_DS 0
|
||||
#define TARGET_SCHED_GET_INSN_CHECKED_DS 0
|
||||
#define TARGET_SCHED_SKIP_RTX_P 0
|
||||
#define TARGET_SCHED_SMS_RES_MII 0
|
||||
|
||||
#define TARGET_SCHED \
|
||||
@ -346,12 +355,21 @@
|
||||
TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD, \
|
||||
TARGET_SCHED_DFA_NEW_CYCLE, \
|
||||
TARGET_SCHED_IS_COSTLY_DEPENDENCE, \
|
||||
TARGET_SCHED_ADJUST_COST_2, \
|
||||
TARGET_SCHED_H_I_D_EXTENDED, \
|
||||
TARGET_SCHED_ALLOC_SCHED_CONTEXT, \
|
||||
TARGET_SCHED_INIT_SCHED_CONTEXT, \
|
||||
TARGET_SCHED_SET_SCHED_CONTEXT, \
|
||||
TARGET_SCHED_CLEAR_SCHED_CONTEXT, \
|
||||
TARGET_SCHED_FREE_SCHED_CONTEXT, \
|
||||
TARGET_SCHED_SPECULATE_INSN, \
|
||||
TARGET_SCHED_NEEDS_BLOCK_P, \
|
||||
TARGET_SCHED_GEN_CHECK, \
|
||||
TARGET_SCHED_GEN_SPEC_CHECK, \
|
||||
TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC, \
|
||||
TARGET_SCHED_SET_SCHED_FLAGS, \
|
||||
TARGET_SCHED_GET_INSN_SPEC_DS, \
|
||||
TARGET_SCHED_GET_INSN_CHECKED_DS, \
|
||||
TARGET_SCHED_SKIP_RTX_P, \
|
||||
TARGET_SCHED_SMS_RES_MII}
|
||||
|
||||
#define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD 0
|
||||
|
42
gcc/target.h
42
gcc/target.h
@ -274,7 +274,7 @@ struct gcc_target
|
||||
/* Finalize machine-dependent scheduling code. */
|
||||
void (* md_finish) (FILE *, int);
|
||||
|
||||
/* Initialize machine-dependent function while scheduling code. */
|
||||
/* Initialize machine-dependent function wide scheduling code. */
|
||||
void (* md_init_global) (FILE *, int, int);
|
||||
|
||||
/* Finalize machine-dependent function wide scheduling code. */
|
||||
@ -354,11 +354,33 @@ struct gcc_target
|
||||
second insn (second parameter). */
|
||||
bool (* is_costly_dependence) (struct _dep *_dep, int, int);
|
||||
|
||||
/* Given the current cost, COST, of an insn, INSN, calculate and
|
||||
return a new cost based on its relationship to DEP_INSN through the
|
||||
dependence of type DEP_TYPE. The default is to make no adjustment. */
|
||||
int (* adjust_cost_2) (rtx insn, int, rtx dep_insn, int cost, int dw);
|
||||
|
||||
/* The following member value is a pointer to a function called
|
||||
by the insn scheduler. This hook is called to notify the backend
|
||||
that new instructions were emitted. */
|
||||
void (* h_i_d_extended) (void);
|
||||
|
||||
|
||||
/* Next 5 functions are for multi-point scheduling. */
|
||||
|
||||
/* Allocate memory for scheduler context. */
|
||||
void *(* alloc_sched_context) (void);
|
||||
|
||||
/* Fills the context from the local machine scheduler context. */
|
||||
void (* init_sched_context) (void *, bool);
|
||||
|
||||
/* Sets local machine scheduler context to a saved value. */
|
||||
void (* set_sched_context) (void *);
|
||||
|
||||
/* Clears a scheduler context so it becomes like after init. */
|
||||
void (* clear_sched_context) (void *);
|
||||
|
||||
/* Frees the scheduler context. */
|
||||
void (* free_sched_context) (void *);
|
||||
|
||||
/* The following member value is a pointer to a function called
|
||||
by the insn scheduler.
|
||||
The first parameter is an instruction, the second parameter is the type
|
||||
@ -374,8 +396,7 @@ struct gcc_target
|
||||
|
||||
/* The following member value is a pointer to a function called
|
||||
by the insn scheduler. It should return true if the check instruction
|
||||
corresponding to the instruction passed as the parameter needs a
|
||||
recovery block. */
|
||||
passed as the parameter needs a recovery block. */
|
||||
bool (* needs_block_p) (const_rtx);
|
||||
|
||||
/* The following member value is a pointer to a function called
|
||||
@ -386,7 +407,7 @@ struct gcc_target
|
||||
simple check). If the mutation of the check is requested (e.g. from
|
||||
ld.c to chk.a), the third parameter is true - in this case the first
|
||||
parameter is the previous check. */
|
||||
rtx (* gen_check) (rtx, rtx, bool);
|
||||
rtx (* gen_spec_check) (rtx, rtx, bool);
|
||||
|
||||
/* The following member value is a pointer to a function controlling
|
||||
what insns from the ready insn queue will be considered for the
|
||||
@ -401,6 +422,17 @@ struct gcc_target
|
||||
The parameter is a pointer to spec_info variable. */
|
||||
void (* set_sched_flags) (struct spec_info_def *);
|
||||
|
||||
/* Return speculation types of the instruction passed as the parameter. */
|
||||
int (* get_insn_spec_ds) (rtx);
|
||||
|
||||
/* Return speculation types that are checked for the instruction passed as
|
||||
the parameter. */
|
||||
int (* get_insn_checked_ds) (rtx);
|
||||
|
||||
/* Return bool if rtx scanning should just skip current layer and
|
||||
advance to the inner rtxes. */
|
||||
bool (* skip_rtx_p) (const_rtx);
|
||||
|
||||
/* The following member value is a pointer to a function that provides
|
||||
information about the target resource-based lower bound which is
|
||||
used by the swing modulo scheduler. The parameter is a pointer
|
||||
|
@ -26,4 +26,7 @@ DEF_VEC_ALLOC_I(char,heap);
|
||||
DEF_VEC_I(int);
|
||||
DEF_VEC_ALLOC_I(int,heap);
|
||||
|
||||
DEF_VEC_I(unsigned);
|
||||
DEF_VEC_ALLOC_I(unsigned,heap);
|
||||
|
||||
#endif /* GCC_VECPRIM_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user