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:
Paolo Bonzini 2004-07-20 07:27:18 +00:00 committed by Paolo Bonzini
parent 31aedc36c0
commit fa0aee8996
32 changed files with 308 additions and 3096 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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