mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-26 17:00:58 +08:00
genattr.c (struct range, [...]): Remove them.
2004-07-19 Paolo Bonzini <bonzini@gnu.org> * genattr.c (struct range, struct function_unit, write_units, extend_range, init_range): Remove them. (main): Remove code dealing with DEFINE_FUNCTION_UNIT. Output "#define INSN_SCHEDULING" here. * genattrtab.c (struct range, struct function_unit_op, struct function_unit, struct dimension, enum operator, operate_exp, expand_units, simplify_knowing, encode_units_mask, simplify_by_exploding, find_and_mark_used_attributes, unmark_used_attributes, add_values_to_cover, increment_current_value, test_for_current_value, simplify_with_current_value, simplify_with_current_value_aux, gen_unit, write_unit_name, write_function_unit_info, write_complex_function, write_toplevel_expr, find_single_value, extend_range): Remove. (write_attr_get): Do not handle common_av->value being an FFS. (struct attr_desc): Remove func_units_p and blockage_p. (write_attr_valueq): Do not handle them. (find_attr): Do not clear them. (make_internal_attr): Do not initialize them. (main): Remove code dealing with DEFINE_FUNCTION_UNIT. * sched-vis.c (init_target_units, insn_print_units, init_block_visualization, print_block_visualization, visualize_scheduled_insns, visualize_no_unit, visualize_stall_cycles, visualize_alloc, visualize_free, target_units, get_visual_tbl_length, MAX_VISUAL_LINES, INSN_LEN, n_visual_lines, visual_tbl_line_length, visual_tbl, n_vis_no_unit, MAX_VISUAL_NO_UNIT, vis_no_unit): Remove. * haifa-sched.c (blockage_range, clear_units, schedule_unit, actual_hazard, potential_hazard, insn_unit, unit_last_insn, unit_tick, actual_hazard_this_instance, potential_hazard, schedule_unit, max_insn_queue_index_value): Remove. (MAX_INSN_QUEUE_INDEX): Removed, renamed throughout to max_insn_queue_index. * rtl.def (DEFINE_FUNCTION_UNIT): Remove. * doc/md.texi (Processor pipeline description): Remove references to old pipeline descriptions. (Automaton pipeline description): Merge with the above. (Old pipeline description, Comparison of the two descriptions): Remove. * bt-load.c (migrate_btr_def): Remove references to use_pipeline_interface. * haifa-sched.c (insn_cost, schedule_insn, schedule_block, advance_one_cycle, sched_init, queue_to_ready, sched_finish): Likewise. * modulo-sched.c (sms_schedule, advance_one_cycle, ps_has_conflicts): Likewise. * sched-rgn.c (init_ready): Likewise. (debug_dependencies): Likewise, and remove an "if (1)". * target.h (use_dfa_pipeline_interface): Remove. * config/alpha/alpha.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/arc/arc.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/arm/arm.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/c4x/c4x.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/frv/frv.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/i386/i386.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/ia64/ia64.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/iq2000/iq2000.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/m32r/m32r.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/mcore/mcore.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/mips/mips.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/pa/pa.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/rs6000/rs6000.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/s390/s390.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/sh/sh.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/sparc/sparc.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/v850/v850.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * config/xtensa/xtensa.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. * doc/tm.texi (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove. From-SVN: r84944
This commit is contained in:
parent
31aedc36c0
commit
fa0aee8996
@ -1,3 +1,79 @@
|
||||
2004-07-19 Paolo Bonzini <bonzini@gnu.org>
|
||||
|
||||
* genattr.c (struct range, struct function_unit,
|
||||
write_units, extend_range, init_range): Remove them.
|
||||
(main): Remove code dealing with DEFINE_FUNCTION_UNIT.
|
||||
Output "#define INSN_SCHEDULING" here.
|
||||
* genattrtab.c (struct range, struct function_unit_op,
|
||||
struct function_unit, struct dimension, enum operator,
|
||||
operate_exp, expand_units, simplify_knowing,
|
||||
encode_units_mask, simplify_by_exploding,
|
||||
find_and_mark_used_attributes, unmark_used_attributes,
|
||||
add_values_to_cover, increment_current_value,
|
||||
test_for_current_value, simplify_with_current_value,
|
||||
simplify_with_current_value_aux, gen_unit,
|
||||
write_unit_name, write_function_unit_info,
|
||||
write_complex_function, write_toplevel_expr,
|
||||
find_single_value, extend_range): Remove.
|
||||
(write_attr_get): Do not handle common_av->value
|
||||
being an FFS.
|
||||
(struct attr_desc): Remove func_units_p and blockage_p.
|
||||
(write_attr_valueq): Do not handle them.
|
||||
(find_attr): Do not clear them.
|
||||
(make_internal_attr): Do not initialize them.
|
||||
(main): Remove code dealing with DEFINE_FUNCTION_UNIT.
|
||||
* sched-vis.c (init_target_units, insn_print_units,
|
||||
init_block_visualization, print_block_visualization,
|
||||
visualize_scheduled_insns, visualize_no_unit,
|
||||
visualize_stall_cycles, visualize_alloc,
|
||||
visualize_free, target_units, get_visual_tbl_length,
|
||||
MAX_VISUAL_LINES, INSN_LEN, n_visual_lines,
|
||||
visual_tbl_line_length, visual_tbl, n_vis_no_unit,
|
||||
MAX_VISUAL_NO_UNIT, vis_no_unit): Remove.
|
||||
* haifa-sched.c (blockage_range, clear_units,
|
||||
schedule_unit, actual_hazard, potential_hazard,
|
||||
insn_unit, unit_last_insn, unit_tick,
|
||||
actual_hazard_this_instance, potential_hazard,
|
||||
schedule_unit, max_insn_queue_index_value): Remove.
|
||||
(MAX_INSN_QUEUE_INDEX): Removed, renamed throughout to
|
||||
max_insn_queue_index.
|
||||
* rtl.def (DEFINE_FUNCTION_UNIT): Remove.
|
||||
* doc/md.texi (Processor pipeline description): Remove
|
||||
references to old pipeline descriptions.
|
||||
(Automaton pipeline description): Merge with the above.
|
||||
(Old pipeline description, Comparison of the two descriptions):
|
||||
Remove.
|
||||
|
||||
* bt-load.c (migrate_btr_def): Remove references to
|
||||
use_pipeline_interface.
|
||||
* haifa-sched.c (insn_cost, schedule_insn,
|
||||
schedule_block, advance_one_cycle, sched_init,
|
||||
queue_to_ready, sched_finish): Likewise.
|
||||
* modulo-sched.c (sms_schedule, advance_one_cycle,
|
||||
ps_has_conflicts): Likewise.
|
||||
* sched-rgn.c (init_ready): Likewise.
|
||||
(debug_dependencies): Likewise, and remove an "if (1)".
|
||||
* target.h (use_dfa_pipeline_interface): Remove.
|
||||
* config/alpha/alpha.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/arc/arc.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/arm/arm.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/c4x/c4x.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/frv/frv.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/i386/i386.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/ia64/ia64.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/iq2000/iq2000.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/m32r/m32r.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/mcore/mcore.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/mips/mips.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/pa/pa.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/rs6000/rs6000.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/s390/s390.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/sh/sh.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/sparc/sparc.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/v850/v850.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* config/xtensa/xtensa.c (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
* doc/tm.texi (TARGET_USE_DFA_PIPELINE_INTERFACE): Remove.
|
||||
|
||||
2004-07-19 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* rtlanal.c (reg_set_p): Add check for regs_invalidated_by_call.
|
||||
|
@ -1237,7 +1237,7 @@ migrate_btr_def (btr_def def, int min_cost)
|
||||
int give_up = 0;
|
||||
int def_moved = 0;
|
||||
btr_user user;
|
||||
int def_latency = 1;
|
||||
int def_latency;
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
@ -1267,14 +1267,11 @@ migrate_btr_def (btr_def def, int min_cost)
|
||||
bitmap_copy (live_range, def->live_range);
|
||||
|
||||
#ifdef INSN_SCHEDULING
|
||||
if (targetm.sched.use_dfa_pipeline_interface ())
|
||||
def_latency = insn_default_latency (def->insn);
|
||||
else
|
||||
def_latency = result_ready_cost (def->insn);
|
||||
def_latency = insn_default_latency (def->insn) * issue_rate;
|
||||
#else
|
||||
def_latency = issue_rate;
|
||||
#endif
|
||||
|
||||
def_latency *= issue_rate;
|
||||
|
||||
for (user = def->uses; user != NULL; user = user->next)
|
||||
{
|
||||
if (user->bb == def->bb
|
||||
|
@ -10152,8 +10152,6 @@ alpha_init_libfuncs (void)
|
||||
#define TARGET_SCHED_ADJUST_COST alpha_adjust_cost
|
||||
#undef TARGET_SCHED_ISSUE_RATE
|
||||
#define TARGET_SCHED_ISSUE_RATE alpha_issue_rate
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
|
||||
alpha_multipass_dfa_lookahead
|
||||
|
@ -146,9 +146,6 @@ static bool arc_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
|
||||
#undef TARGET_SETUP_INCOMING_VARARGS
|
||||
#define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Called by OVERRIDE_OPTIONS to initialize various things. */
|
||||
|
@ -214,9 +214,6 @@ static bool arm_cookie_has_size (void);
|
||||
#undef TARGET_SCHED_ADJUST_COST
|
||||
#define TARGET_SCHED_ADJUST_COST arm_adjust_cost
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
#undef TARGET_ENCODE_SECTION_INFO
|
||||
#ifdef ARM_PE
|
||||
#define TARGET_ENCODE_SECTION_INFO arm_pe_encode_section_info
|
||||
|
@ -237,9 +237,6 @@ static tree c4x_gimplify_va_arg_expr (tree, tree, tree *, tree *);
|
||||
#undef TARGET_SCHED_ADJUST_COST
|
||||
#define TARGET_SCHED_ADJUST_COST c4x_adjust_cost
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
#undef TARGET_ASM_GLOBALIZE_LABEL
|
||||
#define TARGET_ASM_GLOBALIZE_LABEL c4x_globalize_label
|
||||
|
||||
|
@ -319,8 +319,6 @@ static bool frv_must_pass_in_stack (enum machine_mode mode, tree type);
|
||||
|
||||
#undef TARGET_SCHED_ISSUE_RATE
|
||||
#define TARGET_SCHED_ISSUE_RATE frv_issue_rate
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
|
||||
#define TARGET_FUNCTION_OK_FOR_SIBCALL frv_function_ok_for_sibcall
|
||||
|
@ -1019,8 +1019,6 @@ static void init_ext_80387_constants (void);
|
||||
#define TARGET_SCHED_ADJUST_COST ix86_adjust_cost
|
||||
#undef TARGET_SCHED_ISSUE_RATE
|
||||
#define TARGET_SCHED_ISSUE_RATE ix86_issue_rate
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
|
||||
ia32_multipass_dfa_lookahead
|
||||
|
@ -342,9 +342,6 @@ static const struct attribute_spec ia64_attribute_table[] =
|
||||
#undef TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
|
||||
#define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK ia64_dependencies_evaluation_hook
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ia64_first_cycle_multipass_dfa_lookahead
|
||||
|
||||
|
@ -205,9 +205,6 @@ static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
|
||||
#undef TARGET_STRICT_ARGUMENT_NAMING
|
||||
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Return 1 if OP can be used as an operand where a register or 16 bit unsigned
|
||||
|
@ -123,8 +123,6 @@ static bool m32r_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
|
||||
#define TARGET_SCHED_ADJUST_PRIORITY m32r_adjust_priority
|
||||
#undef TARGET_SCHED_ISSUE_RATE
|
||||
#define TARGET_SCHED_ISSUE_RATE m32r_issue_rate
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
#undef TARGET_ENCODE_SECTION_INFO
|
||||
#define TARGET_ENCODE_SECTION_INFO m32r_encode_section_info
|
||||
|
@ -200,9 +200,6 @@ static bool mcore_return_in_memory (tree, tree);
|
||||
#undef TARGET_SETUP_INCOMING_VARARGS
|
||||
#define TARGET_SETUP_INCOMING_VARARGS mcore_setup_incoming_varargs
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
/* Adjust the stack and return the number of bytes taken to do it. */
|
||||
|
@ -652,8 +652,6 @@ const struct mips_cpu_info mips_cpu_info_table[] = {
|
||||
#define TARGET_SCHED_ADJUST_COST mips_adjust_cost
|
||||
#undef TARGET_SCHED_ISSUE_RATE
|
||||
#define TARGET_SCHED_ISSUE_RATE mips_issue_rate
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
|
||||
mips_multipass_dfa_lookahead
|
||||
|
@ -48,9 +48,6 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "target.h"
|
||||
#include "target-def.h"
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
/* Return nonzero if there is a bypass for the output of
|
||||
OUT_INSN and the fp store IN_INSN. */
|
||||
int
|
||||
|
@ -875,8 +875,6 @@ static const char alt_reg_names[][8] =
|
||||
#undef TARGET_ASM_FUNCTION_EPILOGUE
|
||||
#define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
#undef TARGET_SCHED_VARIABLE_ISSUE
|
||||
#define TARGET_SCHED_VARIABLE_ISSUE rs6000_variable_issue
|
||||
|
||||
|
@ -132,8 +132,6 @@ static bool s390_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode,
|
||||
#define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
|
||||
#undef TARGET_SCHED_ISSUE_RATE
|
||||
#define TARGET_SCHED_ISSUE_RATE s390_issue_rate
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD s390_first_cycle_multipass_dfa_lookahead
|
||||
|
||||
|
@ -321,9 +321,6 @@ static bool sh_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
|
||||
#undef TARGET_SCHED_ADJUST_COST
|
||||
#define TARGET_SCHED_ADJUST_COST sh_adjust_cost
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
#undef TARGET_SCHED_ISSUE_RATE
|
||||
#define TARGET_SCHED_ISSUE_RATE sh_issue_rate
|
||||
|
||||
|
@ -389,8 +389,6 @@ enum processor_type sparc_cpu;
|
||||
#define TARGET_SCHED_ISSUE_RATE sparc_issue_rate
|
||||
#undef TARGET_SCHED_INIT
|
||||
#define TARGET_SCHED_INIT sparc_sched_init
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
|
||||
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD sparc_use_sched_lookahead
|
||||
|
||||
|
@ -119,9 +119,6 @@ static int v850_interrupt_p = FALSE;
|
||||
#undef TARGET_ADDRESS_COST
|
||||
#define TARGET_ADDRESS_COST hook_int_rtx_0
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
#undef TARGET_MACHINE_DEPENDENT_REORG
|
||||
#define TARGET_MACHINE_DEPENDENT_REORG v850_reorg
|
||||
|
||||
|
@ -266,9 +266,6 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
|
||||
#undef TARGET_RETURN_IN_MSB
|
||||
#define TARGET_RETURN_IN_MSB xtensa_return_in_msb
|
||||
|
||||
#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE hook_int_void_1
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
||||
|
232
gcc/doc/md.texi
232
gcc/doc/md.texi
@ -5533,172 +5533,31 @@ processors.
|
||||
The task of exploiting more processor parallelism is solved by an
|
||||
instruction scheduler. For a better solution to this problem, the
|
||||
instruction scheduler has to have an adequate description of the
|
||||
processor parallelism (or @dfn{pipeline description}). Currently GCC
|
||||
provides two alternative ways to describe processor parallelism,
|
||||
both described below. The first method is outlined in the next section;
|
||||
it specifies functional unit reservations for groups of instructions
|
||||
with the aid of @dfn{regular expressions}. This is called the
|
||||
@dfn{automaton based description}. The second method is called the
|
||||
@dfn{old pipeline description}. This method specifies usage of
|
||||
function units for classes of insns. This description is not as
|
||||
powerful or accurate as the automaton based description, because it
|
||||
is impossible to model instructions that use more than one function
|
||||
unit. The second method is deprecated; new ports should use the
|
||||
automaton based description.
|
||||
processor parallelism (or @dfn{pipeline description}). GCC
|
||||
machine descriptions describe processor parallelism and functional
|
||||
unit reservations for groups of instructions with the aid of
|
||||
@dfn{regular expressions}.
|
||||
|
||||
The GCC instruction scheduler uses a @dfn{pipeline hazard recognizer} to
|
||||
figure out the possibility of the instruction issue by the processor
|
||||
on a given simulated processor cycle. The pipeline hazard recognizer is
|
||||
automatically generated from the processor pipeline description. The
|
||||
pipeline hazard recognizer generated from the automaton based
|
||||
description is more sophisticated and based on a deterministic finite
|
||||
state automaton (@acronym{DFA}) and therefore faster than one
|
||||
generated from the old description. Furthermore, its speed is not dependent
|
||||
on processor complexity. The instruction issue is possible if there is
|
||||
a transition from one automaton state to another one.
|
||||
pipeline hazard recognizer generated from the machine description
|
||||
is based on a deterministic finite state automaton (@acronym{DFA}):
|
||||
the instruction issue is possible if there is a transition from one
|
||||
automaton state to another one. This algorithm is very fast, and
|
||||
furthermore, its speed is not dependent on processor
|
||||
complexity@footnote{However, the size of the automaton depends on
|
||||
processor complexity. To limit this effect, machine descriptions
|
||||
can split orthogonal parts of the machine description among several
|
||||
automata: but then, since each of these must be stepped independently,
|
||||
this does cause a small decrease in the algorithm's performance.}.
|
||||
|
||||
@menu
|
||||
* Old pipeline description:: Specifying information for insn scheduling.
|
||||
* Automaton pipeline description:: Describing insn pipeline characteristics.
|
||||
* Comparison of the two descriptions:: Drawbacks of the old pipeline description
|
||||
@end menu
|
||||
|
||||
@end ifset
|
||||
@ifset INTERNALS
|
||||
@node Old pipeline description
|
||||
@subsubsection Specifying Function Units
|
||||
@cindex old pipeline description
|
||||
@cindex function units, for scheduling
|
||||
|
||||
@emph{Note:}The old pipeline description is deprecated.
|
||||
|
||||
On most @acronym{RISC} machines, there are instructions whose results
|
||||
are not available for a specific number of cycles. Common cases are
|
||||
instructions that load data from memory. On many machines, a pipeline
|
||||
stall will result if the data is referenced too soon after the load
|
||||
instruction.
|
||||
|
||||
In addition, many newer microprocessors have multiple function units, usually
|
||||
one for integer and one for floating point, and often will incur pipeline
|
||||
stalls when a result that is needed is not yet ready.
|
||||
|
||||
The descriptions in this section allow the specification of how much
|
||||
time must elapse between the execution of an instruction and the time
|
||||
when its result is used. It also allows specification of when the
|
||||
execution of an instruction will delay execution of similar instructions
|
||||
due to function unit conflicts.
|
||||
|
||||
For the purposes of the specifications in this section, a machine is
|
||||
divided into @dfn{function units}, each of which execute a specific
|
||||
class of instructions in first-in-first-out order. Function units
|
||||
that accept one instruction each cycle and allow a result to be used
|
||||
in the succeeding instruction (usually via forwarding) need not be
|
||||
specified. Classic @acronym{RISC} microprocessors will normally have
|
||||
a single function unit, which we can call @samp{memory}. The newer
|
||||
``superscalar'' processors will often have function units for floating
|
||||
point operations, usually at least a floating point adder and
|
||||
multiplier.
|
||||
|
||||
@findex define_function_unit
|
||||
Each usage of a function units by a class of insns is specified with a
|
||||
@code{define_function_unit} expression, which looks like this:
|
||||
|
||||
@smallexample
|
||||
(define_function_unit @var{name} @var{multiplicity} @var{simultaneity}
|
||||
@var{test} @var{ready-delay} @var{issue-delay}
|
||||
[@var{conflict-list}])
|
||||
@end smallexample
|
||||
|
||||
@var{name} is a string giving the name of the function unit.
|
||||
|
||||
@var{multiplicity} is an integer specifying the number of identical
|
||||
units in the processor. If more than one unit is specified, they will
|
||||
be scheduled independently. Only truly independent units should be
|
||||
counted; a pipelined unit should be specified as a single unit. (The
|
||||
only common example of a machine that has multiple function units for a
|
||||
single instruction class that are truly independent and not pipelined
|
||||
are the two multiply and two increment units of the CDC 6600.)
|
||||
|
||||
@var{simultaneity} specifies the maximum number of insns that can be
|
||||
executing in each instance of the function unit simultaneously or zero
|
||||
if the unit is pipelined and has no limit.
|
||||
|
||||
All @code{define_function_unit} definitions referring to function unit
|
||||
@var{name} must have the same name and values for @var{multiplicity} and
|
||||
@var{simultaneity}.
|
||||
|
||||
@var{test} is an attribute test that selects the insns we are describing
|
||||
in this definition. Note that an insn may use more than one function
|
||||
unit and a function unit may be specified in more than one
|
||||
@code{define_function_unit}.
|
||||
|
||||
@var{ready-delay} is an integer that specifies the number of cycles
|
||||
after which the result of the instruction can be used without
|
||||
introducing any stalls.
|
||||
|
||||
@var{issue-delay} is an integer that specifies the number of cycles
|
||||
after the instruction matching the @var{test} expression begins using
|
||||
this unit until a subsequent instruction can begin. A cost of @var{N}
|
||||
indicates an @var{N-1} cycle delay. A subsequent instruction may also
|
||||
be delayed if an earlier instruction has a longer @var{ready-delay}
|
||||
value. This blocking effect is computed using the @var{simultaneity},
|
||||
@var{ready-delay}, @var{issue-delay}, and @var{conflict-list} terms.
|
||||
For a normal non-pipelined function unit, @var{simultaneity} is one, the
|
||||
unit is taken to block for the @var{ready-delay} cycles of the executing
|
||||
insn, and smaller values of @var{issue-delay} are ignored.
|
||||
|
||||
@var{conflict-list} is an optional list giving detailed conflict costs
|
||||
for this unit. If specified, it is a list of condition test expressions
|
||||
to be applied to insns chosen to execute in @var{name} following the
|
||||
particular insn matching @var{test} that is already executing in
|
||||
@var{name}. For each insn in the list, @var{issue-delay} specifies the
|
||||
conflict cost; for insns not in the list, the cost is zero. If not
|
||||
specified, @var{conflict-list} defaults to all instructions that use the
|
||||
function unit.
|
||||
|
||||
Typical uses of this vector are where a floating point function unit can
|
||||
pipeline either single- or double-precision operations, but not both, or
|
||||
where a memory unit can pipeline loads, but not stores, etc.
|
||||
|
||||
As an example, consider a classic @acronym{RISC} machine where the
|
||||
result of a load instruction is not available for two cycles (a single
|
||||
``delay'' instruction is required) and where only one load instruction
|
||||
can be executed simultaneously. This would be specified as:
|
||||
|
||||
@smallexample
|
||||
(define_function_unit "memory" 1 1 (eq_attr "type" "load") 2 0)
|
||||
@end smallexample
|
||||
|
||||
For the case of a floating point function unit that can pipeline either
|
||||
single or double precision, but not both, the following could be specified:
|
||||
|
||||
@smallexample
|
||||
(define_function_unit
|
||||
"fp" 1 0 (eq_attr "type" "sp_fp") 4 4 [(eq_attr "type" "dp_fp")])
|
||||
(define_function_unit
|
||||
"fp" 1 0 (eq_attr "type" "dp_fp") 4 4 [(eq_attr "type" "sp_fp")])
|
||||
@end smallexample
|
||||
|
||||
@strong{Note:} The scheduler attempts to avoid function unit conflicts
|
||||
and uses all the specifications in the @code{define_function_unit}
|
||||
expression. It has recently been discovered that these
|
||||
specifications may not allow modeling of some of the newer
|
||||
``superscalar'' processors that have insns using multiple pipelined
|
||||
units. These insns will cause a potential conflict for the second unit
|
||||
used during their execution and there is no way of representing that
|
||||
conflict. Any examples of how function unit conflicts work
|
||||
in such processors and suggestions for their representation would be
|
||||
welcomed.
|
||||
|
||||
@end ifset
|
||||
@ifset INTERNALS
|
||||
@node Automaton pipeline description
|
||||
@subsubsection Describing instruction pipeline characteristics
|
||||
@cindex automaton based pipeline description
|
||||
|
||||
This section describes constructions of the automaton based processor
|
||||
pipeline description. The order of constructions within the machine
|
||||
description file is not important.
|
||||
The rest of this section describes the directives that constitute
|
||||
an automaton-based processor pipeline description. The order of
|
||||
these constructions within the machine description file is not
|
||||
important.
|
||||
|
||||
@findex define_automaton
|
||||
@cindex pipeline hazard recognizer
|
||||
@ -6114,61 +5973,6 @@ construction
|
||||
@end smallexample
|
||||
|
||||
|
||||
@end ifset
|
||||
@ifset INTERNALS
|
||||
@node Comparison of the two descriptions
|
||||
@subsubsection Drawbacks of the old pipeline description
|
||||
@cindex old pipeline description
|
||||
@cindex automaton based pipeline description
|
||||
@cindex processor functional units
|
||||
@cindex interlock delays
|
||||
@cindex instruction latency time
|
||||
@cindex pipeline hazard recognizer
|
||||
@cindex data bypass
|
||||
|
||||
The old instruction level parallelism description and the pipeline
|
||||
hazards recognizer based on it have the following drawbacks in
|
||||
comparison with the @acronym{DFA}-based ones:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Each functional unit is believed to be reserved at the instruction
|
||||
execution start. This is a very inaccurate model for modern
|
||||
processors.
|
||||
|
||||
@item
|
||||
An inadequate description of instruction latency times. The latency
|
||||
time is bound with a functional unit reserved by an instruction not
|
||||
with the instruction itself. In other words, the description is
|
||||
oriented to describe at most one unit reservation by each instruction.
|
||||
It also does not permit to describe special bypasses between
|
||||
instruction pairs.
|
||||
|
||||
@item
|
||||
The implementation of the pipeline hazard recognizer interface has
|
||||
constraints on number of functional units. This is a number of bits
|
||||
in integer on the host machine.
|
||||
|
||||
@item
|
||||
The interface to the pipeline hazard recognizer is more complex than
|
||||
one to the automaton based pipeline recognizer.
|
||||
|
||||
@item
|
||||
An unnatural description when you write a unit and a condition which
|
||||
selects instructions using the unit. Writing all unit reservations
|
||||
for an instruction (an instruction class) is more natural.
|
||||
|
||||
@item
|
||||
The recognition of the interlock delays has a slow implementation. The GCC
|
||||
scheduler supports structures which describe the unit reservations.
|
||||
The more functional units a processor has, the slower its pipeline hazard
|
||||
recognizer will be. Such an implementation would become even slower when we
|
||||
allowed to
|
||||
reserve functional units not only at the instruction execution start.
|
||||
In an automaton based pipeline hazard recognizer, speed is not dependent
|
||||
on processor complexity.
|
||||
@end itemize
|
||||
|
||||
@end ifset
|
||||
@ifset INTERNALS
|
||||
@node Conditional Execution
|
||||
|
@ -5542,8 +5542,8 @@ This value must be constant over the entire compilation. If you need
|
||||
it to vary depending on what the instructions are, you must use
|
||||
@samp{TARGET_SCHED_VARIABLE_ISSUE}.
|
||||
|
||||
For the automaton based pipeline interface, you could define this hook
|
||||
to return the value of the macro @code{MAX_DFA_ISSUE_RATE}.
|
||||
You could define this hook to return the value of the macro
|
||||
@code{MAX_DFA_ISSUE_RATE}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} int TARGET_SCHED_VARIABLE_ISSUE (FILE *@var{file}, int @var{verbose}, rtx @var{insn}, int @var{more})
|
||||
@ -5572,7 +5572,7 @@ description, the cost of anti-dependence is zero and the cost of
|
||||
output-dependence is maximum of one and the difference of latency
|
||||
times of the first and the second insns. If these values are not
|
||||
acceptable, you could use the hook to modify them too. See also
|
||||
@pxref{Automaton pipeline description}.
|
||||
@pxref{Processor pipeline description}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} int TARGET_SCHED_ADJUST_PRIORITY (rtx @var{insn}, int @var{priority})
|
||||
@ -5653,19 +5653,6 @@ This is the cleanup hook corresponding to TARGET_SCHED_INIT_GLOBAL.
|
||||
@var{verbose} is the verbose level provided by @option{-fsched-verbose-@var{n}}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} int TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE (void)
|
||||
This hook is called many times during insn scheduling. If the hook
|
||||
returns nonzero, the automaton based pipeline description is used for
|
||||
insn scheduling. Otherwise the traditional pipeline description is
|
||||
used. The default is usage of the traditional pipeline description.
|
||||
|
||||
You should also remember that to simplify the insn scheduler sources
|
||||
an empty traditional pipeline description interface is generated even
|
||||
if there is no a traditional pipeline description in the @file{.md}
|
||||
file. The same is true for the automaton based pipeline description.
|
||||
That means that you should be accurate in defining the hook.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} int TARGET_SCHED_DFA_PRE_CYCLE_INSN (void)
|
||||
The hook returns an RTL insn. The automaton state used in the
|
||||
pipeline hazard recognizer is changed as if the insn were scheduled
|
||||
|
178
gcc/genattr.c
178
gcc/genattr.c
@ -30,48 +30,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "gensupport.h"
|
||||
|
||||
|
||||
/* A range of values. */
|
||||
|
||||
struct range
|
||||
{
|
||||
int min;
|
||||
int max;
|
||||
};
|
||||
|
||||
/* Record information about each function unit mentioned in a
|
||||
DEFINE_FUNCTION_UNIT. */
|
||||
|
||||
struct function_unit
|
||||
{
|
||||
char *name; /* Function unit name. */
|
||||
struct function_unit *next; /* Next function unit. */
|
||||
int multiplicity; /* Number of units of this type. */
|
||||
int simultaneity; /* Maximum number of simultaneous insns
|
||||
on this function unit or 0 if unlimited. */
|
||||
struct range ready_cost; /* Range of ready cost values. */
|
||||
struct range issue_delay; /* Range of issue delay values. */
|
||||
};
|
||||
|
||||
static void extend_range (struct range *, int, int);
|
||||
static void init_range (struct range *);
|
||||
static void write_upcase (const char *);
|
||||
static void gen_attr (rtx);
|
||||
static void write_units (int, struct range *, struct range *,
|
||||
struct range *, struct range *,
|
||||
struct range *);
|
||||
static void
|
||||
extend_range (struct range *range, int min, int max)
|
||||
{
|
||||
if (range->min > min) range->min = min;
|
||||
if (range->max < max) range->max = max;
|
||||
}
|
||||
|
||||
static void
|
||||
init_range (struct range *range)
|
||||
{
|
||||
range->min = 100000;
|
||||
range->max = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
write_upcase (const char *str)
|
||||
@ -125,53 +85,6 @@ extern int insn_current_length (rtx);\n\n\
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_units (int num_units, struct range *multiplicity, struct range *simultaneity,
|
||||
struct range *ready_cost, struct range *issue_delay,
|
||||
struct range *blockage)
|
||||
{
|
||||
int i, q_size;
|
||||
|
||||
printf ("#define INSN_SCHEDULING\n\n");
|
||||
printf ("extern int result_ready_cost (rtx);\n");
|
||||
printf ("extern int function_units_used (rtx);\n\n");
|
||||
printf ("extern const struct function_unit_desc\n");
|
||||
printf ("{\n");
|
||||
printf (" const char *const name;\n");
|
||||
printf (" const int bitmask;\n");
|
||||
printf (" const int multiplicity;\n");
|
||||
printf (" const int simultaneity;\n");
|
||||
printf (" const int default_cost;\n");
|
||||
printf (" const int max_issue_delay;\n");
|
||||
printf (" int (*const ready_cost_function) (rtx);\n");
|
||||
printf (" int (*const conflict_cost_function) (rtx, rtx);\n");
|
||||
printf (" const int max_blockage;\n");
|
||||
printf (" unsigned int (*const blockage_range_function) (rtx);\n");
|
||||
printf (" int (*const blockage_function) (rtx, rtx);\n");
|
||||
printf ("} function_units[];\n\n");
|
||||
printf ("#define FUNCTION_UNITS_SIZE %d\n", num_units);
|
||||
printf ("#define MIN_MULTIPLICITY %d\n", multiplicity->min);
|
||||
printf ("#define MAX_MULTIPLICITY %d\n", multiplicity->max);
|
||||
printf ("#define MIN_SIMULTANEITY %d\n", simultaneity->min);
|
||||
printf ("#define MAX_SIMULTANEITY %d\n", simultaneity->max);
|
||||
printf ("#define MIN_READY_COST %d\n", ready_cost->min);
|
||||
printf ("#define MAX_READY_COST %d\n", ready_cost->max);
|
||||
printf ("#define MIN_ISSUE_DELAY %d\n", issue_delay->min);
|
||||
printf ("#define MAX_ISSUE_DELAY %d\n", issue_delay->max);
|
||||
printf ("#define MIN_BLOCKAGE %d\n", blockage->min);
|
||||
printf ("#define MAX_BLOCKAGE %d\n", blockage->max);
|
||||
for (i = 0; (1 << i) < blockage->max; i++)
|
||||
;
|
||||
printf ("#define BLOCKAGE_BITS %d\n", i + 1);
|
||||
|
||||
/* INSN_QUEUE_SIZE is a power of two larger than MAX_BLOCKAGE and
|
||||
MAX_READY_COST. This is the longest time an insn may be queued. */
|
||||
i = MAX (blockage->max, ready_cost->max);
|
||||
for (q_size = 1; q_size <= i; q_size <<= 1)
|
||||
;
|
||||
printf ("#define INSN_QUEUE_SIZE %d\n", q_size);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@ -180,18 +93,8 @@ main (int argc, char **argv)
|
||||
int have_annul_true = 0;
|
||||
int have_annul_false = 0;
|
||||
int num_insn_reservations = 0;
|
||||
int num_units = 0;
|
||||
struct range all_simultaneity, all_multiplicity;
|
||||
struct range all_ready_cost, all_issue_delay, all_blockage;
|
||||
struct function_unit *units = 0, *unit;
|
||||
int i;
|
||||
|
||||
init_range (&all_multiplicity);
|
||||
init_range (&all_simultaneity);
|
||||
init_range (&all_ready_cost);
|
||||
init_range (&all_issue_delay);
|
||||
init_range (&all_blockage);
|
||||
|
||||
progname = "genattr";
|
||||
|
||||
if (argc <= 1)
|
||||
@ -253,92 +156,15 @@ main (int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT)
|
||||
{
|
||||
const char *name = XSTR (desc, 0);
|
||||
int multiplicity = XINT (desc, 1);
|
||||
int simultaneity = XINT (desc, 2);
|
||||
int ready_cost = MAX (XINT (desc, 4), 1);
|
||||
int issue_delay = MAX (XINT (desc, 5), 1);
|
||||
int issueexp_p = (XVEC (desc, 6) != 0);
|
||||
|
||||
for (unit = units; unit; unit = unit->next)
|
||||
if (strcmp (unit->name, name) == 0)
|
||||
break;
|
||||
|
||||
if (unit == 0)
|
||||
{
|
||||
unit = xmalloc (sizeof (struct function_unit));
|
||||
unit->name = xstrdup (name);
|
||||
unit->multiplicity = multiplicity;
|
||||
unit->simultaneity = simultaneity;
|
||||
unit->ready_cost.min = unit->ready_cost.max = ready_cost;
|
||||
unit->issue_delay.min = unit->issue_delay.max = issue_delay;
|
||||
unit->next = units;
|
||||
units = unit;
|
||||
num_units++;
|
||||
|
||||
extend_range (&all_multiplicity, multiplicity, multiplicity);
|
||||
extend_range (&all_simultaneity, simultaneity, simultaneity);
|
||||
}
|
||||
else if (unit->multiplicity != multiplicity
|
||||
|| unit->simultaneity != simultaneity)
|
||||
fatal ("Differing specifications given for `%s' function unit",
|
||||
unit->name);
|
||||
|
||||
extend_range (&unit->ready_cost, ready_cost, ready_cost);
|
||||
extend_range (&unit->issue_delay,
|
||||
issueexp_p ? 1 : issue_delay, issue_delay);
|
||||
extend_range (&all_ready_cost,
|
||||
unit->ready_cost.min, unit->ready_cost.max);
|
||||
extend_range (&all_issue_delay,
|
||||
unit->issue_delay.min, unit->issue_delay.max);
|
||||
}
|
||||
else if (GET_CODE (desc) == DEFINE_INSN_RESERVATION)
|
||||
num_insn_reservations++;
|
||||
}
|
||||
|
||||
if (num_units > 0 || num_insn_reservations > 0)
|
||||
if (num_insn_reservations > 0)
|
||||
{
|
||||
/* Compute the range of blockage cost values. See genattrtab.c
|
||||
for the derivation. BLOCKAGE (E,C) when SIMULTANEITY is zero is
|
||||
|
||||
MAX (ISSUE-DELAY (E,C),
|
||||
READY-COST (E) - (READY-COST (C) - 1))
|
||||
|
||||
and otherwise
|
||||
|
||||
MAX (ISSUE-DELAY (E,C),
|
||||
READY-COST (E) - (READY-COST (C) - 1),
|
||||
READY-COST (E) - FILL-TIME) */
|
||||
|
||||
for (unit = units; unit; unit = unit->next)
|
||||
{
|
||||
struct range blockage;
|
||||
|
||||
blockage = unit->issue_delay;
|
||||
blockage.max = MAX (unit->ready_cost.max
|
||||
- (unit->ready_cost.min - 1),
|
||||
blockage.max);
|
||||
blockage.min = MAX (1, blockage.min);
|
||||
|
||||
if (unit->simultaneity != 0)
|
||||
{
|
||||
int fill_time = ((unit->simultaneity - 1)
|
||||
* unit->issue_delay.min);
|
||||
blockage.min = MAX (unit->ready_cost.min - fill_time,
|
||||
blockage.min);
|
||||
blockage.max = MAX (unit->ready_cost.max - fill_time,
|
||||
blockage.max);
|
||||
}
|
||||
extend_range (&all_blockage, blockage.min, blockage.max);
|
||||
}
|
||||
|
||||
write_units (num_units, &all_multiplicity, &all_simultaneity,
|
||||
&all_ready_cost, &all_issue_delay, &all_blockage);
|
||||
|
||||
/* Output interface for pipeline hazards recognition based on
|
||||
DFA (deterministic finite state automata. */
|
||||
printf ("\n#define INSN_SCHEDULING\n");
|
||||
printf ("\n/* DFA based pipeline interface. */");
|
||||
printf ("\n#ifndef AUTOMATON_ALTS\n");
|
||||
printf ("#define AUTOMATON_ALTS 0\n");
|
||||
|
1651
gcc/genattrtab.c
1651
gcc/genattrtab.c
File diff suppressed because it is too large
Load Diff
@ -54,13 +54,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
as short as possible. The remaining insns are then scheduled in
|
||||
remaining slots.
|
||||
|
||||
Function unit conflicts are resolved during forward list scheduling
|
||||
by tracking the time when each insn is committed to the schedule
|
||||
and from that, the time the function units it uses must be free.
|
||||
As insns on the ready list are considered for scheduling, those
|
||||
that would result in a blockage of the already committed insns are
|
||||
queued until no blockage will result.
|
||||
|
||||
The following list shows the order in which we want to break ties
|
||||
among insns in the ready list:
|
||||
|
||||
@ -225,9 +218,7 @@ static rtx note_list;
|
||||
"Pending" list have their dependencies satisfied and move to either
|
||||
the "Ready" list or the "Queued" set depending on whether
|
||||
sufficient time has passed to make them ready. As time passes,
|
||||
insns move from the "Queued" set to the "Ready" list. Insns may
|
||||
move from the "Ready" list to the "Queued" set if they are blocked
|
||||
due to a function unit conflict.
|
||||
insns move from the "Queued" set to the "Ready" list.
|
||||
|
||||
The "Pending" list (P) are the insns in the INSN_DEPEND of the unscheduled
|
||||
insns, i.e., those that are ready, queued, and pending.
|
||||
@ -238,43 +229,30 @@ static rtx note_list;
|
||||
|
||||
The transition (R->S) is implemented in the scheduling loop in
|
||||
`schedule_block' when the best insn to schedule is chosen.
|
||||
The transition (R->Q) is implemented in `queue_insn' when an
|
||||
insn is found to have a function unit conflict with the already
|
||||
committed insns.
|
||||
The transitions (P->R and P->Q) are implemented in `schedule_insn' as
|
||||
insns move from the ready list to the scheduled list.
|
||||
The transition (Q->R) is implemented in 'queue_to_insn' as time
|
||||
passes or stalls are introduced. */
|
||||
|
||||
/* Implement a circular buffer to delay instructions until sufficient
|
||||
time has passed. For the old pipeline description interface,
|
||||
INSN_QUEUE_SIZE is a power of two larger than MAX_BLOCKAGE and
|
||||
MAX_READY_COST computed by genattr.c. For the new pipeline
|
||||
description interface, MAX_INSN_QUEUE_INDEX is a power of two minus
|
||||
one which is larger than maximal time of instruction execution
|
||||
computed by genattr.c on the base maximal time of functional unit
|
||||
reservations and getting a result. This is the longest time an
|
||||
insn may be queued. */
|
||||
|
||||
#define MAX_INSN_QUEUE_INDEX max_insn_queue_index_macro_value
|
||||
time has passed. For the new pipeline description interface,
|
||||
MAX_INSN_QUEUE_INDEX is a power of two minus one which is larger
|
||||
than maximal time of instruction execution computed by genattr.c on
|
||||
the base maximal time of functional unit reservations and getting a
|
||||
result. This is the longest time an insn may be queued. */
|
||||
|
||||
static rtx *insn_queue;
|
||||
static int q_ptr = 0;
|
||||
static int q_size = 0;
|
||||
#define NEXT_Q(X) (((X)+1) & MAX_INSN_QUEUE_INDEX)
|
||||
#define NEXT_Q_AFTER(X, C) (((X)+C) & MAX_INSN_QUEUE_INDEX)
|
||||
|
||||
/* The following variable defines value for macro
|
||||
MAX_INSN_QUEUE_INDEX. */
|
||||
static int max_insn_queue_index_macro_value;
|
||||
#define NEXT_Q(X) (((X)+1) & max_insn_queue_index)
|
||||
#define NEXT_Q_AFTER(X, C) (((X)+C) & max_insn_queue_index)
|
||||
|
||||
/* The following variable value refers for all current and future
|
||||
reservations of the processor units. */
|
||||
state_t curr_state;
|
||||
|
||||
/* The following variable value is size of memory representing all
|
||||
current and future reservations of the processor units. It is used
|
||||
only by DFA based scheduler. */
|
||||
current and future reservations of the processor units. */
|
||||
static size_t dfa_state_size;
|
||||
|
||||
/* The following array is used to find the best insn from ready when
|
||||
@ -460,14 +438,6 @@ haifa_classify_insn (rtx insn)
|
||||
|
||||
/* Forward declarations. */
|
||||
|
||||
/* The scheduler using only DFA description should never use the
|
||||
following five functions: */
|
||||
static unsigned int blockage_range (int, rtx);
|
||||
static void clear_units (void);
|
||||
static void schedule_unit (int, rtx, int);
|
||||
static int actual_hazard (int, rtx, int, int);
|
||||
static int potential_hazard (int, rtx, int);
|
||||
|
||||
static int priority (rtx);
|
||||
static int rank_for_schedule (const void *, const void *);
|
||||
static void swap_sort (rtx *, int);
|
||||
@ -518,7 +488,7 @@ static rtx move_insn1 (rtx, rtx);
|
||||
static rtx move_insn (rtx, rtx);
|
||||
|
||||
/* The following functions are used to implement multi-pass scheduling
|
||||
on the first cycle. It is used only for DFA based scheduler. */
|
||||
on the first cycle. */
|
||||
static rtx ready_element (struct ready_list *, int);
|
||||
static rtx ready_remove (struct ready_list *, int);
|
||||
static int max_issue (struct ready_list *, int *);
|
||||
@ -543,309 +513,6 @@ schedule_insns (FILE *dump_file ATTRIBUTE_UNUSED)
|
||||
|
||||
static rtx last_scheduled_insn;
|
||||
|
||||
/* Compute the function units used by INSN. This caches the value
|
||||
returned by function_units_used. A function unit is encoded as the
|
||||
unit number if the value is non-negative and the complement of a
|
||||
mask if the value is negative. A function unit index is the
|
||||
non-negative encoding. The scheduler using only DFA description
|
||||
should never use the following function. */
|
||||
|
||||
HAIFA_INLINE int
|
||||
insn_unit (rtx insn)
|
||||
{
|
||||
int unit = INSN_UNIT (insn);
|
||||
|
||||
if (unit == 0)
|
||||
{
|
||||
recog_memoized (insn);
|
||||
|
||||
/* A USE insn, or something else we don't need to understand.
|
||||
We can't pass these directly to function_units_used because it will
|
||||
trigger a fatal error for unrecognizable insns. */
|
||||
if (INSN_CODE (insn) < 0)
|
||||
unit = -1;
|
||||
else
|
||||
{
|
||||
unit = function_units_used (insn);
|
||||
/* Increment non-negative values so we can cache zero. */
|
||||
if (unit >= 0)
|
||||
unit++;
|
||||
}
|
||||
/* We only cache 16 bits of the result, so if the value is out of
|
||||
range, don't cache it. */
|
||||
if (FUNCTION_UNITS_SIZE < HOST_BITS_PER_SHORT
|
||||
|| unit >= 0
|
||||
|| (unit & ~((1 << (HOST_BITS_PER_SHORT - 1)) - 1)) == 0)
|
||||
INSN_UNIT (insn) = unit;
|
||||
}
|
||||
return (unit > 0 ? unit - 1 : unit);
|
||||
}
|
||||
|
||||
/* Compute the blockage range for executing INSN on UNIT. This caches
|
||||
the value returned by the blockage_range_function for the unit.
|
||||
These values are encoded in an int where the upper half gives the
|
||||
minimum value and the lower half gives the maximum value. The
|
||||
scheduler using only DFA description should never use the following
|
||||
function. */
|
||||
|
||||
HAIFA_INLINE static unsigned int
|
||||
blockage_range (int unit, rtx insn)
|
||||
{
|
||||
unsigned int blockage = INSN_BLOCKAGE (insn);
|
||||
unsigned int range;
|
||||
|
||||
if ((int) UNIT_BLOCKED (blockage) != unit + 1)
|
||||
{
|
||||
range = function_units[unit].blockage_range_function (insn);
|
||||
/* We only cache the blockage range for one unit and then only if
|
||||
the values fit. */
|
||||
if (HOST_BITS_PER_INT >= UNIT_BITS + 2 * BLOCKAGE_BITS)
|
||||
INSN_BLOCKAGE (insn) = ENCODE_BLOCKAGE (unit + 1, range);
|
||||
}
|
||||
else
|
||||
range = BLOCKAGE_RANGE (blockage);
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
/* A vector indexed by function unit instance giving the last insn to
|
||||
use the unit. The value of the function unit instance index for
|
||||
unit U instance I is (U + I * FUNCTION_UNITS_SIZE). The scheduler
|
||||
using only DFA description should never use the following variable. */
|
||||
#if FUNCTION_UNITS_SIZE
|
||||
static rtx unit_last_insn[FUNCTION_UNITS_SIZE * MAX_MULTIPLICITY];
|
||||
#else
|
||||
static rtx unit_last_insn[1];
|
||||
#endif
|
||||
|
||||
/* A vector indexed by function unit instance giving the minimum time
|
||||
when the unit will unblock based on the maximum blockage cost. The
|
||||
scheduler using only DFA description should never use the following
|
||||
variable. */
|
||||
#if FUNCTION_UNITS_SIZE
|
||||
static int unit_tick[FUNCTION_UNITS_SIZE * MAX_MULTIPLICITY];
|
||||
#else
|
||||
static int unit_tick[1];
|
||||
#endif
|
||||
|
||||
/* A vector indexed by function unit number giving the number of insns
|
||||
that remain to use the unit. The scheduler using only DFA
|
||||
description should never use the following variable. */
|
||||
#if FUNCTION_UNITS_SIZE
|
||||
static int unit_n_insns[FUNCTION_UNITS_SIZE];
|
||||
#else
|
||||
static int unit_n_insns[1];
|
||||
#endif
|
||||
|
||||
/* Access the unit_last_insn array. Used by the visualization code.
|
||||
The scheduler using only DFA description should never use the
|
||||
following function. */
|
||||
|
||||
rtx
|
||||
get_unit_last_insn (int instance)
|
||||
{
|
||||
return unit_last_insn[instance];
|
||||
}
|
||||
|
||||
/* Reset the function unit state to the null state. */
|
||||
|
||||
static void
|
||||
clear_units (void)
|
||||
{
|
||||
memset (unit_last_insn, 0, sizeof (unit_last_insn));
|
||||
memset (unit_tick, 0, sizeof (unit_tick));
|
||||
memset (unit_n_insns, 0, sizeof (unit_n_insns));
|
||||
}
|
||||
|
||||
/* Return the issue-delay of an insn. The scheduler using only DFA
|
||||
description should never use the following function. */
|
||||
|
||||
HAIFA_INLINE int
|
||||
insn_issue_delay (rtx insn)
|
||||
{
|
||||
int i, delay = 0;
|
||||
int unit = insn_unit (insn);
|
||||
|
||||
/* Efficiency note: in fact, we are working 'hard' to compute a
|
||||
value that was available in md file, and is not available in
|
||||
function_units[] structure. It would be nice to have this
|
||||
value there, too. */
|
||||
if (unit >= 0)
|
||||
{
|
||||
if (function_units[unit].blockage_range_function &&
|
||||
function_units[unit].blockage_function)
|
||||
delay = function_units[unit].blockage_function (insn, insn);
|
||||
}
|
||||
else
|
||||
for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
|
||||
if ((unit & 1) != 0 && function_units[i].blockage_range_function
|
||||
&& function_units[i].blockage_function)
|
||||
delay = MAX (delay, function_units[i].blockage_function (insn, insn));
|
||||
|
||||
return delay;
|
||||
}
|
||||
|
||||
/* Return the actual hazard cost of executing INSN on the unit UNIT,
|
||||
instance INSTANCE at time CLOCK if the previous actual hazard cost
|
||||
was COST. The scheduler using only DFA description should never
|
||||
use the following function. */
|
||||
|
||||
HAIFA_INLINE int
|
||||
actual_hazard_this_instance (int unit, int instance, rtx insn, int clock, int cost)
|
||||
{
|
||||
int tick = unit_tick[instance]; /* Issue time of the last issued insn. */
|
||||
|
||||
if (tick - clock > cost)
|
||||
{
|
||||
/* The scheduler is operating forward, so unit's last insn is the
|
||||
executing insn and INSN is the candidate insn. We want a
|
||||
more exact measure of the blockage if we execute INSN at CLOCK
|
||||
given when we committed the execution of the unit's last insn.
|
||||
|
||||
The blockage value is given by either the unit's max blockage
|
||||
constant, blockage range function, or blockage function. Use
|
||||
the most exact form for the given unit. */
|
||||
|
||||
if (function_units[unit].blockage_range_function)
|
||||
{
|
||||
if (function_units[unit].blockage_function)
|
||||
tick += (function_units[unit].blockage_function
|
||||
(unit_last_insn[instance], insn)
|
||||
- function_units[unit].max_blockage);
|
||||
else
|
||||
tick += ((int) MAX_BLOCKAGE_COST (blockage_range (unit, insn))
|
||||
- function_units[unit].max_blockage);
|
||||
}
|
||||
if (tick - clock > cost)
|
||||
cost = tick - clock;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
/* Record INSN as having begun execution on the units encoded by UNIT
|
||||
at time CLOCK. The scheduler using only DFA description should
|
||||
never use the following function. */
|
||||
|
||||
static void
|
||||
schedule_unit (int unit, rtx insn, int clock)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (unit >= 0)
|
||||
{
|
||||
int instance = unit;
|
||||
#if MAX_MULTIPLICITY > 1
|
||||
/* Find the first free instance of the function unit and use that
|
||||
one. We assume that one is free. */
|
||||
for (i = function_units[unit].multiplicity - 1; i > 0; i--)
|
||||
{
|
||||
if (!actual_hazard_this_instance (unit, instance, insn, clock, 0))
|
||||
break;
|
||||
instance += FUNCTION_UNITS_SIZE;
|
||||
}
|
||||
#endif
|
||||
unit_last_insn[instance] = insn;
|
||||
unit_tick[instance] = (clock + function_units[unit].max_blockage);
|
||||
}
|
||||
else
|
||||
for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
|
||||
if ((unit & 1) != 0)
|
||||
schedule_unit (i, insn, clock);
|
||||
}
|
||||
|
||||
/* Return the actual hazard cost of executing INSN on the units
|
||||
encoded by UNIT at time CLOCK if the previous actual hazard cost
|
||||
was COST. The scheduler using only DFA description should never
|
||||
use the following function. */
|
||||
|
||||
static int
|
||||
actual_hazard (int unit, rtx insn, int clock, int cost)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (unit >= 0)
|
||||
{
|
||||
/* Find the instance of the function unit with the minimum hazard. */
|
||||
int instance = unit;
|
||||
int best_cost = actual_hazard_this_instance (unit, instance, insn,
|
||||
clock, cost);
|
||||
#if MAX_MULTIPLICITY > 1
|
||||
int this_cost;
|
||||
|
||||
if (best_cost > cost)
|
||||
{
|
||||
for (i = function_units[unit].multiplicity - 1; i > 0; i--)
|
||||
{
|
||||
instance += FUNCTION_UNITS_SIZE;
|
||||
this_cost = actual_hazard_this_instance (unit, instance, insn,
|
||||
clock, cost);
|
||||
if (this_cost < best_cost)
|
||||
{
|
||||
best_cost = this_cost;
|
||||
if (this_cost <= cost)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
cost = MAX (cost, best_cost);
|
||||
}
|
||||
else
|
||||
for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
|
||||
if ((unit & 1) != 0)
|
||||
cost = actual_hazard (i, insn, clock, cost);
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
/* Return the potential hazard cost of executing an instruction on the
|
||||
units encoded by UNIT if the previous potential hazard cost was
|
||||
COST. An insn with a large blockage time is chosen in preference
|
||||
to one with a smaller time; an insn that uses a unit that is more
|
||||
likely to be used is chosen in preference to one with a unit that
|
||||
is less used. We are trying to minimize a subsequent actual
|
||||
hazard. The scheduler using only DFA description should never use
|
||||
the following function. */
|
||||
|
||||
HAIFA_INLINE static int
|
||||
potential_hazard (int unit, rtx insn, int cost)
|
||||
{
|
||||
int i, ncost;
|
||||
unsigned int minb, maxb;
|
||||
|
||||
if (unit >= 0)
|
||||
{
|
||||
minb = maxb = function_units[unit].max_blockage;
|
||||
if (maxb > 1)
|
||||
{
|
||||
if (function_units[unit].blockage_range_function)
|
||||
{
|
||||
maxb = minb = blockage_range (unit, insn);
|
||||
maxb = MAX_BLOCKAGE_COST (maxb);
|
||||
minb = MIN_BLOCKAGE_COST (minb);
|
||||
}
|
||||
|
||||
if (maxb > 1)
|
||||
{
|
||||
/* Make the number of instructions left dominate. Make the
|
||||
minimum delay dominate the maximum delay. If all these
|
||||
are the same, use the unit number to add an arbitrary
|
||||
ordering. Other terms can be added. */
|
||||
ncost = minb * 0x40 + maxb;
|
||||
ncost *= (unit_n_insns[unit] - 1) * 0x1000 + unit;
|
||||
if (ncost > cost)
|
||||
cost = ncost;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
|
||||
if ((unit & 1) != 0)
|
||||
cost = potential_hazard (i, insn, cost);
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
/* Compute cost of executing INSN given the dependence LINK on the insn USED.
|
||||
This is the number of cycles between instruction issue and
|
||||
instruction results. */
|
||||
@ -868,12 +535,7 @@ insn_cost (rtx insn, rtx link, rtx used)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
cost = insn_default_latency (insn);
|
||||
else
|
||||
cost = result_ready_cost (insn);
|
||||
|
||||
cost = insn_default_latency (insn);
|
||||
if (cost < 0)
|
||||
cost = 0;
|
||||
|
||||
@ -892,23 +554,19 @@ insn_cost (rtx insn, rtx link, rtx used)
|
||||
cost = 0;
|
||||
else
|
||||
{
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
if (INSN_CODE (insn) >= 0)
|
||||
{
|
||||
if (INSN_CODE (insn) >= 0)
|
||||
if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
|
||||
cost = 0;
|
||||
else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
|
||||
{
|
||||
if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
|
||||
cost = 0;
|
||||
else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
|
||||
{
|
||||
cost = (insn_default_latency (insn)
|
||||
- insn_default_latency (used));
|
||||
if (cost <= 0)
|
||||
cost = 1;
|
||||
}
|
||||
else if (bypass_p (insn))
|
||||
cost = insn_latency (insn, used);
|
||||
cost = (insn_default_latency (insn)
|
||||
- insn_default_latency (used));
|
||||
if (cost <= 0)
|
||||
cost = 1;
|
||||
}
|
||||
else if (bypass_p (insn))
|
||||
cost = insn_latency (insn, used);
|
||||
}
|
||||
|
||||
if (targetm.sched.adjust_cost)
|
||||
@ -1208,19 +866,15 @@ adjust_priority (rtx prev)
|
||||
HAIFA_INLINE static void
|
||||
advance_one_cycle (void)
|
||||
{
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
{
|
||||
if (targetm.sched.dfa_pre_cycle_insn)
|
||||
state_transition (curr_state,
|
||||
targetm.sched.dfa_pre_cycle_insn ());
|
||||
if (targetm.sched.dfa_pre_cycle_insn)
|
||||
state_transition (curr_state,
|
||||
targetm.sched.dfa_pre_cycle_insn ());
|
||||
|
||||
state_transition (curr_state, NULL);
|
||||
|
||||
if (targetm.sched.dfa_post_cycle_insn)
|
||||
state_transition (curr_state,
|
||||
targetm.sched.dfa_post_cycle_insn ());
|
||||
}
|
||||
state_transition (curr_state, NULL);
|
||||
|
||||
if (targetm.sched.dfa_post_cycle_insn)
|
||||
state_transition (curr_state,
|
||||
targetm.sched.dfa_post_cycle_insn ());
|
||||
}
|
||||
|
||||
/* Clock at which the previous instruction was issued. */
|
||||
@ -1237,16 +891,9 @@ schedule_insn (rtx insn, struct ready_list *ready, int clock)
|
||||
{
|
||||
rtx link;
|
||||
int advance = 0;
|
||||
int unit = 0;
|
||||
int premature_issue = 0;
|
||||
|
||||
if (!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
unit = insn_unit (insn);
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ()
|
||||
&& sched_verbose >= 1)
|
||||
if (sched_verbose >= 1)
|
||||
{
|
||||
char buf[2048];
|
||||
|
||||
@ -1260,27 +907,6 @@ schedule_insn (rtx insn, struct ready_list *ready, int clock)
|
||||
print_reservation (sched_dump, insn);
|
||||
fputc ('\n', sched_dump);
|
||||
}
|
||||
else if (sched_verbose >= 2)
|
||||
{
|
||||
fprintf (sched_dump, ";;\t\t--> scheduling insn <<<%d>>> on unit ",
|
||||
INSN_UID (insn));
|
||||
insn_print_units (insn);
|
||||
fputc ('\n', sched_dump);
|
||||
}
|
||||
|
||||
if (!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
{
|
||||
if (sched_verbose && unit == -1)
|
||||
visualize_no_unit (insn);
|
||||
|
||||
|
||||
if (MAX_BLOCKAGE > 1 || issue_rate > 1 || sched_verbose)
|
||||
schedule_unit (unit, insn, clock);
|
||||
|
||||
if (INSN_DEPEND (insn) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (INSN_TICK (insn) > clock)
|
||||
{
|
||||
@ -1780,7 +1406,7 @@ queue_to_ready (struct ready_list *ready)
|
||||
{
|
||||
int stalls;
|
||||
|
||||
for (stalls = 1; stalls <= MAX_INSN_QUEUE_INDEX; stalls++)
|
||||
for (stalls = 1; stalls <= max_insn_queue_index; stalls++)
|
||||
{
|
||||
if ((link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]))
|
||||
{
|
||||
@ -1807,11 +1433,6 @@ queue_to_ready (struct ready_list *ready)
|
||||
advance_one_cycle ();
|
||||
}
|
||||
|
||||
if ((!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
&& sched_verbose && stalls)
|
||||
visualize_stall_cycles (stalls);
|
||||
|
||||
q_ptr = NEXT_Q_AFTER (q_ptr, stalls);
|
||||
clock_var += stalls;
|
||||
}
|
||||
@ -1903,7 +1524,7 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
|
||||
if (! flag_sched_stalled_insns)
|
||||
return 0;
|
||||
|
||||
for (stalls = 0; stalls <= MAX_INSN_QUEUE_INDEX; stalls++)
|
||||
for (stalls = 0; stalls <= max_insn_queue_index; stalls++)
|
||||
{
|
||||
if ((link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]))
|
||||
{
|
||||
@ -2266,16 +1887,9 @@ schedule_block (int b, int rgn_n_insns)
|
||||
(reload_completed ? "after" : "before"));
|
||||
fprintf (sched_dump, ";; ======================================================\n");
|
||||
fprintf (sched_dump, "\n");
|
||||
|
||||
visualize_alloc ();
|
||||
init_block_visualization ();
|
||||
}
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
state_reset (curr_state);
|
||||
else
|
||||
clear_units ();
|
||||
state_reset (curr_state);
|
||||
|
||||
/* Allocate the ready list. */
|
||||
ready.veclen = rgn_n_insns + 1 + issue_rate;
|
||||
@ -2283,17 +1897,13 @@ schedule_block (int b, int rgn_n_insns)
|
||||
ready.vec = xmalloc (ready.veclen * sizeof (rtx));
|
||||
ready.n_ready = 0;
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
{
|
||||
/* It is used for first cycle multipass scheduling. */
|
||||
temp_state = alloca (dfa_state_size);
|
||||
ready_try = xcalloc ((rgn_n_insns + 1), sizeof (char));
|
||||
choice_stack = xmalloc ((rgn_n_insns + 1)
|
||||
* sizeof (struct choice_entry));
|
||||
for (i = 0; i <= rgn_n_insns; i++)
|
||||
choice_stack[i].state = xmalloc (dfa_state_size);
|
||||
}
|
||||
/* It is used for first cycle multipass scheduling. */
|
||||
temp_state = alloca (dfa_state_size);
|
||||
ready_try = xcalloc ((rgn_n_insns + 1), sizeof (char));
|
||||
choice_stack = xmalloc ((rgn_n_insns + 1)
|
||||
* sizeof (struct choice_entry));
|
||||
for (i = 0; i <= rgn_n_insns; i++)
|
||||
choice_stack[i].state = xmalloc (dfa_state_size);
|
||||
|
||||
(*current_sched_info->init_ready_list) (&ready);
|
||||
|
||||
@ -2308,14 +1918,8 @@ schedule_block (int b, int rgn_n_insns)
|
||||
q_ptr = 0;
|
||||
q_size = 0;
|
||||
|
||||
if (!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
max_insn_queue_index_macro_value = INSN_QUEUE_SIZE - 1;
|
||||
else
|
||||
max_insn_queue_index_macro_value = max_insn_queue_index;
|
||||
|
||||
insn_queue = alloca ((MAX_INSN_QUEUE_INDEX + 1) * sizeof (rtx));
|
||||
memset (insn_queue, 0, (MAX_INSN_QUEUE_INDEX + 1) * sizeof (rtx));
|
||||
insn_queue = alloca ((max_insn_queue_index + 1) * sizeof (rtx));
|
||||
memset (insn_queue, 0, (max_insn_queue_index + 1) * sizeof (rtx));
|
||||
last_clock_var = -1;
|
||||
|
||||
/* Start just before the beginning of time. */
|
||||
@ -2391,79 +1995,66 @@ schedule_block (int b, int rgn_n_insns)
|
||||
debug_ready_list (&ready);
|
||||
}
|
||||
|
||||
if (!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
if (ready.n_ready == 0
|
||||
&& can_issue_more
|
||||
&& reload_completed)
|
||||
{
|
||||
if (ready.n_ready == 0 || !can_issue_more
|
||||
|| !(*current_sched_info->schedule_more_p) ())
|
||||
break;
|
||||
insn = ready_remove_first (&ready);
|
||||
cost = actual_hazard (insn_unit (insn), insn, clock_var, 0);
|
||||
/* Allow scheduling insns directly from the queue in case
|
||||
there's nothing better to do (ready list is empty) but
|
||||
there are still vacant dispatch slots in the current cycle. */
|
||||
if (sched_verbose >= 6)
|
||||
fprintf(sched_dump,";;\t\tSecond chance\n");
|
||||
memcpy (temp_state, curr_state, dfa_state_size);
|
||||
if (early_queue_to_ready (temp_state, &ready))
|
||||
ready_sort (&ready);
|
||||
}
|
||||
|
||||
if (ready.n_ready == 0 || !can_issue_more
|
||||
|| state_dead_lock_p (curr_state)
|
||||
|| !(*current_sched_info->schedule_more_p) ())
|
||||
break;
|
||||
|
||||
/* Select and remove the insn from the ready list. */
|
||||
if (sort_p)
|
||||
insn = choose_ready (&ready);
|
||||
else
|
||||
insn = ready_remove_first (&ready);
|
||||
|
||||
if (targetm.sched.dfa_new_cycle
|
||||
&& targetm.sched.dfa_new_cycle (sched_dump, sched_verbose,
|
||||
insn, last_clock_var,
|
||||
clock_var, &sort_p))
|
||||
{
|
||||
ready_add (&ready, insn);
|
||||
break;
|
||||
}
|
||||
|
||||
sort_p = TRUE;
|
||||
memcpy (temp_state, curr_state, dfa_state_size);
|
||||
if (recog_memoized (insn) < 0)
|
||||
{
|
||||
asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT
|
||||
|| asm_noperands (PATTERN (insn)) >= 0);
|
||||
if (!first_cycle_insn_p && asm_p)
|
||||
/* This is asm insn which is tryed to be issued on the
|
||||
cycle not first. Issue it on the next cycle. */
|
||||
cost = 1;
|
||||
else
|
||||
/* A USE insn, or something else we don't need to
|
||||
understand. We can't pass these directly to
|
||||
state_transition because it will trigger a
|
||||
fatal error for unrecognizable insns. */
|
||||
cost = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ready.n_ready == 0
|
||||
&& can_issue_more
|
||||
&& reload_completed)
|
||||
{
|
||||
/* Allow scheduling insns directly from the queue in case
|
||||
there's nothing better to do (ready list is empty) but
|
||||
there are still vacant dispatch slots in the current cycle. */
|
||||
if (sched_verbose >= 6)
|
||||
fprintf(sched_dump,";;\t\tSecond chance\n");
|
||||
memcpy (temp_state, curr_state, dfa_state_size);
|
||||
if (early_queue_to_ready (temp_state, &ready))
|
||||
ready_sort (&ready);
|
||||
}
|
||||
|
||||
if (ready.n_ready == 0 || !can_issue_more
|
||||
|| state_dead_lock_p (curr_state)
|
||||
|| !(*current_sched_info->schedule_more_p) ())
|
||||
break;
|
||||
|
||||
/* Select and remove the insn from the ready list. */
|
||||
if (sort_p)
|
||||
insn = choose_ready (&ready);
|
||||
else
|
||||
insn = ready_remove_first (&ready);
|
||||
|
||||
if (targetm.sched.dfa_new_cycle
|
||||
&& targetm.sched.dfa_new_cycle (sched_dump, sched_verbose,
|
||||
insn, last_clock_var,
|
||||
clock_var, &sort_p))
|
||||
{
|
||||
ready_add (&ready, insn);
|
||||
break;
|
||||
}
|
||||
|
||||
sort_p = TRUE;
|
||||
memcpy (temp_state, curr_state, dfa_state_size);
|
||||
if (recog_memoized (insn) < 0)
|
||||
{
|
||||
asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT
|
||||
|| asm_noperands (PATTERN (insn)) >= 0);
|
||||
if (!first_cycle_insn_p && asm_p)
|
||||
/* This is asm insn which is tryed to be issued on the
|
||||
cycle not first. Issue it on the next cycle. */
|
||||
cost = 1;
|
||||
else
|
||||
/* A USE insn, or something else we don't need to
|
||||
understand. We can't pass these directly to
|
||||
state_transition because it will trigger a
|
||||
fatal error for unrecognizable insns. */
|
||||
cost = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cost = state_transition (temp_state, insn);
|
||||
if (cost < 0)
|
||||
cost = 0;
|
||||
else if (cost == 0)
|
||||
cost = 1;
|
||||
}
|
||||
cost = state_transition (temp_state, insn);
|
||||
if (cost < 0)
|
||||
cost = 0;
|
||||
else if (cost == 0)
|
||||
cost = 1;
|
||||
}
|
||||
|
||||
|
||||
if (cost >= 1)
|
||||
{
|
||||
queue_insn (insn, cost);
|
||||
@ -2475,13 +2066,9 @@ schedule_block (int b, int rgn_n_insns)
|
||||
|
||||
last_scheduled_insn = move_insn (insn, last_scheduled_insn);
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
{
|
||||
if (memcmp (curr_state, temp_state, dfa_state_size) != 0)
|
||||
cycle_issued_insns++;
|
||||
memcpy (curr_state, temp_state, dfa_state_size);
|
||||
}
|
||||
if (memcmp (curr_state, temp_state, dfa_state_size) != 0)
|
||||
cycle_issued_insns++;
|
||||
memcpy (curr_state, temp_state, dfa_state_size);
|
||||
|
||||
if (targetm.sched.variable_issue)
|
||||
can_issue_more =
|
||||
@ -2521,12 +2108,6 @@ schedule_block (int b, int rgn_n_insns)
|
||||
&ready.n_ready, clock_var);
|
||||
}
|
||||
}
|
||||
|
||||
if ((!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
&& sched_verbose)
|
||||
/* Debug info. */
|
||||
visualize_scheduled_insns (clock_var);
|
||||
}
|
||||
|
||||
if (targetm.sched.md_finish)
|
||||
@ -2537,9 +2118,6 @@ schedule_block (int b, int rgn_n_insns)
|
||||
{
|
||||
fprintf (sched_dump, ";;\tReady list (final): ");
|
||||
debug_ready_list (&ready);
|
||||
if (!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
print_block_visualization ("");
|
||||
}
|
||||
|
||||
/* Sanity check -- queue must be empty now. Meaningless if region has
|
||||
@ -2598,7 +2176,6 @@ schedule_block (int b, int rgn_n_insns)
|
||||
clock_var, INSN_UID (head));
|
||||
fprintf (sched_dump, ";; new tail = %d\n\n",
|
||||
INSN_UID (tail));
|
||||
visualize_free ();
|
||||
}
|
||||
|
||||
current_sched_info->head = head;
|
||||
@ -2606,14 +2183,10 @@ schedule_block (int b, int rgn_n_insns)
|
||||
|
||||
free (ready.vec);
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
{
|
||||
free (ready_try);
|
||||
for (i = 0; i <= rgn_n_insns; i++)
|
||||
free (choice_stack [i].state);
|
||||
free (choice_stack);
|
||||
}
|
||||
free (ready_try);
|
||||
for (i = 0; i <= rgn_n_insns; i++)
|
||||
free (choice_stack [i].state);
|
||||
free (choice_stack);
|
||||
}
|
||||
|
||||
/* Set_priorities: compute priority of each insn in the block. */
|
||||
@ -2700,19 +2273,15 @@ sched_init (FILE *dump_file)
|
||||
for (i = 0; i < old_max_uid; i++)
|
||||
h_i_d [i].cost = -1;
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
{
|
||||
if (targetm.sched.init_dfa_pre_cycle_insn)
|
||||
targetm.sched.init_dfa_pre_cycle_insn ();
|
||||
if (targetm.sched.init_dfa_pre_cycle_insn)
|
||||
targetm.sched.init_dfa_pre_cycle_insn ();
|
||||
|
||||
if (targetm.sched.init_dfa_post_cycle_insn)
|
||||
targetm.sched.init_dfa_post_cycle_insn ();
|
||||
if (targetm.sched.init_dfa_post_cycle_insn)
|
||||
targetm.sched.init_dfa_post_cycle_insn ();
|
||||
|
||||
dfa_start ();
|
||||
dfa_state_size = state_size ();
|
||||
curr_state = xmalloc (dfa_state_size);
|
||||
}
|
||||
dfa_start ();
|
||||
dfa_state_size = state_size ();
|
||||
curr_state = xmalloc (dfa_state_size);
|
||||
|
||||
h_i_d[0].luid = 0;
|
||||
luid = 1;
|
||||
@ -2769,12 +2338,6 @@ sched_init (FILE *dump_file)
|
||||
}
|
||||
}
|
||||
|
||||
if ((!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
&& sched_verbose)
|
||||
/* Find units used in this function, for visualization. */
|
||||
init_target_units ();
|
||||
|
||||
/* ??? Add a NOTE after the last insn of the last basic block. It is not
|
||||
known why this is done. */
|
||||
|
||||
@ -2805,13 +2368,8 @@ void
|
||||
sched_finish (void)
|
||||
{
|
||||
free (h_i_d);
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
{
|
||||
free (curr_state);
|
||||
dfa_finish ();
|
||||
}
|
||||
free (curr_state);
|
||||
dfa_finish ();
|
||||
free_dependency_caches ();
|
||||
end_alias_analysis ();
|
||||
if (write_symbols != NO_DEBUG)
|
||||
|
@ -812,14 +812,8 @@ sms_schedule (FILE *dump_file)
|
||||
int max_bb_index = last_basic_block;
|
||||
struct df *df;
|
||||
|
||||
/* SMS uses the DFA interface. */
|
||||
if (! targetm.sched.use_dfa_pipeline_interface
|
||||
|| ! (*targetm.sched.use_dfa_pipeline_interface) ())
|
||||
return;
|
||||
|
||||
stats_file = dump_file;
|
||||
|
||||
|
||||
/* Initialize issue_rate. */
|
||||
if (targetm.sched.issue_rate)
|
||||
{
|
||||
@ -1990,19 +1984,15 @@ add_node_to_ps (partial_schedule_ptr ps, ddg_node_ptr node, int cycle)
|
||||
static void
|
||||
advance_one_cycle (void)
|
||||
{
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& (*targetm.sched.use_dfa_pipeline_interface) ())
|
||||
{
|
||||
if (targetm.sched.dfa_pre_cycle_insn)
|
||||
state_transition (curr_state,
|
||||
(*targetm.sched.dfa_pre_cycle_insn) ());
|
||||
if (targetm.sched.dfa_pre_cycle_insn)
|
||||
state_transition (curr_state,
|
||||
(*targetm.sched.dfa_pre_cycle_insn) ());
|
||||
|
||||
state_transition (curr_state, NULL);
|
||||
state_transition (curr_state, NULL);
|
||||
|
||||
if (targetm.sched.dfa_post_cycle_insn)
|
||||
state_transition (curr_state,
|
||||
(*targetm.sched.dfa_post_cycle_insn) ());
|
||||
}
|
||||
if (targetm.sched.dfa_post_cycle_insn)
|
||||
state_transition (curr_state,
|
||||
(*targetm.sched.dfa_post_cycle_insn) ());
|
||||
}
|
||||
|
||||
/* Checks if PS has resource conflicts according to DFA, starting from
|
||||
@ -2013,10 +2003,6 @@ ps_has_conflicts (partial_schedule_ptr ps, int from, int to)
|
||||
{
|
||||
int cycle;
|
||||
|
||||
if (! targetm.sched.use_dfa_pipeline_interface
|
||||
|| ! (*targetm.sched.use_dfa_pipeline_interface) ())
|
||||
return true;
|
||||
|
||||
state_reset (curr_state);
|
||||
|
||||
for (cycle = from; cycle <= to; cycle++)
|
||||
|
41
gcc/rtl.def
41
gcc/rtl.def
@ -281,47 +281,6 @@ DEF_RTL_EXPR(DEFINE_EXPAND, "define_expand", "sEss", RTX_EXTRA)
|
||||
requirements for delay slots. */
|
||||
DEF_RTL_EXPR(DEFINE_DELAY, "define_delay", "eE", RTX_EXTRA)
|
||||
|
||||
/* Define a set of insns that requires a function unit. This means that
|
||||
these insns produce their result after a delay and that there may be
|
||||
restrictions on the number of insns of this type that can be scheduled
|
||||
simultaneously.
|
||||
|
||||
More than one DEFINE_FUNCTION_UNIT can be specified for a function unit.
|
||||
Each gives a set of operations and associated delays. The first three
|
||||
operands must be the same for each operation for the same function unit.
|
||||
|
||||
All delays are specified in cycles.
|
||||
|
||||
1st operand: Name of function unit (mostly for documentation)
|
||||
2nd operand: Number of identical function units in CPU
|
||||
3rd operand: Total number of simultaneous insns that can execute on this
|
||||
function unit; 0 if unlimited.
|
||||
4th operand: Condition involving insn attribute, that, if true, specifies
|
||||
those insns that this expression applies to.
|
||||
5th operand: Constant delay after which insn result will be
|
||||
available.
|
||||
6th operand: Delay until next insn can be scheduled on the function unit
|
||||
executing this operation. The meaning depends on whether or
|
||||
not the next operand is supplied.
|
||||
7th operand: If this operand is not specified, the 6th operand gives the
|
||||
number of cycles after the instruction matching the 4th
|
||||
operand begins using the function unit until a subsequent
|
||||
insn can begin. A value of zero should be used for a
|
||||
unit with no issue constraints. If only one operation can
|
||||
be executed a time and the unit is busy for the entire time,
|
||||
the 3rd operand should be specified as 1, the 6th operand
|
||||
should be specified as 0, and the 7th operand should not
|
||||
be specified.
|
||||
|
||||
If this operand is specified, it is a list of attribute
|
||||
expressions. If an insn for which any of these expressions
|
||||
is true is currently executing on the function unit, the
|
||||
issue delay will be given by the 6th operand. Otherwise,
|
||||
the insn can be immediately scheduled (subject to the limit
|
||||
on the number of simultaneous operations executing on the
|
||||
unit.) */
|
||||
DEF_RTL_EXPR(DEFINE_FUNCTION_UNIT, "define_function_unit", "siieiiV", RTX_EXTRA)
|
||||
|
||||
/* Define attribute computation for `asm' instructions. */
|
||||
DEF_RTL_EXPR(DEFINE_ASM_ATTRIBUTES, "define_asm_attributes", "V", RTX_EXTRA)
|
||||
|
||||
|
@ -353,15 +353,7 @@ enum INSN_TRAP_CLASS
|
||||
#endif
|
||||
|
||||
/* Functions in sched-vis.c. */
|
||||
extern void init_target_units (void);
|
||||
extern void insn_print_units (rtx);
|
||||
extern void init_block_visualization (void);
|
||||
extern void print_block_visualization (const char *);
|
||||
extern void visualize_scheduled_insns (int);
|
||||
extern void visualize_no_unit (rtx);
|
||||
extern void visualize_stall_cycles (int);
|
||||
extern void visualize_alloc (void);
|
||||
extern void visualize_free (void);
|
||||
extern void print_insn (char *, rtx, int);
|
||||
|
||||
/* Functions in sched-deps.c. */
|
||||
extern int add_dependence (rtx, rtx, enum reg_note);
|
||||
@ -388,7 +380,7 @@ extern void restore_line_notes (rtx, rtx);
|
||||
extern void rm_redundant_line_notes (void);
|
||||
extern void rm_other_notes (rtx, rtx);
|
||||
|
||||
extern int insn_issue_delay (rtx);
|
||||
extern int insn_cost (rtx, rtx, rtx);
|
||||
extern int set_priorities (rtx, rtx);
|
||||
|
||||
extern void schedule_block (int, int);
|
||||
@ -397,12 +389,4 @@ extern void sched_finish (void);
|
||||
|
||||
extern void ready_add (struct ready_list *, rtx);
|
||||
|
||||
/* The following are exported for the benefit of debugging functions. It
|
||||
would be nicer to keep them private to haifa-sched.c. */
|
||||
extern int insn_unit (rtx);
|
||||
extern int insn_cost (rtx, rtx, rtx);
|
||||
extern rtx get_unit_last_insn (int);
|
||||
extern int actual_hazard_this_instance (int, int, rtx, int, int);
|
||||
extern void print_insn (char *, rtx, int);
|
||||
|
||||
#endif /* GCC_SCHED_INT_H */
|
||||
|
165
gcc/sched-rgn.c
165
gcc/sched-rgn.c
@ -1784,14 +1784,9 @@ init_ready_list (struct ready_list *ready)
|
||||
|
||||
if (!CANT_MOVE (insn)
|
||||
&& (!IS_SPECULATIVE_INSN (insn)
|
||||
|| ((((!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
&& insn_issue_delay (insn) <= 3)
|
||||
|| (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ()
|
||||
&& (recog_memoized (insn) < 0
|
||||
|| min_insn_conflict_delay (curr_state,
|
||||
insn, insn) <= 3)))
|
||||
|| ((recog_memoized (insn) < 0
|
||||
|| min_insn_conflict_delay (curr_state,
|
||||
insn, insn) <= 3)
|
||||
&& check_live (insn, bb_src)
|
||||
&& is_exception_free (insn, bb_src, target_bb))))
|
||||
if (INSN_DEP_COUNT (insn) == 0)
|
||||
@ -1882,15 +1877,8 @@ new_ready (rtx next)
|
||||
&& (!IS_VALID (INSN_BB (next))
|
||||
|| CANT_MOVE (next)
|
||||
|| (IS_SPECULATIVE_INSN (next)
|
||||
&& (0
|
||||
|| (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ()
|
||||
&& recog_memoized (next) >= 0
|
||||
&& min_insn_conflict_delay (curr_state, next,
|
||||
next) > 3)
|
||||
|| ((!targetm.sched.use_dfa_pipeline_interface
|
||||
|| !targetm.sched.use_dfa_pipeline_interface ())
|
||||
&& insn_issue_delay (next) > 3)
|
||||
&& ((recog_memoized (next) >= 0
|
||||
&& min_insn_conflict_delay (curr_state, next, next) > 3)
|
||||
|| !check_live (next, INSN_BB (next))
|
||||
|| !is_exception_free (next, INSN_BB (next), target_bb)))))
|
||||
return 0;
|
||||
@ -2278,106 +2266,67 @@ debug_dependencies (void)
|
||||
fprintf (sched_dump, ";; --------------- forward dependences: ------------ \n");
|
||||
for (bb = 0; bb < current_nr_blocks; bb++)
|
||||
{
|
||||
if (1)
|
||||
rtx head, tail;
|
||||
rtx next_tail;
|
||||
rtx insn;
|
||||
|
||||
get_block_head_tail (BB_TO_BLOCK (bb), &head, &tail);
|
||||
next_tail = NEXT_INSN (tail);
|
||||
fprintf (sched_dump, "\n;; --- Region Dependences --- b %d bb %d \n",
|
||||
BB_TO_BLOCK (bb), bb);
|
||||
|
||||
fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%14s\n",
|
||||
"insn", "code", "bb", "dep", "prio", "cost",
|
||||
"reservation");
|
||||
fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%14s\n",
|
||||
"----", "----", "--", "---", "----", "----",
|
||||
"-----------");
|
||||
|
||||
for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
|
||||
{
|
||||
rtx head, tail;
|
||||
rtx next_tail;
|
||||
rtx insn;
|
||||
rtx link;
|
||||
|
||||
get_block_head_tail (BB_TO_BLOCK (bb), &head, &tail);
|
||||
next_tail = NEXT_INSN (tail);
|
||||
fprintf (sched_dump, "\n;; --- Region Dependences --- b %d bb %d \n",
|
||||
BB_TO_BLOCK (bb), bb);
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
if (! INSN_P (insn))
|
||||
{
|
||||
fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%14s\n",
|
||||
"insn", "code", "bb", "dep", "prio", "cost",
|
||||
"reservation");
|
||||
fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%14s\n",
|
||||
"----", "----", "--", "---", "----", "----",
|
||||
"-----------");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%11s%6s\n",
|
||||
"insn", "code", "bb", "dep", "prio", "cost", "blockage", "units");
|
||||
fprintf (sched_dump, ";; %7s%6s%6s%6s%6s%6s%11s%6s\n",
|
||||
"----", "----", "--", "---", "----", "----", "--------", "-----");
|
||||
}
|
||||
|
||||
for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
|
||||
{
|
||||
rtx link;
|
||||
|
||||
if (! INSN_P (insn))
|
||||
int n;
|
||||
fprintf (sched_dump, ";; %6d ", INSN_UID (insn));
|
||||
if (NOTE_P (insn))
|
||||
{
|
||||
int n;
|
||||
fprintf (sched_dump, ";; %6d ", INSN_UID (insn));
|
||||
if (NOTE_P (insn))
|
||||
n = NOTE_LINE_NUMBER (insn);
|
||||
if (n < 0)
|
||||
fprintf (sched_dump, "%s\n", GET_NOTE_INSN_NAME (n));
|
||||
else
|
||||
{
|
||||
n = NOTE_LINE_NUMBER (insn);
|
||||
if (n < 0)
|
||||
fprintf (sched_dump, "%s\n", GET_NOTE_INSN_NAME (n));
|
||||
else
|
||||
{
|
||||
expanded_location xloc;
|
||||
NOTE_EXPANDED_LOCATION (xloc, insn);
|
||||
fprintf (sched_dump, "line %d, file %s\n",
|
||||
xloc.line, xloc.file);
|
||||
}
|
||||
expanded_location xloc;
|
||||
NOTE_EXPANDED_LOCATION (xloc, insn);
|
||||
fprintf (sched_dump, "line %d, file %s\n",
|
||||
xloc.line, xloc.file);
|
||||
}
|
||||
else
|
||||
fprintf (sched_dump, " {%s}\n", GET_RTX_NAME (GET_CODE (insn)));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
{
|
||||
fprintf (sched_dump,
|
||||
";; %s%5d%6d%6d%6d%6d%6d ",
|
||||
(SCHED_GROUP_P (insn) ? "+" : " "),
|
||||
INSN_UID (insn),
|
||||
INSN_CODE (insn),
|
||||
INSN_BB (insn),
|
||||
INSN_DEP_COUNT (insn),
|
||||
INSN_PRIORITY (insn),
|
||||
insn_cost (insn, 0, 0));
|
||||
|
||||
if (recog_memoized (insn) < 0)
|
||||
fprintf (sched_dump, "nothing");
|
||||
else
|
||||
print_reservation (sched_dump, insn);
|
||||
}
|
||||
else
|
||||
{
|
||||
int unit = insn_unit (insn);
|
||||
int range
|
||||
= (unit < 0
|
||||
|| function_units[unit].blockage_range_function == 0
|
||||
? 0
|
||||
: function_units[unit].blockage_range_function (insn));
|
||||
fprintf (sched_dump,
|
||||
";; %s%5d%6d%6d%6d%6d%6d %3d -%3d ",
|
||||
(SCHED_GROUP_P (insn) ? "+" : " "),
|
||||
INSN_UID (insn),
|
||||
INSN_CODE (insn),
|
||||
INSN_BB (insn),
|
||||
INSN_DEP_COUNT (insn),
|
||||
INSN_PRIORITY (insn),
|
||||
insn_cost (insn, 0, 0),
|
||||
(int) MIN_BLOCKAGE_COST (range),
|
||||
(int) MAX_BLOCKAGE_COST (range));
|
||||
insn_print_units (insn);
|
||||
}
|
||||
|
||||
fprintf (sched_dump, "\t: ");
|
||||
for (link = INSN_DEPEND (insn); link; link = XEXP (link, 1))
|
||||
fprintf (sched_dump, "%d ", INSN_UID (XEXP (link, 0)));
|
||||
fprintf (sched_dump, "\n");
|
||||
fprintf (sched_dump, " {%s}\n", GET_RTX_NAME (GET_CODE (insn)));
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf (sched_dump,
|
||||
";; %s%5d%6d%6d%6d%6d%6d ",
|
||||
(SCHED_GROUP_P (insn) ? "+" : " "),
|
||||
INSN_UID (insn),
|
||||
INSN_CODE (insn),
|
||||
INSN_BB (insn),
|
||||
INSN_DEP_COUNT (insn),
|
||||
INSN_PRIORITY (insn),
|
||||
insn_cost (insn, 0, 0));
|
||||
|
||||
if (recog_memoized (insn) < 0)
|
||||
fprintf (sched_dump, "nothing");
|
||||
else
|
||||
print_reservation (sched_dump, insn);
|
||||
|
||||
fprintf (sched_dump, "\t: ");
|
||||
for (link = INSN_DEPEND (insn); link; link = XEXP (link, 1))
|
||||
fprintf (sched_dump, "%d ", INSN_UID (XEXP (link, 0)));
|
||||
fprintf (sched_dump, "\n");
|
||||
}
|
||||
}
|
||||
fprintf (sched_dump, "\n");
|
||||
|
259
gcc/sched-vis.c
259
gcc/sched-vis.c
@ -37,133 +37,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "target.h"
|
||||
|
||||
#ifdef INSN_SCHEDULING
|
||||
/* target_units bitmask has 1 for each unit in the cpu. It should be
|
||||
possible to compute this variable from the machine description.
|
||||
But currently it is computed by examining the insn list. Since
|
||||
this is only needed for visualization, it seems an acceptable
|
||||
solution. (For understanding the mapping of bits to units, see
|
||||
definition of function_units[] in "insn-attrtab.c".) The scheduler
|
||||
using only DFA description should never use the following variable. */
|
||||
|
||||
static int target_units = 0;
|
||||
|
||||
static char *safe_concat (char *, char *, const char *);
|
||||
static int get_visual_tbl_length (void);
|
||||
static void print_exp (char *, rtx, int);
|
||||
static void print_value (char *, rtx, int);
|
||||
static void print_pattern (char *, rtx, int);
|
||||
|
||||
/* Print names of units on which insn can/should execute, for debugging. */
|
||||
|
||||
void
|
||||
insn_print_units (rtx insn)
|
||||
{
|
||||
int i;
|
||||
int unit = insn_unit (insn);
|
||||
|
||||
if (unit == -1)
|
||||
fprintf (sched_dump, "none");
|
||||
else if (unit >= 0)
|
||||
fprintf (sched_dump, "%s", function_units[unit].name);
|
||||
else
|
||||
{
|
||||
fprintf (sched_dump, "[");
|
||||
for (i = 0, unit = ~unit; unit; i++, unit >>= 1)
|
||||
if (unit & 1)
|
||||
{
|
||||
fprintf (sched_dump, "%s", function_units[i].name);
|
||||
if (unit != 1)
|
||||
fprintf (sched_dump, " ");
|
||||
}
|
||||
fprintf (sched_dump, "]");
|
||||
}
|
||||
}
|
||||
|
||||
/* MAX_VISUAL_LINES is the maximum number of lines in visualization table
|
||||
of a basic block. If more lines are needed, table is split to two.
|
||||
n_visual_lines is the number of lines printed so far for a block.
|
||||
visual_tbl contains the block visualization info.
|
||||
vis_no_unit holds insns in a cycle that are not mapped to any unit. */
|
||||
#define MAX_VISUAL_LINES 100
|
||||
#define INSN_LEN 30
|
||||
int n_visual_lines;
|
||||
static unsigned visual_tbl_line_length;
|
||||
char *visual_tbl;
|
||||
int n_vis_no_unit;
|
||||
#define MAX_VISUAL_NO_UNIT 20
|
||||
rtx vis_no_unit[MAX_VISUAL_NO_UNIT];
|
||||
|
||||
/* Finds units that are in use in this function. Required only
|
||||
for visualization. */
|
||||
|
||||
void
|
||||
init_target_units (void)
|
||||
{
|
||||
rtx insn;
|
||||
int unit;
|
||||
|
||||
for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
|
||||
{
|
||||
if (! INSN_P (insn))
|
||||
continue;
|
||||
|
||||
unit = insn_unit (insn);
|
||||
|
||||
if (unit < 0)
|
||||
target_units |= ~unit;
|
||||
else
|
||||
target_units |= (1 << unit);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the length of the visualization table. */
|
||||
|
||||
static int
|
||||
get_visual_tbl_length (void)
|
||||
{
|
||||
int unit, i;
|
||||
int n, n1;
|
||||
char *s;
|
||||
|
||||
if (targetm.sched.use_dfa_pipeline_interface
|
||||
&& targetm.sched.use_dfa_pipeline_interface ())
|
||||
{
|
||||
visual_tbl_line_length = 1;
|
||||
return 1; /* Can't return 0 because that will cause problems
|
||||
with alloca. */
|
||||
}
|
||||
|
||||
/* Compute length of one field in line. */
|
||||
s = alloca (INSN_LEN + 6);
|
||||
sprintf (s, " %33s", "uname");
|
||||
n1 = strlen (s);
|
||||
|
||||
/* Compute length of one line. */
|
||||
n = strlen (";; ");
|
||||
n += n1;
|
||||
for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
|
||||
if (function_units[unit].bitmask & target_units)
|
||||
for (i = 0; i < function_units[unit].multiplicity; i++)
|
||||
n += n1;
|
||||
n += n1;
|
||||
n += strlen ("\n") + 2;
|
||||
|
||||
visual_tbl_line_length = n;
|
||||
|
||||
/* Compute length of visualization string. */
|
||||
return (MAX_VISUAL_LINES * n);
|
||||
}
|
||||
|
||||
/* Init block visualization debugging info. */
|
||||
|
||||
void
|
||||
init_block_visualization (void)
|
||||
{
|
||||
strcpy (visual_tbl, "");
|
||||
n_visual_lines = 0;
|
||||
n_vis_no_unit = 0;
|
||||
}
|
||||
|
||||
#define BUF_LEN 2048
|
||||
|
||||
static char *
|
||||
@ -808,142 +687,4 @@ print_insn (char *buf, rtx x, int verbose)
|
||||
}
|
||||
} /* print_insn */
|
||||
|
||||
/* Print visualization debugging info. The scheduler using only DFA
|
||||
description should never use the following function. */
|
||||
|
||||
void
|
||||
print_block_visualization (const char *s)
|
||||
{
|
||||
int unit, i;
|
||||
|
||||
/* Print header. */
|
||||
fprintf (sched_dump, "\n;; ==================== scheduling visualization %s \n", s);
|
||||
|
||||
/* Print names of units. */
|
||||
fprintf (sched_dump, ";; %-8s", "clock");
|
||||
for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
|
||||
if (function_units[unit].bitmask & target_units)
|
||||
for (i = 0; i < function_units[unit].multiplicity; i++)
|
||||
fprintf (sched_dump, " %-33s", function_units[unit].name);
|
||||
fprintf (sched_dump, " %-8s\n", "no-unit");
|
||||
|
||||
fprintf (sched_dump, ";; %-8s", "=====");
|
||||
for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
|
||||
if (function_units[unit].bitmask & target_units)
|
||||
for (i = 0; i < function_units[unit].multiplicity; i++)
|
||||
fprintf (sched_dump, " %-33s", "==============================");
|
||||
fprintf (sched_dump, " %-8s\n", "=======");
|
||||
|
||||
/* Print insns in each cycle. */
|
||||
fprintf (sched_dump, "%s\n", visual_tbl);
|
||||
}
|
||||
|
||||
/* Print insns in the 'no_unit' column of visualization. */
|
||||
|
||||
void
|
||||
visualize_no_unit (rtx insn)
|
||||
{
|
||||
if (n_vis_no_unit < MAX_VISUAL_NO_UNIT)
|
||||
{
|
||||
vis_no_unit[n_vis_no_unit] = insn;
|
||||
n_vis_no_unit++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print insns scheduled in clock, for visualization. */
|
||||
|
||||
void
|
||||
visualize_scheduled_insns (int clock)
|
||||
{
|
||||
int i, unit;
|
||||
|
||||
/* If no more room, split table into two. */
|
||||
if (n_visual_lines >= MAX_VISUAL_LINES)
|
||||
{
|
||||
print_block_visualization ("(incomplete)");
|
||||
init_block_visualization ();
|
||||
}
|
||||
|
||||
n_visual_lines++;
|
||||
|
||||
sprintf (visual_tbl + strlen (visual_tbl), ";; %-8d", clock);
|
||||
for (unit = 0; unit < FUNCTION_UNITS_SIZE; unit++)
|
||||
if (function_units[unit].bitmask & target_units)
|
||||
for (i = 0; i < function_units[unit].multiplicity; i++)
|
||||
{
|
||||
int instance = unit + i * FUNCTION_UNITS_SIZE;
|
||||
rtx insn = get_unit_last_insn (instance);
|
||||
|
||||
/* Print insns that still keep the unit busy. */
|
||||
if (insn
|
||||
&& actual_hazard_this_instance (unit, instance, insn, clock, 0))
|
||||
{
|
||||
char str[BUF_LEN];
|
||||
print_insn (str, insn, 0);
|
||||
str[INSN_LEN] = '\0';
|
||||
sprintf (visual_tbl + strlen (visual_tbl), " %-33s", str);
|
||||
}
|
||||
else
|
||||
sprintf (visual_tbl + strlen (visual_tbl), " %-33s", "------------------------------");
|
||||
}
|
||||
|
||||
/* Print insns that are not assigned to any unit. */
|
||||
for (i = 0; i < n_vis_no_unit; i++)
|
||||
sprintf (visual_tbl + strlen (visual_tbl), " %-8d",
|
||||
INSN_UID (vis_no_unit[i]));
|
||||
n_vis_no_unit = 0;
|
||||
|
||||
sprintf (visual_tbl + strlen (visual_tbl), "\n");
|
||||
}
|
||||
|
||||
/* Print stalled cycles. */
|
||||
|
||||
void
|
||||
visualize_stall_cycles (int stalls)
|
||||
{
|
||||
static const char *const prefix = ";; ";
|
||||
const char *suffix = "\n";
|
||||
char *p;
|
||||
|
||||
/* If no more room, split table into two. */
|
||||
if (n_visual_lines >= MAX_VISUAL_LINES)
|
||||
{
|
||||
print_block_visualization ("(incomplete)");
|
||||
init_block_visualization ();
|
||||
}
|
||||
|
||||
n_visual_lines++;
|
||||
|
||||
p = visual_tbl + strlen (visual_tbl);
|
||||
strcpy (p, prefix);
|
||||
p += strlen (prefix);
|
||||
|
||||
if ((unsigned) stalls >
|
||||
visual_tbl_line_length - strlen (prefix) - strlen (suffix))
|
||||
{
|
||||
suffix = "[...]\n";
|
||||
stalls = visual_tbl_line_length - strlen (prefix) - strlen (suffix);
|
||||
}
|
||||
|
||||
memset (p, '.', stalls);
|
||||
p += stalls;
|
||||
|
||||
strcpy (p, suffix);
|
||||
}
|
||||
|
||||
/* Allocate data used for visualization during scheduling. */
|
||||
|
||||
void
|
||||
visualize_alloc (void)
|
||||
{
|
||||
visual_tbl = xmalloc (get_visual_tbl_length ());
|
||||
}
|
||||
|
||||
/* Free data used for visualization. */
|
||||
|
||||
void
|
||||
visualize_free (void)
|
||||
{
|
||||
free (visual_tbl);
|
||||
}
|
||||
#endif
|
||||
|
@ -233,7 +233,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#define TARGET_SCHED_REORDER 0
|
||||
#define TARGET_SCHED_REORDER2 0
|
||||
#define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK 0
|
||||
#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE 0
|
||||
#define TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN 0
|
||||
#define TARGET_SCHED_DFA_PRE_CYCLE_INSN 0
|
||||
#define TARGET_SCHED_INIT_DFA_POST_CYCLE_INSN 0
|
||||
@ -255,7 +254,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
TARGET_SCHED_REORDER, \
|
||||
TARGET_SCHED_REORDER2, \
|
||||
TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK, \
|
||||
TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE, \
|
||||
TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN, \
|
||||
TARGET_SCHED_DFA_PRE_CYCLE_INSN, \
|
||||
TARGET_SCHED_INIT_DFA_POST_CYCLE_INSN, \
|
||||
|
10
gcc/target.h
10
gcc/target.h
@ -213,12 +213,6 @@ struct gcc_target
|
||||
by two parameter values (head and tail correspondingly). */
|
||||
void (* dependencies_evaluation_hook) (rtx, rtx);
|
||||
|
||||
/* The following member value is a pointer to a function returning
|
||||
nonzero if we should use DFA based scheduling. The default is
|
||||
to use the old pipeline scheduler. */
|
||||
int (* use_dfa_pipeline_interface) (void);
|
||||
/* The values of all the following members are used only for the
|
||||
DFA based scheduler: */
|
||||
/* The values of the following four members are pointers to
|
||||
functions used to simplify the automaton descriptions.
|
||||
dfa_pre_cycle_insn and dfa_post_cycle_insn give functions
|
||||
@ -234,6 +228,7 @@ struct gcc_target
|
||||
rtx (* dfa_pre_cycle_insn) (void);
|
||||
void (* init_dfa_post_cycle_insn) (void);
|
||||
rtx (* dfa_post_cycle_insn) (void);
|
||||
|
||||
/* The following member value is a pointer to a function returning value
|
||||
which defines how many insns in queue `ready' will we try for
|
||||
multi-pass scheduling. If the member value is nonzero and the
|
||||
@ -242,12 +237,14 @@ struct gcc_target
|
||||
try to choose ready insn which permits to start maximum number of
|
||||
insns on the same cycle. */
|
||||
int (* first_cycle_multipass_dfa_lookahead) (void);
|
||||
|
||||
/* The following member value is pointer to a function controlling
|
||||
what insns from the ready insn queue will be considered for the
|
||||
multipass insn scheduling. If the hook returns zero for insn
|
||||
passed as the parameter, the insn will be not chosen to be
|
||||
issued. */
|
||||
int (* first_cycle_multipass_dfa_lookahead_guard) (rtx);
|
||||
|
||||
/* The following member value is pointer to a function called by
|
||||
the insn scheduler before issuing insn passed as the third
|
||||
parameter on given cycle. If the hook returns nonzero, the
|
||||
@ -261,6 +258,7 @@ struct gcc_target
|
||||
the previous insn has been issued and the current processor
|
||||
cycle. */
|
||||
int (* dfa_new_cycle) (FILE *, int, rtx, int, int, int *);
|
||||
|
||||
/* The following member value is a pointer to a function called
|
||||
by the insn scheduler. It should return true if there exists a
|
||||
dependence which is considered costly by the target, between
|
||||
|
Loading…
x
Reference in New Issue
Block a user