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:
Andrey Belevantsev 2008-09-01 12:57:00 +04:00 committed by Andrey Belevantsev
parent f57ca1ea5f
commit e855c69d16
46 changed files with 20882 additions and 1710 deletions

View File

@ -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.

View File

@ -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 \

View File

@ -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))

View File

@ -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 */

View File

@ -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 *

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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. */

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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.

View File

@ -3985,6 +3985,7 @@ emit_insn_after_1 (rtx first, rtx after, basic_block bb)
if (after == last_insn)
last_insn = last;
return last;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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");

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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"

View File

@ -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
}

View File

@ -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 ();
}

View File

@ -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);

View File

@ -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",

View File

@ -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

View File

@ -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);

View File

@ -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)
{

View File

@ -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
{

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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. */

File diff suppressed because it is too large Load Diff

View File

@ -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
View 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
View 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

File diff suppressed because it is too large Load Diff

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

File diff suppressed because it is too large Load Diff

27
gcc/sel-sched.h Normal file
View 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 */

View File

@ -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

View File

@ -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

View File

@ -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 */