diff options
32 files changed, 306 insertions, 3094 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b83f93f..b609a50 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/bt-load.c b/gcc/bt-load.c index ea3d729..a397429 100644 --- a/gcc/bt-load.c +++ b/gcc/bt-load.c @@ -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 diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 646258b..5171fa3 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -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 diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index cbc0efa..9fc5ee2 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -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. */ diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index f342a80..460c3ef 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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 diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index 4011a51..11abe89 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -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 diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index d935540..ccc26cf 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -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 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index bcc9104..86ea389 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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 diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index bee9720..cb156b9 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -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 diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index b2156d6..a137744 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -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 diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c index c46bff5..a35c394 100644 --- a/gcc/config/m32r/m32r.c +++ b/gcc/config/m32r/m32r.c @@ -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 diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index c41ce8f..bdf50cc 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -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. */ diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index c3c7fa3..f5b2a08 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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 diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index ebe7a52..bd8b0a4 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -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 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index e81e1b3..e270f69 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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 diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 4ebfbb3..83e0c62 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -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 diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 5c5a72b..913bb34 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -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 diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index d378757..1c56087 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -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 diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index 11311c3..398fe7e 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -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 diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 29e72d4..66b04cf 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -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; diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 5949b8d..0e35053 100644 --- a/gcc/doc/md.texi +++ b/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 @@ -6116,61 +5975,6 @@ construction @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 @section Conditional Execution @cindex conditional execution diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index a8c410f..76fd387 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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 diff --git a/gcc/genattr.c b/gcc/genattr.c index 41ff649..0be3035 100644 --- a/gcc/genattr.c +++ b/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"); diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index c701488..f1bbaf5 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -21,7 +21,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This program handles insn attributes and the DEFINE_DELAY and - DEFINE_FUNCTION_UNIT definitions. + DEFINE_INSN_RESERVATION definitions. It produces a series of functions named `get_attr_...', one for each insn attribute. Each of these is given the rtx for an insn and returns a member @@ -54,7 +54,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA used. Internal attributes are defined to handle DEFINE_DELAY and - DEFINE_FUNCTION_UNIT. Special routines are output for these cases. + DEFINE_INSN_RESERVATION. Special routines are output for these cases. This program works by keeping a list of possible values for each attribute. These include the basic attribute choices, default values for attribute, and @@ -70,9 +70,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA indicates when the attribute has the specified value for the insn. This avoids recursive calls during compilation. - The strategy used when processing DEFINE_DELAY and DEFINE_FUNCTION_UNIT - definitions is to create arbitrarily complex expressions and have the - optimization simplify them. + The strategy used when processing DEFINE_DELAY definitions is to create + arbitrarily complex expressions and have the optimization simplify them. Once optimization is complete, any required routines and definitions will be written. @@ -193,21 +192,11 @@ struct attr_desc unsigned unsigned_p : 1; /* Make the output function unsigned int. */ unsigned is_const : 1; /* Attribute value constant for each run. */ unsigned is_special : 1; /* Don't call `write_attr_set'. */ - unsigned func_units_p : 1; /* This is the function_units attribute. */ - unsigned blockage_p : 1; /* This is the blockage range function. */ unsigned static_p : 1; /* Make the output function static. */ }; #define NULL_ATTR (struct attr_desc *) NULL -/* A range of values. */ - -struct range -{ - int min; - int max; -}; - /* Structure for each DEFINE_DELAY. */ struct delay_desc @@ -218,43 +207,6 @@ struct delay_desc int lineno; /* Line number. */ }; -/* Record information about each DEFINE_FUNCTION_UNIT. */ - -struct function_unit_op -{ - rtx condexp; /* Expression TRUE for applicable insn. */ - struct function_unit_op *next; /* Next operation for this function unit. */ - int num; /* Ordinal for this operation type in unit. */ - int ready; /* Cost until data is ready. */ - int issue_delay; /* Cost until unit can accept another insn. */ - rtx conflict_exp; /* Expression TRUE for insns incurring issue delay. */ - rtx issue_exp; /* Expression computing issue delay. */ - int lineno; /* Line number. */ -}; - -/* Record information about each function unit mentioned in a - DEFINE_FUNCTION_UNIT. */ - -struct function_unit -{ - const char *name; /* Function unit name. */ - struct function_unit *next; /* Next function unit. */ - int num; /* Ordinal of this unit type. */ - int multiplicity; /* Number of units of this type. */ - int simultaneity; /* Maximum number of simultaneous insns - on this function unit or 0 if unlimited. */ - rtx condexp; /* Expression TRUE for insn needing unit. */ - int num_opclasses; /* Number of different operation types. */ - struct function_unit_op *ops; /* Pointer to first operation type. */ - int needs_conflict_function; /* Nonzero if a conflict function required. */ - int needs_blockage_function; /* Nonzero if a blockage function required. */ - int needs_range_function; /* Nonzero if blockage range function needed. */ - rtx default_cost; /* Conflict cost, if constant. */ - struct range issue_delay; /* Range of issue delay values. */ - int max_blockage; /* Maximum time an insn blocks the unit. */ - int first_lineno; /* First seen line number. */ -}; - /* Listheads of above structures. */ /* This one is indexed by the first character of the attribute name. */ @@ -262,50 +214,6 @@ struct function_unit static struct attr_desc *attrs[MAX_ATTRS_INDEX]; static struct insn_def *defs; static struct delay_desc *delays; -static struct function_unit *units; - -/* An expression where all the unknown terms are EQ_ATTR tests can be - rearranged into a COND provided we can enumerate all possible - combinations of the unknown values. The set of combinations become the - tests of the COND; the value of the expression given that combination is - computed and becomes the corresponding value. To do this, we must be - able to enumerate all values for each attribute used in the expression - (currently, we give up if we find a numeric attribute). - - If the set of EQ_ATTR tests used in an expression tests the value of N - different attributes, the list of all possible combinations can be made - by walking the N-dimensional attribute space defined by those - attributes. We record each of these as a struct dimension. - - The algorithm relies on sharing EQ_ATTR nodes: if two nodes in an - expression are the same, the will also have the same address. We find - all the EQ_ATTR nodes by marking them ATTR_EQ_ATTR_P. This bit later - represents the value of an EQ_ATTR node, so once all nodes are marked, - they are also given an initial value of FALSE. - - We then separate the set of EQ_ATTR nodes into dimensions for each - attribute and put them on the VALUES list. Terms are added as needed by - `add_values_to_cover' so that all possible values of the attribute are - tested. - - Each dimension also has a current value. This is the node that is - currently considered to be TRUE. If this is one of the nodes added by - `add_values_to_cover', all the EQ_ATTR tests in the original expression - will be FALSE. Otherwise, only the CURRENT_VALUE will be true. - - NUM_VALUES is simply the length of the VALUES list and is there for - convenience. - - Once the dimensions are created, the algorithm enumerates all possible - values and computes the current value of the given expression. */ - -struct dimension -{ - struct attr_desc *attr; /* Attribute for this dimension. */ - rtx values; /* List of attribute values used. */ - rtx current_value; /* Position in the list for the TRUE value. */ - int num_values; /* Length of the values list. */ -}; /* Other variables. */ @@ -318,15 +226,10 @@ static int address_used; static int length_used; static int num_delays; static int have_annul_true, have_annul_false; -static int num_units, num_unit_opclasses; static int num_insn_ents; int num_dfa_decls; -/* Used as operand to `operate_exp': */ - -enum operator {PLUS_OP, MINUS_OP, POS_MINUS_OP, EQ_OP, OR_OP, ORX_OP, MAX_OP, MIN_OP, RANGE_OP}; - /* Stores, for each insn code, the number of constraint alternatives. */ static int *insn_n_alternatives; @@ -401,10 +304,6 @@ static struct attr_value *get_attr_value (rtx, struct attr_desc *, int); static rtx copy_rtx_unchanging (rtx); static rtx copy_boolean (rtx); static void expand_delays (void); -static rtx operate_exp (enum operator, rtx, rtx); -static void expand_units (void); -static rtx simplify_knowing (rtx, rtx); -static rtx encode_units_mask (rtx); static void fill_attr (struct attr_desc *); static rtx substitute_address (rtx, rtx (*) (rtx), rtx (*) (rtx)); static void make_length_attrs (void); @@ -414,14 +313,6 @@ static rtx one_fn (rtx); static rtx max_fn (rtx); static void write_length_unit_log (void); static rtx simplify_cond (rtx, int, int); -static rtx simplify_by_exploding (rtx); -static int find_and_mark_used_attributes (rtx, rtx *, int *); -static void unmark_used_attributes (rtx, struct dimension *, int); -static int add_values_to_cover (struct dimension *); -static int increment_current_value (struct dimension *, int); -static rtx test_for_current_value (struct dimension *, int); -static rtx simplify_with_current_value (rtx, struct dimension *, int); -static rtx simplify_with_current_value_aux (rtx); static void clear_struct_flag (rtx); static void remove_insn_ent (struct attr_value *, struct insn_ent *); static void insert_insn_ent (struct attr_value *, struct insn_ent *); @@ -440,7 +331,6 @@ static int compares_alternatives_p (rtx); static int contained_in_p (rtx, rtx); static void gen_insn (rtx, int); static void gen_delay (rtx, int); -static void gen_unit (rtx, int); static void write_test_expr (rtx, int); static int max_attr_value (rtx, int*); static int or_attr_value (rtx, int*); @@ -452,23 +342,16 @@ static void write_attr_set (struct attr_desc *, int, rtx, int, int); static void write_attr_case (struct attr_desc *, struct attr_value *, int, const char *, const char *, int, rtx); -static void write_unit_name (const char *, int, const char *); static void write_attr_valueq (struct attr_desc *, const char *); static void write_attr_value (struct attr_desc *, rtx); static void write_upcase (const char *); static void write_indent (int); static void write_eligible_delay (const char *); -static void write_function_unit_info (void); -static void write_complex_function (struct function_unit *, const char *, - const char *); static int write_expr_attr_cache (rtx, struct attr_desc *); -static void write_toplevel_expr (rtx); static void write_const_num_delay_slots (void); static char *next_comma_elt (const char **); static struct attr_desc *find_attr (const char **, int); static struct attr_value *find_most_used (struct attr_desc *); -static rtx find_single_value (struct attr_desc *); -static void extend_range (struct range *, int, int); static rtx attr_eq (const char *, const char *); static const char *attr_numeral (int); static int attr_equal_p (rtx, rtx); @@ -1606,654 +1489,6 @@ expand_delays (void) } } -/* This function is given a left and right side expression and an operator. - Each side is a conditional expression, each alternative of which has a - numerical value. The function returns another conditional expression - which, for every possible set of condition values, returns a value that is - the operator applied to the values of the two sides. - - Since this is called early, it must also support IF_THEN_ELSE. */ - -static rtx -operate_exp (enum operator op, rtx left, rtx right) -{ - int left_value, right_value; - rtx newexp; - int i; - - /* If left is a string, apply operator to it and the right side. */ - if (GET_CODE (left) == CONST_STRING) - { - /* If right is also a string, just perform the operation. */ - if (GET_CODE (right) == CONST_STRING) - { - left_value = atoi (XSTR (left, 0)); - right_value = atoi (XSTR (right, 0)); - switch (op) - { - case PLUS_OP: - i = left_value + right_value; - break; - - case MINUS_OP: - i = left_value - right_value; - break; - - case POS_MINUS_OP: /* The positive part of LEFT - RIGHT. */ - if (left_value > right_value) - i = left_value - right_value; - else - i = 0; - break; - - case OR_OP: - case ORX_OP: - i = left_value | right_value; - break; - - case EQ_OP: - i = left_value == right_value; - break; - - case RANGE_OP: - i = (left_value << (HOST_BITS_PER_INT / 2)) | right_value; - break; - - case MAX_OP: - if (left_value > right_value) - i = left_value; - else - i = right_value; - break; - - case MIN_OP: - if (left_value < right_value) - i = left_value; - else - i = right_value; - break; - - default: - abort (); - } - - if (i == left_value) - return left; - if (i == right_value) - return right; - return make_numeric_value (i); - } - else if (GET_CODE (right) == IF_THEN_ELSE) - { - /* Apply recursively to all values within. */ - rtx newleft = operate_exp (op, left, XEXP (right, 1)); - rtx newright = operate_exp (op, left, XEXP (right, 2)); - if (rtx_equal_p (newleft, newright)) - return newleft; - return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), newleft, newright); - } - else if (GET_CODE (right) == COND) - { - int allsame = 1; - rtx defval; - - newexp = rtx_alloc (COND); - XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0)); - defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1)); - - for (i = 0; i < XVECLEN (right, 0); i += 2) - { - XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i); - XVECEXP (newexp, 0, i + 1) - = operate_exp (op, left, XVECEXP (right, 0, i + 1)); - if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1), - defval)) - allsame = 0; - } - - /* If the resulting cond is trivial (all alternatives - give the same value), optimize it away. */ - if (allsame) - return operate_exp (op, left, XEXP (right, 1)); - - return newexp; - } - else - fatal ("badly formed attribute value"); - } - - /* A hack to prevent expand_units from completely blowing up: ORX_OP does - not associate through IF_THEN_ELSE. */ - else if (op == ORX_OP && GET_CODE (right) == IF_THEN_ELSE) - { - return attr_rtx (IOR, left, right); - } - - /* Otherwise, do recursion the other way. */ - else if (GET_CODE (left) == IF_THEN_ELSE) - { - rtx newleft = operate_exp (op, XEXP (left, 1), right); - rtx newright = operate_exp (op, XEXP (left, 2), right); - if (rtx_equal_p (newleft, newright)) - return newleft; - return attr_rtx (IF_THEN_ELSE, XEXP (left, 0), newleft, newright); - } - else if (GET_CODE (left) == COND) - { - int allsame = 1; - rtx defval; - - newexp = rtx_alloc (COND); - XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0)); - defval = XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right); - - for (i = 0; i < XVECLEN (left, 0); i += 2) - { - XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i); - XVECEXP (newexp, 0, i + 1) - = operate_exp (op, XVECEXP (left, 0, i + 1), right); - if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1), - defval)) - allsame = 0; - } - - /* If the cond is trivial (all alternatives give the same value), - optimize it away. */ - if (allsame) - return operate_exp (op, XEXP (left, 1), right); - - /* If the result is the same as the LEFT operand, - just use that. */ - if (rtx_equal_p (newexp, left)) - return left; - - return newexp; - } - - else - fatal ("badly formed attribute value"); - /* NOTREACHED */ - return NULL; -} - -/* Once all attributes and DEFINE_FUNCTION_UNITs have been read, we - construct a number of attributes. - - The first produces a function `function_units_used' which is given an - insn and produces an encoding showing which function units are required - for the execution of that insn. If the value is non-negative, the insn - uses that unit; otherwise, the value is a one's complement mask of units - used. - - The second produces a function `result_ready_cost' which is used to - determine the time that the result of an insn will be ready and hence - a worst-case schedule. - - Both of these produce quite complex expressions which are then set as the - default value of internal attributes. Normal attribute simplification - should produce reasonable expressions. - - For each unit, a `<name>_unit_ready_cost' function will take an - insn and give the delay until that unit will be ready with the result - and a `<name>_unit_conflict_cost' function is given an insn already - executing on the unit and a candidate to execute and will give the - cost from the time the executing insn started until the candidate - can start (ignore limitations on the number of simultaneous insns). - - For each unit, a `<name>_unit_blockage' function is given an insn - already executing on the unit and a candidate to execute and will - give the delay incurred due to function unit conflicts. The range of - blockage cost values for a given executing insn is given by the - `<name>_unit_blockage_range' function. These values are encoded in - an int where the upper half gives the minimum value and the lower - half gives the maximum value. */ - -static void -expand_units (void) -{ - struct function_unit *unit, **unit_num; - struct function_unit_op *op, **op_array, ***unit_ops; - rtx unitsmask; - rtx readycost; - rtx newexp; - const char *str; - int i, j, u, num, nvalues; - - /* Rebuild the condition for the unit to share the RTL expressions. - Sharing is required by simplify_by_exploding. Build the issue delay - expressions. Validate the expressions we were given for the conditions - and conflict vector. Then make attributes for use in the conflict - function. */ - - for (unit = units; unit; unit = unit->next) - { - unit->condexp = check_attr_test (unit->condexp, 0, unit->first_lineno); - - for (op = unit->ops; op; op = op->next) - { - rtx issue_delay = make_numeric_value (op->issue_delay); - rtx issue_exp = issue_delay; - - /* Build, validate, and simplify the issue delay expression. */ - if (op->conflict_exp != true_rtx) - issue_exp = attr_rtx (IF_THEN_ELSE, op->conflict_exp, - issue_exp, make_numeric_value (0)); - issue_exp = check_attr_value (make_canonical (NULL_ATTR, - issue_exp), - NULL_ATTR); - issue_exp = simplify_knowing (issue_exp, unit->condexp); - op->issue_exp = issue_exp; - - /* Make an attribute for use in the conflict function if needed. */ - unit->needs_conflict_function = (unit->issue_delay.min - != unit->issue_delay.max); - if (unit->needs_conflict_function) - { - str = attr_printf ((strlen (unit->name) + sizeof "*_cost_" - + MAX_DIGITS), - "*%s_cost_%d", unit->name, op->num); - make_internal_attr (str, issue_exp, ATTR_SPECIAL); - } - - /* Validate the condition. */ - op->condexp = check_attr_test (op->condexp, 0, op->lineno); - } - } - - /* Compute the mask of function units used. Initially, the unitsmask is - zero. Set up a conditional to compute each unit's contribution. */ - unitsmask = make_numeric_value (0); - newexp = rtx_alloc (IF_THEN_ELSE); - XEXP (newexp, 2) = make_numeric_value (0); - - /* If we have just a few units, we may be all right expanding the whole - thing. But the expansion is 2**N in space on the number of opclasses, - so we can't do this for very long -- Alpha and MIPS in particular have - problems with this. So in that situation, we fall back on an alternate - implementation method. */ -#define NUM_UNITOP_CUTOFF 20 - - if (num_unit_opclasses < NUM_UNITOP_CUTOFF) - { - /* Merge each function unit into the unit mask attributes. */ - for (unit = units; unit; unit = unit->next) - { - XEXP (newexp, 0) = unit->condexp; - XEXP (newexp, 1) = make_numeric_value (1 << unit->num); - unitsmask = operate_exp (OR_OP, unitsmask, newexp); - } - } - else - { - /* Merge each function unit into the unit mask attributes. */ - for (unit = units; unit; unit = unit->next) - { - XEXP (newexp, 0) = unit->condexp; - XEXP (newexp, 1) = make_numeric_value (1 << unit->num); - unitsmask = operate_exp (ORX_OP, unitsmask, attr_copy_rtx (newexp)); - } - } - - /* Simplify the unit mask expression, encode it, and make an attribute - for the function_units_used function. */ - unitsmask = simplify_by_exploding (unitsmask); - - if (num_unit_opclasses < NUM_UNITOP_CUTOFF) - unitsmask = encode_units_mask (unitsmask); - else - { - /* We can no longer encode unitsmask at compile time, so emit code to - calculate it at runtime. Rather, put a marker for where we'd do - the code, and actually output it in write_attr_get(). */ - unitsmask = attr_rtx (FFS, unitsmask); - } - - make_internal_attr ("*function_units_used", unitsmask, - (ATTR_NEGATIVE_OK | ATTR_FUNC_UNITS)); - - /* Create an array of ops for each unit. Add an extra unit for the - result_ready_cost function that has the ops of all other units. */ - unit_ops = xmalloc ((num_units + 1) * sizeof (struct function_unit_op **)); - unit_num = xmalloc ((num_units + 1) * sizeof (struct function_unit *)); - - unit_num[num_units] = unit = xmalloc (sizeof (struct function_unit)); - unit->num = num_units; - unit->num_opclasses = 0; - - for (unit = units; unit; unit = unit->next) - { - unit_num[num_units]->num_opclasses += unit->num_opclasses; - unit_num[unit->num] = unit; - unit_ops[unit->num] = op_array = - xmalloc (unit->num_opclasses * sizeof (struct function_unit_op *)); - - for (op = unit->ops; op; op = op->next) - op_array[op->num] = op; - } - - /* Compose the array of ops for the extra unit. */ - unit_ops[num_units] = op_array = - xmalloc (unit_num[num_units]->num_opclasses - * sizeof (struct function_unit_op *)); - - for (unit = units, i = 0; unit; i += unit->num_opclasses, unit = unit->next) - memcpy (&op_array[i], unit_ops[unit->num], - unit->num_opclasses * sizeof (struct function_unit_op *)); - - /* Compute the ready cost function for each unit by computing the - condition for each non-default value. */ - for (u = 0; u <= num_units; u++) - { - rtx orexp; - int value; - - unit = unit_num[u]; - op_array = unit_ops[unit->num]; - num = unit->num_opclasses; - - /* Sort the array of ops into increasing ready cost order. */ - for (i = 0; i < num; i++) - for (j = num - 1; j > i; j--) - if (op_array[j - 1]->ready < op_array[j]->ready) - { - op = op_array[j]; - op_array[j] = op_array[j - 1]; - op_array[j - 1] = op; - } - - /* Determine how many distinct non-default ready cost values there - are. We use a default ready cost value of 1. */ - nvalues = 0; value = 1; - for (i = num - 1; i >= 0; i--) - if (op_array[i]->ready > value) - { - value = op_array[i]->ready; - nvalues++; - } - - if (nvalues == 0) - readycost = make_numeric_value (1); - else - { - /* Construct the ready cost expression as a COND of each value from - the largest to the smallest. */ - readycost = rtx_alloc (COND); - XVEC (readycost, 0) = rtvec_alloc (nvalues * 2); - XEXP (readycost, 1) = make_numeric_value (1); - - nvalues = 0; - orexp = false_rtx; - value = op_array[0]->ready; - for (i = 0; i < num; i++) - { - op = op_array[i]; - if (op->ready <= 1) - break; - else if (op->ready == value) - orexp = insert_right_side (IOR, orexp, op->condexp, -2, -2); - else - { - XVECEXP (readycost, 0, nvalues * 2) = orexp; - XVECEXP (readycost, 0, nvalues * 2 + 1) - = make_numeric_value (value); - nvalues++; - value = op->ready; - orexp = op->condexp; - } - } - XVECEXP (readycost, 0, nvalues * 2) = orexp; - XVECEXP (readycost, 0, nvalues * 2 + 1) = make_numeric_value (value); - } - - if (u < num_units) - { - rtx max_blockage = 0, min_blockage = 0; - - /* Simplify the readycost expression by only considering insns - that use the unit. */ - readycost = simplify_knowing (readycost, unit->condexp); - - /* Determine the blockage cost the executing insn (E) given - the candidate insn (C). This is the maximum of the issue - delay, the pipeline delay, and the simultaneity constraint. - Each function_unit_op represents the characteristics of the - candidate insn, so in the expressions below, C is a known - term and E is an unknown term. - - We compute the blockage cost for each E for every possible C. - Thus OP represents E, and READYCOST is a list of values for - every possible C. - - The issue delay function for C is op->issue_exp and is used to - write the `<name>_unit_conflict_cost' function. Symbolically - this is "ISSUE-DELAY (E,C)". - - The pipeline delay results form the FIFO constraint on the - function unit and is "READY-COST (E) + 1 - READY-COST (C)". - - The simultaneity constraint is based on how long it takes to - fill the unit given the minimum issue delay. FILL-TIME is the - constant "MIN (ISSUE-DELAY (*,*)) * (SIMULTANEITY - 1)", and - the simultaneity constraint is "READY-COST (E) - FILL-TIME" - if SIMULTANEITY is nonzero and zero otherwise. - - Thus, 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) - - The `<name>_unit_blockage' function is computed by determining - this value for each candidate insn. As these values are - computed, we also compute the upper and lower bounds for - BLOCKAGE (E,*). These are combined to form the function - `<name>_unit_blockage_range'. Finally, the maximum blockage - cost, MAX (BLOCKAGE (*,*)), is computed. */ - - for (op = unit->ops; op; op = op->next) - { - rtx blockage = op->issue_exp; - blockage = simplify_knowing (blockage, unit->condexp); - - /* Add this op's contribution to MAX (BLOCKAGE (E,*)) and - MIN (BLOCKAGE (E,*)). */ - if (max_blockage == 0) - max_blockage = min_blockage = blockage; - else - { - max_blockage - = simplify_knowing (operate_exp (MAX_OP, max_blockage, - blockage), - unit->condexp); - min_blockage - = simplify_knowing (operate_exp (MIN_OP, min_blockage, - blockage), - unit->condexp); - } - - /* Make an attribute for use in the blockage function. */ - str = attr_printf ((strlen (unit->name) + sizeof "*_block_" - + MAX_DIGITS), - "*%s_block_%d", unit->name, op->num); - make_internal_attr (str, blockage, ATTR_SPECIAL); - } - - /* Record MAX (BLOCKAGE (*,*)). */ - { - int unknown; - unit->max_blockage = max_attr_value (max_blockage, &unknown); - } - - /* See if the upper and lower bounds of BLOCKAGE (E,*) are the - same. If so, the blockage function carries no additional - information and is not written. */ - newexp = operate_exp (EQ_OP, max_blockage, min_blockage); - newexp = simplify_knowing (newexp, unit->condexp); - unit->needs_blockage_function - = (GET_CODE (newexp) != CONST_STRING - || atoi (XSTR (newexp, 0)) != 1); - - /* If the all values of BLOCKAGE (E,C) have the same value, - neither blockage function is written. */ - unit->needs_range_function - = (unit->needs_blockage_function - || GET_CODE (max_blockage) != CONST_STRING); - - if (unit->needs_range_function) - { - /* Compute the blockage range function and make an attribute - for writing its value. */ - newexp = operate_exp (RANGE_OP, min_blockage, max_blockage); - newexp = simplify_knowing (newexp, unit->condexp); - - str = attr_printf ((strlen (unit->name) - + sizeof "*_unit_blockage_range"), - "*%s_unit_blockage_range", unit->name); - make_internal_attr (str, newexp, (ATTR_STATIC|ATTR_BLOCKAGE|ATTR_UNSIGNED)); - } - - str = attr_printf (strlen (unit->name) + sizeof "*_unit_ready_cost", - "*%s_unit_ready_cost", unit->name); - make_internal_attr (str, readycost, ATTR_STATIC); - } - else - { - /* Make an attribute for the ready_cost function. Simplifying - further with simplify_by_exploding doesn't win. */ - str = "*result_ready_cost"; - make_internal_attr (str, readycost, ATTR_NONE); - } - } - - /* For each unit that requires a conflict cost function, make an attribute - that maps insns to the operation number. */ - for (unit = units; unit; unit = unit->next) - { - rtx caseexp; - - if (! unit->needs_conflict_function - && ! unit->needs_blockage_function) - continue; - - caseexp = rtx_alloc (COND); - XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2); - - for (op = unit->ops; op; op = op->next) - { - /* Make our adjustment to the COND being computed. If we are the - last operation class, place our values into the default of the - COND. */ - if (op->num == unit->num_opclasses - 1) - { - XEXP (caseexp, 1) = make_numeric_value (op->num); - } - else - { - XVECEXP (caseexp, 0, op->num * 2) = op->condexp; - XVECEXP (caseexp, 0, op->num * 2 + 1) - = make_numeric_value (op->num); - } - } - - /* Simplifying caseexp with simplify_by_exploding doesn't win. */ - str = attr_printf (strlen (unit->name) + sizeof "*_cases", - "*%s_cases", unit->name); - make_internal_attr (str, caseexp, ATTR_SPECIAL); - } -} - -/* Simplify EXP given KNOWN_TRUE. */ - -static rtx -simplify_knowing (rtx exp, rtx known_true) -{ - if (GET_CODE (exp) != CONST_STRING) - { - int unknown = 0, max; - max = max_attr_value (exp, &unknown); - if (! unknown) - { - exp = attr_rtx (IF_THEN_ELSE, known_true, exp, - make_numeric_value (max)); - exp = simplify_by_exploding (exp); - } - } - return exp; -} - -/* Translate the CONST_STRING expressions in X to change the encoding of - value. On input, the value is a bitmask with a one bit for each unit - used; on output, the value is the unit number (zero based) if one - and only one unit is used or the one's complement of the bitmask. */ - -static rtx -encode_units_mask (rtx x) -{ - int i; - int j; - enum rtx_code code; - const char *fmt; - - code = GET_CODE (x); - - switch (code) - { - case CONST_STRING: - i = atoi (XSTR (x, 0)); - if (i < 0) - /* The sign bit encodes a one's complement mask. */ - abort (); - else if (i != 0 && i == (i & -i)) - /* Only one bit is set, so yield that unit number. */ - for (j = 0; (i >>= 1) != 0; j++) - ; - else - j = ~i; - return attr_rtx (CONST_STRING, attr_printf (MAX_DIGITS, "%d", j)); - - case REG: - case CONST_INT: - case CONST_DOUBLE: - case CONST_VECTOR: - case SYMBOL_REF: - case CODE_LABEL: - case PC: - case CC0: - case EQ_ATTR: - case EQ_ATTR_ALT: - return x; - - default: - break; - } - - /* Compare the elements. If any pair of corresponding elements - fail to match, return 0 for the whole things. */ - - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - switch (fmt[i]) - { - case 'V': - case 'E': - for (j = 0; j < XVECLEN (x, i); j++) - XVECEXP (x, i, j) = encode_units_mask (XVECEXP (x, i, j)); - break; - - case 'e': - XEXP (x, i) = encode_units_mask (XEXP (x, i)); - break; - } - } - return x; -} - /* Once all attributes and insns have been read and checked, we construct for each attribute value a list of all the insns that have that value for the attribute. */ @@ -3715,444 +2950,6 @@ optimize_attrs (void) free (insn_code_values - 2); } -/* If EXP is a suitable expression, reorganize it by constructing an - equivalent expression that is a COND with the tests being all combinations - of attribute values and the values being simple constants. */ - -static rtx -simplify_by_exploding (rtx exp) -{ - rtx list = 0, link, condexp, defval = NULL_RTX; - struct dimension *space; - rtx *condtest, *condval; - int i, j, total, ndim = 0; - int most_tests, num_marks, new_marks; - rtx ret; - - /* Locate all the EQ_ATTR expressions. */ - if (! find_and_mark_used_attributes (exp, &list, &ndim) || ndim == 0) - { - unmark_used_attributes (list, 0, 0); - return exp; - } - - /* Create an attribute space from the list of used attributes. For each - dimension in the attribute space, record the attribute, list of values - used, and number of values used. Add members to the list of values to - cover the domain of the attribute. This makes the expanded COND form - order independent. */ - - space = xmalloc (ndim * sizeof (struct dimension)); - - total = 1; - for (ndim = 0; list; ndim++) - { - /* Pull the first attribute value from the list and record that - attribute as another dimension in the attribute space. */ - const char *name = XSTR (XEXP (list, 0), 0); - rtx *prev; - - space[ndim].attr = find_attr (&name, 0); - XSTR (XEXP (list, 0), 0) = name; - - if (space[ndim].attr == 0 - || space[ndim].attr->is_numeric) - { - unmark_used_attributes (list, space, ndim); - return exp; - } - - /* Add all remaining attribute values that refer to this attribute. */ - space[ndim].num_values = 0; - space[ndim].values = 0; - prev = &list; - for (link = list; link; link = *prev) - if (! strcmp_check (XSTR (XEXP (link, 0), 0), name)) - { - space[ndim].num_values++; - *prev = XEXP (link, 1); - XEXP (link, 1) = space[ndim].values; - space[ndim].values = link; - } - else - prev = &XEXP (link, 1); - - /* Add sufficient members to the list of values to make the list - mutually exclusive and record the total size of the attribute - space. */ - total *= add_values_to_cover (&space[ndim]); - } - - /* Sort the attribute space so that the attributes go from non-constant - to constant and from most values to least values. */ - for (i = 0; i < ndim; i++) - for (j = ndim - 1; j > i; j--) - if ((space[j-1].attr->is_const && !space[j].attr->is_const) - || space[j-1].num_values < space[j].num_values) - { - struct dimension tmp; - tmp = space[j]; - space[j] = space[j - 1]; - space[j - 1] = tmp; - } - - /* Establish the initial current value. */ - for (i = 0; i < ndim; i++) - space[i].current_value = space[i].values; - - condtest = xmalloc (total * sizeof (rtx)); - condval = xmalloc (total * sizeof (rtx)); - - /* Expand the tests and values by iterating over all values in the - attribute space. */ - for (i = 0;; i++) - { - condtest[i] = test_for_current_value (space, ndim); - condval[i] = simplify_with_current_value (exp, space, ndim); - if (! increment_current_value (space, ndim)) - break; - } - if (i != total - 1) - abort (); - - /* We are now finished with the original expression. */ - unmark_used_attributes (0, space, ndim); - free (space); - - /* Find the most used constant value and make that the default. */ - most_tests = -1; - for (i = num_marks = 0; i < total; i++) - if (GET_CODE (condval[i]) == CONST_STRING - && ! ATTR_EQ_ATTR_P (condval[i])) - { - /* Mark the unmarked constant value and count how many are marked. */ - ATTR_EQ_ATTR_P (condval[i]) = 1; - for (j = new_marks = 0; j < total; j++) - if (GET_CODE (condval[j]) == CONST_STRING - && ATTR_EQ_ATTR_P (condval[j])) - new_marks++; - if (new_marks - num_marks > most_tests) - { - most_tests = new_marks - num_marks; - defval = condval[i]; - } - num_marks = new_marks; - } - /* Clear all the marks. */ - for (i = 0; i < total; i++) - ATTR_EQ_ATTR_P (condval[i]) = 0; - - /* Give up if nothing is constant. */ - if (num_marks == 0) - ret = exp; - - /* If all values are the default, use that. */ - else if (total == most_tests) - ret = defval; - - /* Make a COND with the most common constant value the default. (A more - complex method where tests with the same value were combined didn't - seem to improve things.) */ - else - { - condexp = rtx_alloc (COND); - XVEC (condexp, 0) = rtvec_alloc ((total - most_tests) * 2); - XEXP (condexp, 1) = defval; - for (i = j = 0; i < total; i++) - if (condval[i] != defval) - { - XVECEXP (condexp, 0, 2 * j) = condtest[i]; - XVECEXP (condexp, 0, 2 * j + 1) = condval[i]; - j++; - } - ret = condexp; - } - free (condtest); - free (condval); - return ret; -} - -/* Set the ATTR_EQ_ATTR_P flag for all EQ_ATTR expressions in EXP and - verify that EXP can be simplified to a constant term if all the EQ_ATTR - tests have known value. */ - -static int -find_and_mark_used_attributes (rtx exp, rtx *terms, int *nterms) -{ - int i; - - switch (GET_CODE (exp)) - { - case EQ_ATTR: - if (! ATTR_EQ_ATTR_P (exp)) - { - rtx link = rtx_alloc (EXPR_LIST); - XEXP (link, 0) = exp; - XEXP (link, 1) = *terms; - *terms = link; - *nterms += 1; - ATTR_EQ_ATTR_P (exp) = 1; - } - return 1; - - case CONST_STRING: - case CONST_INT: - return 1; - - case IF_THEN_ELSE: - if (! find_and_mark_used_attributes (XEXP (exp, 2), terms, nterms)) - return 0; - case IOR: - case AND: - if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms)) - return 0; - case NOT: - if (! find_and_mark_used_attributes (XEXP (exp, 0), terms, nterms)) - return 0; - return 1; - - case COND: - for (i = 0; i < XVECLEN (exp, 0); i++) - if (! find_and_mark_used_attributes (XVECEXP (exp, 0, i), terms, nterms)) - return 0; - if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms)) - return 0; - return 1; - - default: - return 0; - } -} - -/* Clear the ATTR_EQ_ATTR_P flag in all EQ_ATTR expressions on LIST and - in the values of the NDIM-dimensional attribute space SPACE. */ - -static void -unmark_used_attributes (rtx list, struct dimension *space, int ndim) -{ - rtx link, exp; - int i; - - for (i = 0; i < ndim; i++) - unmark_used_attributes (space[i].values, 0, 0); - - for (link = list; link; link = XEXP (link, 1)) - { - exp = XEXP (link, 0); - if (GET_CODE (exp) == EQ_ATTR) - ATTR_EQ_ATTR_P (exp) = 0; - } -} - -/* Update the attribute dimension DIM so that all values of the attribute - are tested. Return the updated number of values. */ - -static int -add_values_to_cover (struct dimension *dim) -{ - struct attr_value *av; - rtx exp, link, *prev; - int nalt = 0; - - for (av = dim->attr->first_value; av; av = av->next) - if (GET_CODE (av->value) == CONST_STRING) - nalt++; - - if (nalt < dim->num_values) - abort (); - else if (nalt == dim->num_values) - /* OK. */ - ; - else if (nalt * 2 < dim->num_values * 3) - { - /* Most all the values of the attribute are used, so add all the unused - values. */ - prev = &dim->values; - for (link = dim->values; link; link = *prev) - prev = &XEXP (link, 1); - - for (av = dim->attr->first_value; av; av = av->next) - if (GET_CODE (av->value) == CONST_STRING) - { - exp = attr_eq (dim->attr->name, XSTR (av->value, 0)); - if (ATTR_EQ_ATTR_P (exp)) - continue; - - link = rtx_alloc (EXPR_LIST); - XEXP (link, 0) = exp; - XEXP (link, 1) = 0; - *prev = link; - prev = &XEXP (link, 1); - } - dim->num_values = nalt; - } - else - { - rtx orexp = false_rtx; - - /* Very few values are used, so compute a mutually exclusive - expression. (We could do this for numeric values if that becomes - important.) */ - prev = &dim->values; - for (link = dim->values; link; link = *prev) - { - orexp = insert_right_side (IOR, orexp, XEXP (link, 0), -2, -2); - prev = &XEXP (link, 1); - } - link = rtx_alloc (EXPR_LIST); - XEXP (link, 0) = attr_rtx (NOT, orexp); - XEXP (link, 1) = 0; - *prev = link; - dim->num_values++; - } - return dim->num_values; -} - -/* Increment the current value for the NDIM-dimensional attribute space SPACE - and return FALSE if the increment overflowed. */ - -static int -increment_current_value (struct dimension *space, int ndim) -{ - int i; - - for (i = ndim - 1; i >= 0; i--) - { - if ((space[i].current_value = XEXP (space[i].current_value, 1)) == 0) - space[i].current_value = space[i].values; - else - return 1; - } - return 0; -} - -/* Construct an expression corresponding to the current value for the - NDIM-dimensional attribute space SPACE. */ - -static rtx -test_for_current_value (struct dimension *space, int ndim) -{ - int i; - rtx exp = true_rtx; - - for (i = 0; i < ndim; i++) - exp = insert_right_side (AND, exp, XEXP (space[i].current_value, 0), - -2, -2); - - return exp; -} - -/* Given the current value of the NDIM-dimensional attribute space SPACE, - set the corresponding EQ_ATTR expressions to that value and reduce - the expression EXP as much as possible. On input [and output], all - known EQ_ATTR expressions are set to FALSE. */ - -static rtx -simplify_with_current_value (rtx exp, struct dimension *space, int ndim) -{ - int i; - rtx x; - - /* Mark each current value as TRUE. */ - for (i = 0; i < ndim; i++) - { - x = XEXP (space[i].current_value, 0); - if (GET_CODE (x) == EQ_ATTR) - ATTR_EQ_ATTR_P (x) = 0; - } - - exp = simplify_with_current_value_aux (exp); - - /* Change each current value back to FALSE. */ - for (i = 0; i < ndim; i++) - { - x = XEXP (space[i].current_value, 0); - if (GET_CODE (x) == EQ_ATTR) - ATTR_EQ_ATTR_P (x) = 1; - } - - return exp; -} - -/* Reduce the expression EXP based on the ATTR_EQ_ATTR_P settings of - all EQ_ATTR expressions. */ - -static rtx -simplify_with_current_value_aux (rtx exp) -{ - int i; - rtx cond; - - switch (GET_CODE (exp)) - { - case EQ_ATTR: - if (ATTR_EQ_ATTR_P (exp)) - return false_rtx; - else - return true_rtx; - case CONST_STRING: - case CONST_INT: - return exp; - - case IF_THEN_ELSE: - cond = simplify_with_current_value_aux (XEXP (exp, 0)); - if (cond == true_rtx) - return simplify_with_current_value_aux (XEXP (exp, 1)); - else if (cond == false_rtx) - return simplify_with_current_value_aux (XEXP (exp, 2)); - else - return attr_rtx (IF_THEN_ELSE, cond, - simplify_with_current_value_aux (XEXP (exp, 1)), - simplify_with_current_value_aux (XEXP (exp, 2))); - - case IOR: - cond = simplify_with_current_value_aux (XEXP (exp, 1)); - if (cond == true_rtx) - return cond; - else if (cond == false_rtx) - return simplify_with_current_value_aux (XEXP (exp, 0)); - else - return attr_rtx (IOR, cond, - simplify_with_current_value_aux (XEXP (exp, 0))); - - case AND: - cond = simplify_with_current_value_aux (XEXP (exp, 1)); - if (cond == true_rtx) - return simplify_with_current_value_aux (XEXP (exp, 0)); - else if (cond == false_rtx) - return cond; - else - return attr_rtx (AND, cond, - simplify_with_current_value_aux (XEXP (exp, 0))); - - case NOT: - cond = simplify_with_current_value_aux (XEXP (exp, 0)); - if (cond == true_rtx) - return false_rtx; - else if (cond == false_rtx) - return true_rtx; - else - return attr_rtx (NOT, cond); - - case COND: - for (i = 0; i < XVECLEN (exp, 0); i += 2) - { - cond = simplify_with_current_value_aux (XVECEXP (exp, 0, i)); - if (cond == true_rtx) - return simplify_with_current_value_aux (XVECEXP (exp, 0, i + 1)); - else if (cond == false_rtx) - continue; - else - abort (); /* With all EQ_ATTR's of known value, a case should - have been selected. */ - } - return simplify_with_current_value_aux (XEXP (exp, 1)); - - default: - abort (); - } -} - /* Clear the ATTR_CURR_SIMPLIFIED_P flag in EXP and its subexpressions. */ static void @@ -4454,97 +3251,6 @@ gen_delay (rtx def, int lineno) delays = delay; } -/* Process a DEFINE_FUNCTION_UNIT. - - This gives information about a function unit contained in the CPU. - We fill in a `struct function_unit_op' and a `struct function_unit' - with information used later by `expand_unit'. */ - -static void -gen_unit (rtx def, int lineno) -{ - struct function_unit *unit; - struct function_unit_op *op; - const char *name = XSTR (def, 0); - int multiplicity = XINT (def, 1); - int simultaneity = XINT (def, 2); - rtx condexp = XEXP (def, 3); - int ready_cost = MAX (XINT (def, 4), 1); - int issue_delay = MAX (XINT (def, 5), 1); - - /* See if we have already seen this function unit. If so, check that - the multiplicity and simultaneity values are the same. If not, make - a structure for this function unit. */ - for (unit = units; unit; unit = unit->next) - if (! strcmp (unit->name, name)) - { - if (unit->multiplicity != multiplicity - || unit->simultaneity != simultaneity) - { - message_with_line (lineno, - "differing specifications given for function unit %s", - unit->name); - message_with_line (unit->first_lineno, "previous definition"); - have_error = 1; - return; - } - break; - } - - if (unit == 0) - { - unit = oballoc (sizeof (struct function_unit)); - unit->name = name; - unit->multiplicity = multiplicity; - unit->simultaneity = simultaneity; - unit->issue_delay.min = unit->issue_delay.max = issue_delay; - unit->num = num_units++; - unit->num_opclasses = 0; - unit->condexp = false_rtx; - unit->ops = 0; - unit->next = units; - unit->first_lineno = lineno; - units = unit; - } - else - XSTR (def, 0) = unit->name; - - /* Make a new operation class structure entry and initialize it. */ - op = oballoc (sizeof (struct function_unit_op)); - op->condexp = condexp; - op->num = unit->num_opclasses++; - op->ready = ready_cost; - op->issue_delay = issue_delay; - op->next = unit->ops; - op->lineno = lineno; - unit->ops = op; - num_unit_opclasses++; - - /* Set our issue expression based on whether or not an optional conflict - vector was specified. */ - if (XVEC (def, 6)) - { - /* Compute the IOR of all the specified expressions. */ - rtx orexp = false_rtx; - int i; - - for (i = 0; i < XVECLEN (def, 6); i++) - orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2, -2); - - op->conflict_exp = orexp; - extend_range (&unit->issue_delay, 1, issue_delay); - } - else - { - op->conflict_exp = true_rtx; - extend_range (&unit->issue_delay, issue_delay, issue_delay); - } - - /* Merge our conditional into that of the function unit so we can determine - which insns are used by the function unit. */ - unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2, -2); -} - /* Given a piece of RTX, print a C expression to test its truth value. We use AND and IOR both for logical and bit-wise operations, so interpret them as logical unless they are inside a comparison expression. @@ -5041,37 +3747,15 @@ write_attr_get (struct attr_desc *attr) } printf ("{\n"); + printf (" switch (recog_memoized (insn))\n"); + printf (" {\n"); - if (GET_CODE (common_av->value) == FFS) - { - rtx p = XEXP (common_av->value, 0); - - /* No need to emit code to abort if the insn is unrecognized; the - other get_attr_foo functions will do that when we call them. */ - - write_toplevel_expr (p); - - printf ("\n if (accum && accum == (accum & -accum))\n"); - printf (" {\n"); - printf (" int i;\n"); - printf (" for (i = 0; accum >>= 1; ++i) continue;\n"); - printf (" accum = i;\n"); - printf (" }\n else\n"); - printf (" accum = ~accum;\n"); - printf (" return accum;\n}\n\n"); - } - else - { - printf (" switch (recog_memoized (insn))\n"); - printf (" {\n"); - - for (av = attr->first_value; av; av = av->next) - if (av != common_av) - write_attr_case (attr, av, 1, "return", ";", 4, true_rtx); + for (av = attr->first_value; av; av = av->next) + if (av != common_av) + write_attr_case (attr, av, 1, "return", ";", 4, true_rtx); - write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx); - printf (" }\n}\n\n"); - } + write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx); + printf (" }\n}\n\n"); } /* Given an AND tree of known true terms (because we are inside an `if' with @@ -5307,56 +3991,7 @@ write_expr_attr_cache (rtx p, struct attr_desc *attr) return 0; } -/* Evaluate an expression at top level. A front end to write_test_expr, - in which we cache attribute values and break up excessively large - expressions to cater to older compilers. */ - -static void -write_toplevel_expr (rtx p) -{ - struct attr_desc *attr; - int i; - - for (i = 0; i < MAX_ATTRS_INDEX; ++i) - for (attr = attrs[i]; attr; attr = attr->next) - if (!attr->is_const) - write_expr_attr_cache (p, attr); - - printf (" unsigned long accum = 0;\n\n"); - - while (GET_CODE (p) == IOR) - { - rtx e; - if (GET_CODE (XEXP (p, 0)) == IOR) - e = XEXP (p, 1), p = XEXP (p, 0); - else - e = XEXP (p, 0), p = XEXP (p, 1); - - printf (" accum |= "); - write_test_expr (e, 3); - printf (";\n"); - } - printf (" accum |= "); - write_test_expr (p, 3); - printf (";\n"); -} - -/* Utilities to write names in various forms. */ - -static void -write_unit_name (const char *prefix, int num, const char *suffix) -{ - struct function_unit *unit; - - for (unit = units; unit; unit = unit->next) - if (unit->num == num) - { - printf ("%s%s%s", prefix, unit->name, suffix); - return; - } - - printf ("%s<unknown>%s", prefix, suffix); -} +/* Utilities to write in various forms. */ static void write_attr_valueq (struct attr_desc *attr, const char *s) @@ -5367,32 +4002,7 @@ write_attr_valueq (struct attr_desc *attr, const char *s) printf ("%d", num); - /* Make the blockage range values and function units used values easier - to read. */ - if (attr->func_units_p) - { - if (num == -1) - printf (" /* units: none */"); - else if (num >= 0) - write_unit_name (" /* units: ", num, " */"); - else - { - int i; - const char *sep = " /* units: "; - for (i = 0, num = ~num; num; i++, num >>= 1) - if (num & 1) - { - write_unit_name (sep, i, (num == 1) ? " */" : ""); - sep = ", "; - } - } - } - - else if (attr->blockage_p) - printf (" /* min %d, max %d */", num >> (HOST_BITS_PER_INT / 2), - num & ((1 << (HOST_BITS_PER_INT / 2)) - 1)); - - else if (num > 9 || num < 0) + if (num > 9 || num < 0) printf (" /* 0x%x */", num); } else @@ -5613,175 +4223,6 @@ write_eligible_delay (const char *kind) printf ("}\n\n"); } -/* Write routines to compute conflict cost for function units. Then write a - table describing the available function units. */ - -static void -write_function_unit_info (void) -{ - struct function_unit *unit; - int i; - - /* Write out conflict routines for function units. Don't bother writing - one if there is only one issue delay value. */ - - for (unit = units; unit; unit = unit->next) - { - if (unit->needs_blockage_function) - write_complex_function (unit, "blockage", "block"); - - /* If the minimum and maximum conflict costs are the same, there - is only one value, so we don't need a function. */ - if (! unit->needs_conflict_function) - { - unit->default_cost = make_numeric_value (unit->issue_delay.max); - continue; - } - - /* The function first computes the case from the candidate insn. */ - unit->default_cost = make_numeric_value (0); - write_complex_function (unit, "conflict_cost", "cost"); - } - - /* Now that all functions have been written, write the table describing - the function units. The name is included for documentation purposes - only. */ - - printf ("const struct function_unit_desc function_units[] = {\n"); - - /* Write out the descriptions in numeric order, but don't force that order - on the list. Doing so increases the runtime of genattrtab.c. */ - for (i = 0; i < num_units; i++) - { - for (unit = units; unit; unit = unit->next) - if (unit->num == i) - break; - - printf (" {\"%s\", %d, %d, %d, %s, %d, %s_unit_ready_cost, ", - unit->name, 1 << unit->num, unit->multiplicity, - unit->simultaneity, XSTR (unit->default_cost, 0), - unit->issue_delay.max, unit->name); - - if (unit->needs_conflict_function) - printf ("%s_unit_conflict_cost, ", unit->name); - else - printf ("0, "); - - printf ("%d, ", unit->max_blockage); - - if (unit->needs_range_function) - printf ("%s_unit_blockage_range, ", unit->name); - else - printf ("0, "); - - if (unit->needs_blockage_function) - printf ("%s_unit_blockage", unit->name); - else - printf ("0"); - - printf ("}, \n"); - } - - if (num_units == 0) - printf ("{\"dummy\", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} /* a dummy element */"); - printf ("};\n\n"); -} - -static void -write_complex_function (struct function_unit *unit, - const char *name, - const char *connection) -{ - struct attr_desc *case_attr, *attr; - struct attr_value *av, *common_av; - rtx value; - char str[256]; - const char *pstr; - int using_case; - int i; - - printf ("static int\n"); - printf ("%s_unit_%s (rtx executing_insn, rtx candidate_insn)\n", - unit->name, name); - printf ("{\n"); - printf (" rtx insn;\n"); - printf (" int casenum;\n\n"); - printf (" insn = executing_insn;\n"); - printf (" switch (recog_memoized (insn))\n"); - printf (" {\n"); - - /* Write the `switch' statement to get the case value. */ - if (strlen (unit->name) + sizeof "*_cases" > 256) - abort (); - sprintf (str, "*%s_cases", unit->name); - pstr = str; - case_attr = find_attr (&pstr, 0); - if (! case_attr) - abort (); - common_av = find_most_used (case_attr); - - for (av = case_attr->first_value; av; av = av->next) - if (av != common_av) - write_attr_case (case_attr, av, 1, - "casenum =", ";", 4, unit->condexp); - - write_attr_case (case_attr, common_av, 0, - "casenum =", ";", 4, unit->condexp); - printf (" }\n\n"); - - /* Now write an outer switch statement on each case. Then write - the tests on the executing function within each. */ - printf (" insn = candidate_insn;\n"); - printf (" switch (casenum)\n"); - printf (" {\n"); - - for (i = 0; i < unit->num_opclasses; i++) - { - /* Ensure using this case. */ - using_case = 0; - for (av = case_attr->first_value; av; av = av->next) - if (av->num_insns - && contained_in_p (make_numeric_value (i), av->value)) - using_case = 1; - - if (! using_case) - continue; - - printf (" case %d:\n", i); - sprintf (str, "*%s_%s_%d", unit->name, connection, i); - pstr = str; - attr = find_attr (&pstr, 0); - if (! attr) - abort (); - - /* If single value, just write it. */ - value = find_single_value (attr); - if (value) - write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2, -2); - else - { - common_av = find_most_used (attr); - printf (" switch (recog_memoized (insn))\n"); - printf ("\t{\n"); - - for (av = attr->first_value; av; av = av->next) - if (av != common_av) - write_attr_case (attr, av, 1, - "return", ";", 8, unit->condexp); - - write_attr_case (attr, common_av, 0, - "return", ";", 8, unit->condexp); - printf (" }\n\n"); - } - } - - /* This default case should not be needed, but gcc's analysis is not - good enough to realize that the default case is not needed for the - second switch statement. */ - printf (" default:\n abort ();\n"); - printf (" }\n}\n\n"); -} - /* This page contains miscellaneous utility routines. */ /* Given a pointer to a (char *), return a malloc'ed string containing the @@ -5837,7 +4278,7 @@ find_attr (const char **name_p, int create) attr->name = DEF_ATTR_STRING (name); attr->first_value = attr->default_val = NULL; attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0; - attr->unsigned_p = attr->func_units_p = attr->blockage_p = attr->static_p = 0; + attr->unsigned_p = attr->static_p = 0; attr->next = attrs[index]; attrs[index] = attr; @@ -5862,8 +4303,6 @@ make_internal_attr (const char *name, rtx value, int special) attr->is_special = (special & ATTR_SPECIAL) != 0; attr->negative_ok = (special & ATTR_NEGATIVE_OK) != 0; attr->unsigned_p = (special & ATTR_UNSIGNED) != 0; - attr->func_units_p = (special & ATTR_FUNC_UNITS) != 0; - attr->blockage_p = (special & ATTR_BLOCKAGE) != 0; attr->static_p = (special & ATTR_STATIC) != 0; attr->default_val = get_attr_value (value, attr, -2); } @@ -5887,28 +4326,6 @@ find_most_used (struct attr_desc *attr) return most_used; } -/* If an attribute only has a single value used, return it. Otherwise - return NULL. */ - -static rtx -find_single_value (struct attr_desc *attr) -{ - struct attr_value *av; - rtx unique_value; - - unique_value = NULL; - for (av = attr->first_value; av; av = av->next) - if (av->num_insns) - { - if (unique_value) - return NULL; - else - unique_value = av->value; - } - - return unique_value; -} - /* Return (attr_value "n") */ rtx @@ -5933,15 +4350,6 @@ make_numeric_value (int n) return exp; } -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 rtx copy_rtx_unchanging (rtx orig) { @@ -6052,10 +4460,6 @@ from the machine description file `md'. */\n\n"); gen_delay (desc, lineno); break; - case DEFINE_FUNCTION_UNIT: - gen_unit (desc, lineno); - break; - case DEFINE_CPU_UNIT: gen_cpu_unit (desc); break; @@ -6128,14 +4532,10 @@ from the machine description file `md'. */\n\n"); if (num_delays) expand_delays (); - if (num_units || num_dfa_decls) - { - /* Expand DEFINE_FUNCTION_UNIT information into new attributes. */ - expand_units (); - /* Build DFA, output some functions and expand DFA information - into new attributes. */ - expand_automata (); - } + /* Build DFA, output some functions and expand DFA information + to new attributes. */ + if (num_dfa_decls) + expand_automata (); printf ("#include \"config.h\"\n"); printf ("#include \"system.h\"\n"); @@ -6191,8 +4591,7 @@ from the machine description file `md'. */\n\n"); optimize_attrs (); /* Now write out all the `gen_attr_...' routines. Do these before the - special routines (specifically before write_function_unit_info), so - that they get defined before they are used. */ + special routines so that they get defined before they are used. */ for (i = 0; i < MAX_ATTRS_INDEX; i++) for (attr = attrs[i]; attr; attr = attr->next) @@ -6224,14 +4623,10 @@ from the machine description file `md'. */\n\n"); write_eligible_delay ("annul_false"); } - if (num_units || num_dfa_decls) - { - /* Write out information about function units. */ - write_function_unit_info (); - /* Output code for pipeline hazards recognition based on DFA - (deterministic finite state automata. */ - write_automata (); - } + /* Output code for pipeline hazards recognition based on DFA + (deterministic finite-state automata). */ + if (num_dfa_decls) + write_automata (); /* Write out constant delay slot info. */ write_const_num_delay_slots (); diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 1e29e7f..ad782cc 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -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 ()); - - 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_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 ()); } /* 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,78 +1995,65 @@ 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); } - 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; + 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); + /* 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; - } + 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; - } + 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 - { - cost = state_transition (temp_state, insn); - if (cost < 0) - cost = 0; - else if (cost == 0) - cost = 1; - } + /* 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; } - if (cost >= 1) { @@ -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) diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index 731cbe7..d9cb45c 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -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++) diff --git a/gcc/rtl.def b/gcc/rtl.def index 50d947d..fd23963 100644 --- a/gcc/rtl.def +++ b/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) diff --git a/gcc/sched-int.h b/gcc/sched-int.h index 383a29d..8dddc9e 100644 --- a/gcc/sched-int.h +++ b/gcc/sched-int.h @@ -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 */ diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c index 698cadd..325e169 100644 --- a/gcc/sched-rgn.c +++ b/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); + rtx head, tail; + rtx next_tail; + rtx insn; - if (targetm.sched.use_dfa_pipeline_interface - && targetm.sched.use_dfa_pipeline_interface ()) - { - 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", - "----", "----", "--", "---", "----", "----", "--------", "-----"); - } + 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 link; - for (insn = head; insn != next_tail; insn = NEXT_INSN (insn)) + if (! INSN_P (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"); diff --git a/gcc/sched-vis.c b/gcc/sched-vis.c index 8568306..c7c5427 100644 --- a/gcc/sched-vis.c +++ b/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 diff --git a/gcc/target-def.h b/gcc/target-def.h index 242d535..a3edb01 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -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, \ diff --git a/gcc/target.h b/gcc/target.h index 2a304a0..cdcaa18 100644 --- a/gcc/target.h +++ b/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 |