1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
4 Written by Vladimir Makarov <vmakarov@redhat.com>
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 GNU CC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 1. Detecting pipeline structural hazards quickly. T. Proebsting,
26 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
27 Principles of Programming Languages, pages 280--286, 1994.
29 This article is a good start point to understand usage of finite
30 state automata for pipeline hazard recognizers. But I'd
31 recommend the 2nd article for more deep understanding.
33 2. Efficient Instruction Scheduling Using Finite State Automata:
34 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
35 article about usage of finite state automata for pipeline hazard
38 The current implementation is different from the 2nd article in the
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministicly and
45 2. Possibility of usage of nondeterministic automata too.
47 3. Possibility to query functional unit reservations for given
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', `final_presence_set',
52 `absence_set', and `final_absence_set').
54 5. No reverse automata are generated. Trace instruction scheduling
55 requires this. It can be easily added in the future if we
58 6. Union of automaton states are not generated yet. It is planned
59 to be implemented. Such feature is needed to make more accurate
60 interlock insn scheduling to get state describing functional
61 unit reservation in a joint CFG point. */
63 /* This file code processes constructions of machine description file
64 which describes automaton used for recognition of processor pipeline
65 hazards by insn scheduler and can be used for other tasks (such as
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_final_presence_set', `gen_absence_set',
71 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
72 `gen_reserv', `gen_insn_reserv' are called from file
73 `genattrtab.c'. They transform RTL constructions describing
74 automata in .md file into internal representation convenient for
77 The translator major function `expand_automata' processes the
78 description internal representation into finite state automaton.
81 o checking correctness of the automaton pipeline description
82 (major function is `check_all_description').
84 o generating automaton (automata) from the description (major
85 function is `make_automaton').
87 o optional transformation of nondeterministic finite state
88 automata into deterministic ones if the alternative operator
89 `|' is treated nondeterministically in the description (major
90 function is NDFA_to_DFA).
92 o optional minimization of the finite state automata by merging
93 equivalent automaton states (major function is `minimize_DFA').
95 o forming tables (some as comb vectors) and attributes
96 representing the automata (functions output_..._table).
98 Function `write_automata' outputs the created finite state
99 automaton as different tables and functions which works with the
100 automata to inquire automaton state and to change its state. These
101 function are used by gcc instruction scheduler and may be some
106 #include "coretypes.h"
120 #include "genattrtab.h"
122 /* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
126 /* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128 typedef unsigned HOST_WIDE_INT set_el_t
;
130 /* Reservations of function units are represented by value of the following
132 typedef set_el_t
*reserv_sets_t
;
134 /* The following structure represents variable length array (vla) of
135 pointers and HOST WIDE INTs. We could be use only varray. But we
136 add new lay because we add elements very frequently and this could
137 stress OS allocator when varray is used only. */
139 size_t length
; /* current size of vla. */
140 varray_type varray
; /* container for vla. */
143 typedef vla_ptr_t vla_hwint_t
;
145 /* The following structure describes a ticker. */
148 /* The following member value is time of the ticker creation with
149 taking into account time when the ticker is off. Active time of
150 the ticker is current time minus the value. */
151 int modified_creation_time
;
152 /* The following member value is time (incremented by one) when the
153 ticker was off. Zero value means that now the ticker is on. */
154 int incremented_off_time
;
157 /* The ticker is represented by the following type. */
158 typedef struct ticker ticker_t
;
160 /* The following type describes elements of output vectors. */
161 typedef HOST_WIDE_INT vect_el_t
;
163 /* Forward declaration of structures of internal representation of
164 pipeline description based on NDFA. */
169 struct automaton_decl
;
170 struct unit_pattern_rel_decl
;
172 struct insn_reserv_decl
;
175 struct result_regexp
;
176 struct reserv_regexp
;
177 struct nothing_regexp
;
178 struct sequence_regexp
;
179 struct repeat_regexp
;
185 struct pattern_set_el
;
186 struct pattern_reserv
;
192 struct state_ainsn_table
;
194 /* The following typedefs are for brevity. */
195 typedef struct unit_decl
*unit_decl_t
;
196 typedef struct decl
*decl_t
;
197 typedef struct regexp
*regexp_t
;
198 typedef struct unit_set_el
*unit_set_el_t
;
199 typedef struct pattern_set_el
*pattern_set_el_t
;
200 typedef struct pattern_reserv
*pattern_reserv_t
;
201 typedef struct alt_state
*alt_state_t
;
202 typedef struct state
*state_t
;
203 typedef struct arc
*arc_t
;
204 typedef struct ainsn
*ainsn_t
;
205 typedef struct automaton
*automaton_t
;
206 typedef struct automata_list_el
*automata_list_el_t
;
207 typedef struct state_ainsn_table
*state_ainsn_table_t
;
210 /* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
211 gen_bypass, gen_excl_set, gen_presence_set, gen_final_presence_set,
212 gen_absence_set, gen_final_absence_set, gen_automaton,
213 gen_automata_option, gen_reserv, gen_insn_reserv,
214 initiate_automaton_gen, expand_automata, write_automata are
215 described on the file top because the functions are called from
218 static void *create_node
PARAMS ((size_t));
219 static void *copy_node
PARAMS ((const void *, size_t));
220 static char *check_name
PARAMS ((char *, pos_t
));
221 static char *next_sep_el
PARAMS ((char **, int, int));
222 static int n_sep_els
PARAMS ((char *, int, int));
223 static char **get_str_vect
PARAMS ((char *, int *, int, int));
224 static void gen_presence_absence_set
PARAMS ((rtx
, int, int));
225 static regexp_t gen_regexp_el
PARAMS ((char *));
226 static regexp_t gen_regexp_repeat
PARAMS ((char *));
227 static regexp_t gen_regexp_allof
PARAMS ((char *));
228 static regexp_t gen_regexp_oneof
PARAMS ((char *));
229 static regexp_t gen_regexp_sequence
PARAMS ((char *));
230 static regexp_t gen_regexp
PARAMS ((char *));
232 static unsigned string_hash
PARAMS ((const char *));
233 static unsigned automaton_decl_hash
PARAMS ((const void *));
234 static int automaton_decl_eq_p
PARAMS ((const void *,
236 static decl_t insert_automaton_decl
PARAMS ((decl_t
));
237 static decl_t find_automaton_decl
PARAMS ((char *));
238 static void initiate_automaton_decl_table
PARAMS ((void));
239 static void finish_automaton_decl_table
PARAMS ((void));
241 static hashval_t insn_decl_hash
PARAMS ((const void *));
242 static int insn_decl_eq_p
PARAMS ((const void *,
244 static decl_t insert_insn_decl
PARAMS ((decl_t
));
245 static decl_t find_insn_decl
PARAMS ((char *));
246 static void initiate_insn_decl_table
PARAMS ((void));
247 static void finish_insn_decl_table
PARAMS ((void));
249 static hashval_t decl_hash
PARAMS ((const void *));
250 static int decl_eq_p
PARAMS ((const void *,
252 static decl_t insert_decl
PARAMS ((decl_t
));
253 static decl_t find_decl
PARAMS ((char *));
254 static void initiate_decl_table
PARAMS ((void));
255 static void finish_decl_table
PARAMS ((void));
257 static unit_set_el_t process_excls
PARAMS ((char **, int, pos_t
));
258 static void add_excls
PARAMS ((unit_set_el_t
, unit_set_el_t
,
260 static unit_set_el_t process_presence_absence_names
261 PARAMS ((char **, int, pos_t
,
263 static pattern_set_el_t process_presence_absence_patterns
264 PARAMS ((char ***, int, pos_t
,
266 static void add_presence_absence
PARAMS ((unit_set_el_t
,
269 static void process_decls
PARAMS ((void));
270 static struct bypass_decl
*find_bypass
PARAMS ((struct bypass_decl
*,
271 struct insn_reserv_decl
*));
272 static void check_automaton_usage
PARAMS ((void));
273 static regexp_t process_regexp
PARAMS ((regexp_t
));
274 static void process_regexp_decls
PARAMS ((void));
275 static void check_usage
PARAMS ((void));
276 static int loop_in_regexp
PARAMS ((regexp_t
, decl_t
));
277 static void check_loops_in_regexps
PARAMS ((void));
278 static void process_regexp_cycles
PARAMS ((regexp_t
, int, int,
280 static void evaluate_max_reserv_cycles
PARAMS ((void));
281 static void check_all_description
PARAMS ((void));
283 static ticker_t create_ticker
PARAMS ((void));
284 static void ticker_off
PARAMS ((ticker_t
*));
285 static void ticker_on
PARAMS ((ticker_t
*));
286 static int active_time
PARAMS ((ticker_t
));
287 static void print_active_time
PARAMS ((FILE *, ticker_t
));
289 static void add_advance_cycle_insn_decl
PARAMS ((void));
291 static alt_state_t get_free_alt_state
PARAMS ((void));
292 static void free_alt_state
PARAMS ((alt_state_t
));
293 static void free_alt_states
PARAMS ((alt_state_t
));
294 static int alt_state_cmp
PARAMS ((const void *alt_state_ptr_1
,
295 const void *alt_state_ptr_2
));
296 static alt_state_t uniq_sort_alt_states
PARAMS ((alt_state_t
));
297 static int alt_states_eq
PARAMS ((alt_state_t
, alt_state_t
));
298 static void initiate_alt_states
PARAMS ((void));
299 static void finish_alt_states
PARAMS ((void));
301 static reserv_sets_t alloc_empty_reserv_sets
PARAMS ((void));
302 static unsigned reserv_sets_hash_value
PARAMS ((reserv_sets_t
));
303 static int reserv_sets_cmp
PARAMS ((reserv_sets_t
, reserv_sets_t
));
304 static int reserv_sets_eq
PARAMS ((reserv_sets_t
, reserv_sets_t
));
305 static void set_unit_reserv
PARAMS ((reserv_sets_t
, int, int));
306 static int test_unit_reserv
PARAMS ((reserv_sets_t
, int, int));
307 static int it_is_empty_reserv_sets
PARAMS ((reserv_sets_t
))
309 static int reserv_sets_are_intersected
PARAMS ((reserv_sets_t
, reserv_sets_t
));
310 static void reserv_sets_shift
PARAMS ((reserv_sets_t
, reserv_sets_t
));
311 static void reserv_sets_or
PARAMS ((reserv_sets_t
, reserv_sets_t
,
313 static void reserv_sets_and
PARAMS ((reserv_sets_t
, reserv_sets_t
,
316 static void output_cycle_reservs
PARAMS ((FILE *, reserv_sets_t
,
318 static void output_reserv_sets
PARAMS ((FILE *, reserv_sets_t
));
319 static state_t get_free_state
PARAMS ((int, automaton_t
));
320 static void free_state
PARAMS ((state_t
));
321 static hashval_t state_hash
PARAMS ((const void *));
322 static int state_eq_p
PARAMS ((const void *, const void *));
323 static state_t insert_state
PARAMS ((state_t
));
324 static void set_state_reserv
PARAMS ((state_t
, int, int));
325 static int intersected_state_reservs_p
PARAMS ((state_t
, state_t
));
326 static state_t states_union
PARAMS ((state_t
, state_t
, reserv_sets_t
));
327 static state_t state_shift
PARAMS ((state_t
, reserv_sets_t
));
328 static void initiate_states
PARAMS ((void));
329 static void finish_states
PARAMS ((void));
331 static void free_arc
PARAMS ((arc_t
));
332 static void remove_arc
PARAMS ((state_t
, arc_t
));
333 static arc_t find_arc
PARAMS ((state_t
, state_t
, ainsn_t
));
334 static arc_t add_arc
PARAMS ((state_t
, state_t
, ainsn_t
, int));
335 static arc_t first_out_arc
PARAMS ((state_t
));
336 static arc_t next_out_arc
PARAMS ((arc_t
));
337 static void initiate_arcs
PARAMS ((void));
338 static void finish_arcs
PARAMS ((void));
340 static automata_list_el_t get_free_automata_list_el
PARAMS ((void));
341 static void free_automata_list_el
PARAMS ((automata_list_el_t
));
342 static void free_automata_list
PARAMS ((automata_list_el_t
));
343 static hashval_t automata_list_hash
PARAMS ((const void *));
344 static int automata_list_eq_p
PARAMS ((const void *, const void *));
345 static void initiate_automata_lists
PARAMS ((void));
346 static void automata_list_start
PARAMS ((void));
347 static void automata_list_add
PARAMS ((automaton_t
));
348 static automata_list_el_t automata_list_finish
PARAMS ((void));
349 static void finish_automata_lists
PARAMS ((void));
351 static void initiate_excl_sets
PARAMS ((void));
352 static reserv_sets_t get_excl_set
PARAMS ((reserv_sets_t
));
354 static pattern_reserv_t form_reserv_sets_list
PARAMS ((pattern_set_el_t
));
355 static void initiate_presence_absence_pattern_sets
PARAMS ((void));
356 static int check_presence_pattern_sets
PARAMS ((reserv_sets_t
,
357 reserv_sets_t
, int));
358 static int check_absence_pattern_sets
PARAMS ((reserv_sets_t
, reserv_sets_t
,
361 static regexp_t copy_insn_regexp
PARAMS ((regexp_t
));
362 static regexp_t transform_1
PARAMS ((regexp_t
));
363 static regexp_t transform_2
PARAMS ((regexp_t
));
364 static regexp_t transform_3
PARAMS ((regexp_t
));
365 static regexp_t regexp_transform_func
366 PARAMS ((regexp_t
, regexp_t (*) (regexp_t
)));
367 static regexp_t transform_regexp
PARAMS ((regexp_t
));
368 static void transform_insn_regexps
PARAMS ((void));
370 static void check_unit_distribution_in_reserv
PARAMS ((const char *, regexp_t
,
372 static void check_regexp_units_distribution
PARAMS ((const char *, regexp_t
));
373 static void check_unit_distributions_to_automata
PARAMS ((void));
375 static int process_seq_for_forming_states
PARAMS ((regexp_t
, automaton_t
,
377 static void finish_forming_alt_state
PARAMS ((alt_state_t
,
379 static void process_alts_for_forming_states
PARAMS ((regexp_t
,
381 static void create_alt_states
PARAMS ((automaton_t
));
383 static void form_ainsn_with_same_reservs
PARAMS ((automaton_t
));
385 static reserv_sets_t form_reservs_matter
PARAMS ((automaton_t
));
386 static void make_automaton
PARAMS ((automaton_t
));
387 static void form_arcs_marked_by_insn
PARAMS ((state_t
));
388 static int create_composed_state
PARAMS ((state_t
, arc_t
, vla_ptr_t
*));
389 static void NDFA_to_DFA
PARAMS ((automaton_t
));
390 static void pass_state_graph
PARAMS ((state_t
, void (*) (state_t
)));
391 static void pass_states
PARAMS ((automaton_t
,
392 void (*) (state_t
)));
393 static void initiate_pass_states
PARAMS ((void));
394 static void add_achieved_state
PARAMS ((state_t
));
395 static int set_out_arc_insns_equiv_num
PARAMS ((state_t
, int));
396 static void clear_arc_insns_equiv_num
PARAMS ((state_t
));
397 static void copy_equiv_class
PARAMS ((vla_ptr_t
*to
,
398 const vla_ptr_t
*from
));
399 static int first_cycle_unit_presence
PARAMS ((state_t
, int));
400 static int state_is_differed
PARAMS ((state_t
, state_t
, int, int));
401 static state_t init_equiv_class
PARAMS ((state_t
*states
, int));
402 static int partition_equiv_class
PARAMS ((state_t
*, int,
403 vla_ptr_t
*, int *));
404 static void evaluate_equiv_classes
PARAMS ((automaton_t
, vla_ptr_t
*));
405 static void merge_states
PARAMS ((automaton_t
, vla_ptr_t
*));
406 static void set_new_cycle_flags
PARAMS ((state_t
));
407 static void minimize_DFA
PARAMS ((automaton_t
));
408 static void incr_states_and_arcs_nums
PARAMS ((state_t
));
409 static void count_states_and_arcs
PARAMS ((automaton_t
, int *, int *));
410 static void build_automaton
PARAMS ((automaton_t
));
412 static void set_order_state_num
PARAMS ((state_t
));
413 static void enumerate_states
PARAMS ((automaton_t
));
415 static ainsn_t insert_ainsn_into_equiv_class
PARAMS ((ainsn_t
, ainsn_t
));
416 static void delete_ainsn_from_equiv_class
PARAMS ((ainsn_t
));
417 static void process_insn_equiv_class
PARAMS ((ainsn_t
, arc_t
*));
418 static void process_state_for_insn_equiv_partition
PARAMS ((state_t
));
419 static void set_insn_equiv_classes
PARAMS ((automaton_t
));
421 static double estimate_one_automaton_bound
PARAMS ((void));
422 static int compare_max_occ_cycle_nums
PARAMS ((const void *,
424 static void units_to_automata_heuristic_distr
PARAMS ((void));
425 static ainsn_t create_ainsns
PARAMS ((void));
426 static void units_to_automata_distr
PARAMS ((void));
427 static void create_automata
PARAMS ((void));
429 static void form_regexp
PARAMS ((regexp_t
));
430 static const char *regexp_representation
PARAMS ((regexp_t
));
431 static void finish_regexp_representation
PARAMS ((void));
433 static void output_range_type
PARAMS ((FILE *, long int, long int));
434 static int longest_path_length
PARAMS ((state_t
));
435 static void process_state_longest_path_length
PARAMS ((state_t
));
436 static void output_dfa_max_issue_rate
PARAMS ((void));
437 static void output_vect
PARAMS ((vect_el_t
*, int));
438 static void output_chip_member_name
PARAMS ((FILE *, automaton_t
));
439 static void output_temp_chip_member_name
PARAMS ((FILE *, automaton_t
));
440 static void output_translate_vect_name
PARAMS ((FILE *, automaton_t
));
441 static void output_trans_full_vect_name
PARAMS ((FILE *, automaton_t
));
442 static void output_trans_comb_vect_name
PARAMS ((FILE *, automaton_t
));
443 static void output_trans_check_vect_name
PARAMS ((FILE *, automaton_t
));
444 static void output_trans_base_vect_name
PARAMS ((FILE *, automaton_t
));
445 static void output_state_alts_full_vect_name
PARAMS ((FILE *, automaton_t
));
446 static void output_state_alts_comb_vect_name
PARAMS ((FILE *, automaton_t
));
447 static void output_state_alts_check_vect_name
PARAMS ((FILE *, automaton_t
));
448 static void output_state_alts_base_vect_name
PARAMS ((FILE *, automaton_t
));
449 static void output_min_issue_delay_vect_name
PARAMS ((FILE *, automaton_t
));
450 static void output_dead_lock_vect_name
PARAMS ((FILE *, automaton_t
));
451 static void output_reserved_units_table_name
PARAMS ((FILE *, automaton_t
));
452 static void output_state_member_type
PARAMS ((FILE *, automaton_t
));
453 static void output_chip_definitions
PARAMS ((void));
454 static void output_translate_vect
PARAMS ((automaton_t
));
455 static int comb_vect_p
PARAMS ((state_ainsn_table_t
));
456 static state_ainsn_table_t create_state_ainsn_table
PARAMS ((automaton_t
));
457 static void output_state_ainsn_table
458 PARAMS ((state_ainsn_table_t
, char *, void (*) (FILE *, automaton_t
),
459 void (*) (FILE *, automaton_t
), void (*) (FILE *, automaton_t
),
460 void (*) (FILE *, automaton_t
)));
461 static void add_vect
PARAMS ((state_ainsn_table_t
,
462 int, vect_el_t
*, int));
463 static int out_state_arcs_num
PARAMS ((state_t
));
464 static int compare_transition_els_num
PARAMS ((const void *, const void *));
465 static void add_vect_el
PARAMS ((vla_hwint_t
*,
467 static void add_states_vect_el
PARAMS ((state_t
));
468 static void output_trans_table
PARAMS ((automaton_t
));
469 static void output_state_alts_table
PARAMS ((automaton_t
));
470 static int min_issue_delay_pass_states
PARAMS ((state_t
, ainsn_t
));
471 static int min_issue_delay
PARAMS ((state_t
, ainsn_t
));
472 static void initiate_min_issue_delay_pass_states
PARAMS ((void));
473 static void output_min_issue_delay_table
PARAMS ((automaton_t
));
474 static void output_dead_lock_vect
PARAMS ((automaton_t
));
475 static void output_reserved_units_table
PARAMS ((automaton_t
));
476 static void output_tables
PARAMS ((void));
477 static void output_max_insn_queue_index_def
PARAMS ((void));
478 static void output_insn_code_cases
PARAMS ((void (*) (automata_list_el_t
)));
479 static void output_automata_list_min_issue_delay_code
PARAMS ((automata_list_el_t
));
480 static void output_internal_min_issue_delay_func
PARAMS ((void));
481 static void output_automata_list_transition_code
PARAMS ((automata_list_el_t
));
482 static void output_internal_trans_func
PARAMS ((void));
483 static void output_internal_insn_code_evaluation
PARAMS ((const char *,
485 static void output_dfa_insn_code_func
PARAMS ((void));
486 static void output_trans_func
PARAMS ((void));
487 static void output_automata_list_state_alts_code
PARAMS ((automata_list_el_t
));
488 static void output_internal_state_alts_func
PARAMS ((void));
489 static void output_state_alts_func
PARAMS ((void));
490 static void output_min_issue_delay_func
PARAMS ((void));
491 static void output_internal_dead_lock_func
PARAMS ((void));
492 static void output_dead_lock_func
PARAMS ((void));
493 static void output_internal_reset_func
PARAMS ((void));
494 static void output_size_func
PARAMS ((void));
495 static void output_reset_func
PARAMS ((void));
496 static void output_min_insn_conflict_delay_func
PARAMS ((void));
497 static void output_internal_insn_latency_func
PARAMS ((void));
498 static void output_insn_latency_func
PARAMS ((void));
499 static void output_print_reservation_func
PARAMS ((void));
500 static int units_cmp
PARAMS ((const void *,
502 static void output_get_cpu_unit_code_func
PARAMS ((void));
503 static void output_cpu_unit_reservation_p
PARAMS ((void));
504 static void output_dfa_clean_insn_cache_func
PARAMS ((void));
505 static void output_dfa_start_func
PARAMS ((void));
506 static void output_dfa_finish_func
PARAMS ((void));
508 static void output_regexp
PARAMS ((regexp_t
));
509 static void output_unit_set_el_list
PARAMS ((unit_set_el_t
));
510 static void output_pattern_set_el_list
PARAMS ((pattern_set_el_t
));
511 static void output_description
PARAMS ((void));
512 static void output_automaton_name
PARAMS ((FILE *, automaton_t
));
513 static void output_automaton_units
PARAMS ((automaton_t
));
514 static void add_state_reservs
PARAMS ((state_t
));
515 static void output_state_arcs
PARAMS ((state_t
));
516 static int state_reservs_cmp
PARAMS ((const void *,
518 static void remove_state_duplicate_reservs
PARAMS ((void));
519 static void output_state
PARAMS ((state_t
));
520 static void output_automaton_descriptions
PARAMS ((void));
521 static void output_statistics
PARAMS ((FILE *));
522 static void output_time_statistics
PARAMS ((FILE *));
523 static void generate
PARAMS ((void));
525 static void make_insn_alts_attr
PARAMS ((void));
526 static void make_internal_dfa_insn_code_attr
PARAMS ((void));
527 static void make_default_insn_latency_attr
PARAMS ((void));
528 static void make_bypass_attr
PARAMS ((void));
529 static const char *file_name_suffix
PARAMS ((const char *));
530 static const char *base_file_name
PARAMS ((const char *));
531 static void check_automata_insn_issues
PARAMS ((void));
532 static void add_automaton_state
PARAMS ((state_t
));
533 static void form_important_insn_automata_lists
PARAMS ((void));
535 /* Undefined position. */
536 static pos_t no_pos
= 0;
538 /* All IR is stored in the following obstack. */
539 static struct obstack irp
;
543 /* This page contains code for work with variable length array (vla)
544 of pointers. We could be use only varray. But we add new lay
545 because we add elements very frequently and this could stress OS
546 allocator when varray is used only. */
548 /* Start work with vla. */
549 #define VLA_PTR_CREATE(vla, allocated_length, name) \
552 vla_ptr_t *const vla_ptr = &(vla); \
554 VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\
555 vla_ptr->length = 0; \
559 /* Finish work with the vla. */
560 #define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
562 /* Return start address of the vla. */
563 #define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
565 /* Address of the last element of the vla. Do not use side effects in
566 the macro argument. */
567 #define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \
569 /* Nullify the vla. */
570 #define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
572 /* Shorten the vla on given number bytes. */
573 #define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
575 /* Expand the vla on N elements. The values of new elements are
577 #define VLA_PTR_EXPAND(vla, n) \
579 vla_ptr_t *const expand_vla_ptr = &(vla); \
580 const size_t new_length = (n) + expand_vla_ptr->length; \
582 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
583 VARRAY_GROW (expand_vla_ptr->varray, \
584 (new_length - expand_vla_ptr->length < 128 \
585 ? expand_vla_ptr->length + 128 : new_length)); \
586 expand_vla_ptr->length = new_length; \
589 /* Add element to the end of the vla. */
590 #define VLA_PTR_ADD(vla, ptr) \
592 vla_ptr_t *const vla_ptr = &(vla); \
594 VLA_PTR_EXPAND (*vla_ptr, 1); \
595 VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\
598 /* Length of the vla in elements. */
599 #define VLA_PTR_LENGTH(vla) ((vla).length)
601 /* N-th element of the vla. */
602 #define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
605 /* The following macros are analogous to the previous ones but for
606 VLAs of HOST WIDE INTs. */
608 #define VLA_HWINT_CREATE(vla, allocated_length, name) \
610 vla_hwint_t *const vla_ptr = &(vla); \
612 VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name); \
613 vla_ptr->length = 0; \
616 #define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
618 #define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
620 #define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
622 #define VLA_HWINT_EXPAND(vla, n) \
624 vla_hwint_t *const expand_vla_ptr = &(vla); \
625 const size_t new_length = (n) + expand_vla_ptr->length; \
627 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
628 VARRAY_GROW (expand_vla_ptr->varray, \
629 (new_length - expand_vla_ptr->length < 128 \
630 ? expand_vla_ptr->length + 128 : new_length)); \
631 expand_vla_ptr->length = new_length; \
634 #define VLA_HWINT_ADD(vla, ptr) \
636 vla_hwint_t *const vla_ptr = &(vla); \
638 VLA_HWINT_EXPAND (*vla_ptr, 1); \
639 VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr); \
642 #define VLA_HWINT_LENGTH(vla) ((vla).length)
644 #define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
648 /* Options with the following names can be set up in automata_option
649 construction. Because the strings occur more one time we use the
652 #define NO_MINIMIZATION_OPTION "-no-minimization"
654 #define TIME_OPTION "-time"
656 #define V_OPTION "-v"
658 #define W_OPTION "-w"
660 #define NDFA_OPTION "-ndfa"
662 /* The following flags are set up by function `initiate_automaton_gen'. */
664 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
665 static int ndfa_flag
;
667 /* Do not make minimization of DFA (`-no-minimization'). */
668 static int no_minimization_flag
;
670 /* Value of this variable is number of automata being generated. The
671 actual number of automata may be less this value if there is not
672 sufficient number of units. This value is defined by argument of
673 option `-split' or by constructions automaton if the value is zero
674 (it is default value of the argument). */
675 static int split_argument
;
677 /* Flag of output time statistics (`-time'). */
678 static int time_flag
;
680 /* Flag of creation of description file which contains description of
681 result automaton and statistics information (`-v'). */
684 /* Flag of generating warning instead of error for non-critical errors
689 /* Output file for pipeline hazard recognizer (PHR) being generated.
690 The value is NULL if the file is not defined. */
691 static FILE *output_file
;
693 /* Description file of PHR. The value is NULL if the file is not
695 static FILE *output_description_file
;
697 /* PHR description file name. */
698 static char *output_description_file_name
;
700 /* Value of the following variable is node representing description
701 being processed. This is start point of IR. */
702 static struct description
*description
;
706 /* This page contains description of IR structure (nodes). */
720 /* This describes define_cpu_unit and define_query_cpu_unit (see file
725 /* NULL if the automaton name is absent. */
726 char *automaton_name
;
727 /* If the following value is not zero, the cpu unit reservation is
728 described in define_query_cpu_unit. */
731 /* The following fields are defined by checker. */
733 /* The following field value is nonzero if the unit is used in an
737 /* The following field value is order number (0, 1, ...) of given
740 /* The following field value is corresponding declaration of
741 automaton which was given in description. If the field value is
742 NULL then automaton in the unit declaration was absent. */
743 struct automaton_decl
*automaton_decl
;
744 /* The following field value is maximal cycle number (1, ...) on
745 which given unit occurs in insns. Zero value means that given
746 unit is not used in insns. */
747 int max_occ_cycle_num
;
748 /* The following field value is minimal cycle number (0, ...) on
749 which given unit occurs in insns. -1 value means that given
750 unit is not used in insns. */
751 int min_occ_cycle_num
;
752 /* The following list contains units which conflict with given
754 unit_set_el_t excl_list
;
755 /* The following list contains patterns which are required to
756 reservation of given unit. */
757 pattern_set_el_t presence_list
;
758 pattern_set_el_t final_presence_list
;
759 /* The following list contains patterns which should be not present
760 in reservation for given unit. */
761 pattern_set_el_t absence_list
;
762 pattern_set_el_t final_absence_list
;
763 /* The following is used only when `query_p' has nonzero value.
764 This is query number for the unit. */
767 /* The following fields are defined by automaton generator. */
769 /* The following field value is number of the automaton to which
770 given unit belongs. */
771 int corresponding_automaton_num
;
772 /* If the following value is not zero, the cpu unit is present in a
773 `exclusion_set' or in right part of a `presence_set',
774 `final_presence_set', `absence_set', and
775 `final_absence_set'define_query_cpu_unit. */
779 /* This describes define_bypass (see file rtl.def). */
785 char *bypass_guard_name
;
787 /* The following fields are defined by checker. */
789 /* output and input insns of given bypass. */
790 struct insn_reserv_decl
*out_insn_reserv
;
791 struct insn_reserv_decl
*in_insn_reserv
;
792 /* The next bypass for given output insn. */
793 struct bypass_decl
*next
;
796 /* This describes define_automaton (see file rtl.def). */
797 struct automaton_decl
801 /* The following fields are defined by automaton generator. */
803 /* The following field value is nonzero if the automaton is used in
804 an regexp definition. */
805 char automaton_is_used
;
807 /* The following fields are defined by checker. */
809 /* The following field value is the corresponding automaton. This
810 field is not NULL only if the automaton is present in unit
811 declarations and the automatic partition on automata is not
813 automaton_t corresponding_automaton
;
816 /* This describes exclusion relations: exclusion_set (see file
821 int first_list_length
;
825 /* This describes unit relations: [final_]presence_set or
826 [final_]absence_set (see file rtl.def). */
827 struct unit_pattern_rel_decl
836 /* This describes define_reservation (see file rtl.def). */
842 /* The following fields are defined by checker. */
844 /* The following field value is nonzero if the unit is used in an
847 /* The following field is used to check up cycle in expression
852 /* This describes define_insn_reservation (see file rtl.def). */
853 struct insn_reserv_decl
860 /* The following fields are defined by checker. */
862 /* The following field value is order number (0, 1, ...) of given
865 /* The following field value is list of bypasses in which given insn
867 struct bypass_decl
*bypass_list
;
869 /* The following fields are defined by automaton generator. */
871 /* The following field is the insn regexp transformed that
872 the regexp has not optional regexp, repetition regexp, and an
873 reservation name (i.e. reservation identifiers are changed by the
874 corresponding regexp) and all alternations are the topest level
875 of the regexp. The value can be NULL only if it is special
876 insn `cycle advancing'. */
877 regexp_t transformed_regexp
;
878 /* The following field value is list of arcs marked given
879 insn. The field is used in transformation NDFA -> DFA. */
880 arc_t arcs_marked_by_insn
;
881 /* The two following fields are used during minimization of a finite state
883 /* The field value is number of equivalence class of state into
884 which arc marked by given insn enters from a state (fixed during
885 an automaton minimization). */
887 /* The field value is state_alts of arc leaving a state (fixed
888 during an automaton minimization) and marked by given insn
891 /* The following member value is the list to automata which can be
892 changed by the insn issue. */
893 automata_list_el_t important_automata_list
;
894 /* The following member is used to process insn once for output. */
898 /* This contains a declaration mentioned above. */
901 /* What node in the union? */
906 struct unit_decl unit
;
907 struct bypass_decl bypass
;
908 struct automaton_decl automaton
;
909 struct excl_rel_decl excl
;
910 struct unit_pattern_rel_decl presence
;
911 struct unit_pattern_rel_decl absence
;
912 struct reserv_decl reserv
;
913 struct insn_reserv_decl insn_reserv
;
917 /* The following structures represent parsed reservation strings. */
929 /* Cpu unit in reservation. */
933 unit_decl_t unit_decl
;
936 /* Define_reservation in a reservation. */
940 struct reserv_decl
*reserv_decl
;
943 /* Absence of reservation (represented by string `nothing'). */
944 struct nothing_regexp
946 /* This used to be empty but ISO C doesn't allow that. */
950 /* Representation of reservations separated by ',' (see file
952 struct sequence_regexp
955 regexp_t regexps
[1];
958 /* Representation of construction `repeat' (see file rtl.def). */
965 /* Representation of reservations separated by '+' (see file
970 regexp_t regexps
[1];
973 /* Representation of reservations separated by '|' (see file
978 regexp_t regexps
[1];
981 /* Representation of a reservation string. */
984 /* What node in the union? */
985 enum regexp_mode mode
;
989 struct unit_regexp unit
;
990 struct reserv_regexp reserv
;
991 struct nothing_regexp nothing
;
992 struct sequence_regexp sequence
;
993 struct repeat_regexp repeat
;
994 struct allof_regexp allof
;
995 struct oneof_regexp oneof
;
999 /* Represents description of pipeline hazard description based on
1005 /* The following fields are defined by checker. */
1007 /* The following fields values are correspondingly number of all
1008 units, query units, and insns in the description. */
1010 int query_units_num
;
1012 /* The following field value is max length (in cycles) of
1013 reservations of insns. The field value is defined only for
1014 correct programs. */
1015 int max_insn_reserv_cycles
;
1017 /* The following fields are defined by automaton generator. */
1019 /* The following field value is the first automaton. */
1020 automaton_t first_automaton
;
1022 /* The following field is created by pipeline hazard parser and
1023 contains all declarations. We allocate additional entry for
1024 special insn "cycle advancing" which is added by the automaton
1030 /* The following nodes are created in automaton checker. */
1032 /* The following nodes represent exclusion set for cpu units. Each
1033 element is accessed through only one excl_list. */
1036 unit_decl_t unit_decl
;
1037 unit_set_el_t next_unit_set_el
;
1040 /* The following nodes represent presence or absence pattern for cpu
1041 units. Each element is accessed through only one presence_list or
1043 struct pattern_set_el
1045 /* The number of units in unit_decls. */
1047 /* The units forming the pattern. */
1048 struct unit_decl
**unit_decls
;
1049 pattern_set_el_t next_pattern_set_el
;
1053 /* The following nodes are created in automaton generator. */
1056 /* The following nodes represent presence or absence pattern for cpu
1057 units. Each element is accessed through only one element of
1058 unit_presence_set_table or unit_absence_set_table. */
1059 struct pattern_reserv
1061 reserv_sets_t reserv
;
1062 pattern_reserv_t next_pattern_reserv
;
1065 /* The following node type describes state automaton. The state may
1066 be deterministic or non-deterministic. Non-deterministic state has
1067 several component states which represent alternative cpu units
1068 reservations. The state also is used for describing a
1069 deterministic reservation of automaton insn. */
1072 /* The following member value is nonzero if there is a transition by
1075 /* The following field is list of processor unit reservations on
1077 reserv_sets_t reservs
;
1078 /* The following field is unique number of given state between other
1081 /* The following field value is automaton to which given state
1083 automaton_t automaton
;
1084 /* The following field value is the first arc output from given
1086 arc_t first_out_arc
;
1087 /* The following field is used to form NDFA. */
1088 char it_was_placed_in_stack_for_NDFA_forming
;
1089 /* The following field is used to form DFA. */
1090 char it_was_placed_in_stack_for_DFA_forming
;
1091 /* The following field is used to transform NDFA to DFA and DFA
1092 minimization. The field value is not NULL if the state is a
1093 compound state. In this case the value of field `unit_sets_list'
1094 is NULL. All states in the list are in the hash table. The list
1095 is formed through field `next_sorted_alt_state'. We should
1096 support only one level of nesting state. */
1097 alt_state_t component_states
;
1098 /* The following field is used for passing graph of states. */
1100 /* The list of states belonging to one equivalence class is formed
1101 with the aid of the following field. */
1102 state_t next_equiv_class_state
;
1103 /* The two following fields are used during minimization of a finite
1105 int equiv_class_num_1
, equiv_class_num_2
;
1106 /* The following field is used during minimization of a finite state
1107 automaton. The field value is state corresponding to equivalence
1108 class to which given state belongs. */
1109 state_t equiv_class_state
;
1110 /* The following field value is the order number of given state.
1111 The states in final DFA is enumerated with the aid of the
1113 int order_state_num
;
1114 /* This member is used for passing states for searching minimal
1117 /* The following member is used to evaluate min issue delay of insn
1119 int min_insn_issue_delay
;
1120 /* The following member is used to evaluate max issue rate of the
1121 processor. The value of the member is maximal length of the path
1122 from given state no containing arcs marked by special insn `cycle
1124 int longest_path_length
;
1127 /* The following macro is an initial value of member
1128 `longest_path_length' of a state. */
1129 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1131 /* Automaton arc. */
1134 /* The following field refers for the state into which given arc
1137 /* The following field describes that the insn issue (with cycle
1138 advancing for special insn `cycle advancing' and without cycle
1139 advancing for others) makes transition from given state to
1140 another given state. */
1142 /* The following field value is the next arc output from the same
1145 /* List of arcs marked given insn is formed with the following
1146 field. The field is used in transformation NDFA -> DFA. */
1147 arc_t next_arc_marked_by_insn
;
1148 /* The following field is defined if NDFA_FLAG is zero. The member
1149 value is number of alternative reservations which can be used for
1150 transition for given state by given insn. */
1154 /* The following node type describes a deterministic alternative in
1155 non-deterministic state which characterizes cpu unit reservations
1156 of automaton insn or which is part of NDFA. */
1159 /* The following field is a determinist state which characterizes
1160 unit reservations of the instruction. */
1162 /* The following field refers to the next state which characterizes
1163 unit reservations of the instruction. */
1164 alt_state_t next_alt_state
;
1165 /* The following field refers to the next state in sorted list. */
1166 alt_state_t next_sorted_alt_state
;
1169 /* The following node type describes insn of automaton. They are
1170 labels of FA arcs. */
1173 /* The following field value is the corresponding insn declaration
1175 struct insn_reserv_decl
*insn_reserv_decl
;
1176 /* The following field value is the next insn declaration for an
1179 /* The following field is states which characterize automaton unit
1180 reservations of the instruction. The value can be NULL only if it
1181 is special insn `cycle advancing'. */
1182 alt_state_t alt_states
;
1183 /* The following field is sorted list of states which characterize
1184 automaton unit reservations of the instruction. The value can be
1185 NULL only if it is special insn `cycle advancing'. */
1186 alt_state_t sorted_alt_states
;
1187 /* The following field refers the next automaton insn with
1188 the same reservations. */
1189 ainsn_t next_same_reservs_insn
;
1190 /* The following field is flag of the first automaton insn with the
1191 same reservations in the declaration list. Only arcs marked such
1192 insn is present in the automaton. This significantly decreases
1193 memory requirements especially when several automata are
1195 char first_insn_with_same_reservs
;
1196 /* The following member has nonzero value if there is arc from state of
1197 the automaton marked by the ainsn. */
1199 /* Cyclic list of insns of an equivalence class is formed with the
1200 aid of the following field. */
1201 ainsn_t next_equiv_class_insn
;
1202 /* The following field value is nonzero if the insn declaration is
1203 the first insn declaration with given equivalence number. */
1204 char first_ainsn_with_given_equialence_num
;
1205 /* The following field is number of class of equivalence of insns.
1206 It is necessary because many insns may be equivalent with the
1207 point of view of pipeline hazards. */
1208 int insn_equiv_class_num
;
1209 /* The following member value is TRUE if there is an arc in the
1210 automaton marked by the insn into another state. In other
1211 words, the insn can change the state of the automaton. */
1215 /* The folowing describes an automaton for PHR. */
1218 /* The following field value is the list of insn declarations for
1221 /* The following field value is the corresponding automaton
1222 declaration. This field is not NULL only if the automatic
1223 partition on automata is not used. */
1224 struct automaton_decl
*corresponding_automaton_decl
;
1225 /* The following field value is the next automaton. */
1226 automaton_t next_automaton
;
1227 /* The following field is start state of FA. There are not unit
1228 reservations in the state. */
1229 state_t start_state
;
1230 /* The following field value is number of equivalence classes of
1231 insns (see field `insn_equiv_class_num' in
1232 `insn_reserv_decl'). */
1233 int insn_equiv_classes_num
;
1234 /* The following field value is number of states of final DFA. */
1235 int achieved_states_num
;
1236 /* The following field value is the order number (0, 1, ...) of
1238 int automaton_order_num
;
1239 /* The following fields contain statistics information about
1240 building automaton. */
1241 int NDFA_states_num
, DFA_states_num
;
1242 /* The following field value is defined only if minimization of DFA
1244 int minimal_DFA_states_num
;
1245 int NDFA_arcs_num
, DFA_arcs_num
;
1246 /* The following field value is defined only if minimization of DFA
1248 int minimal_DFA_arcs_num
;
1249 /* The following two members refer for two table state x ainsn ->
1251 state_ainsn_table_t trans_table
;
1252 state_ainsn_table_t state_alts_table
;
1253 /* The following member value is maximal value of min issue delay
1254 for insns of the automaton. */
1256 /* Usually min issue delay is small and we can place several (2, 4,
1257 8) elements in one vector element. So the compression factor can
1258 be 1 (no compression), 2, 4, 8. */
1259 int min_issue_delay_table_compression_factor
;
1262 /* The following is the element of the list of automata. */
1263 struct automata_list_el
1265 /* The automaton itself. */
1266 automaton_t automaton
;
1267 /* The next automata set element. */
1268 automata_list_el_t next_automata_list_el
;
1271 /* The following structure describes a table state X ainsn -> int(>= 0). */
1272 struct state_ainsn_table
1274 /* Automaton to which given table belongs. */
1275 automaton_t automaton
;
1276 /* The following tree vectors for comb vector implementation of the
1278 vla_hwint_t comb_vect
;
1279 vla_hwint_t check_vect
;
1280 vla_hwint_t base_vect
;
1281 /* This is simple implementation of the table. */
1282 vla_hwint_t full_vect
;
1283 /* Minimal and maximal values of the previous vectors. */
1284 int min_comb_vect_el_value
, max_comb_vect_el_value
;
1285 int min_base_vect_el_value
, max_base_vect_el_value
;
1288 /* Macros to access members of unions. Use only them for access to
1289 union members of declarations and regexps. */
1291 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1293 #define DECL_UNIT(d) __extension__ \
1294 (({ struct decl *const _decl = (d); \
1295 if (_decl->mode != dm_unit) \
1296 decl_mode_check_failed (_decl->mode, "dm_unit", \
1297 __FILE__, __LINE__, __FUNCTION__); \
1298 &(_decl)->decl.unit; }))
1300 #define DECL_BYPASS(d) __extension__ \
1301 (({ struct decl *const _decl = (d); \
1302 if (_decl->mode != dm_bypass) \
1303 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1304 __FILE__, __LINE__, __FUNCTION__); \
1305 &(_decl)->decl.bypass; }))
1307 #define DECL_AUTOMATON(d) __extension__ \
1308 (({ struct decl *const _decl = (d); \
1309 if (_decl->mode != dm_automaton) \
1310 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1311 __FILE__, __LINE__, __FUNCTION__); \
1312 &(_decl)->decl.automaton; }))
1314 #define DECL_EXCL(d) __extension__ \
1315 (({ struct decl *const _decl = (d); \
1316 if (_decl->mode != dm_excl) \
1317 decl_mode_check_failed (_decl->mode, "dm_excl", \
1318 __FILE__, __LINE__, __FUNCTION__); \
1319 &(_decl)->decl.excl; }))
1321 #define DECL_PRESENCE(d) __extension__ \
1322 (({ struct decl *const _decl = (d); \
1323 if (_decl->mode != dm_presence) \
1324 decl_mode_check_failed (_decl->mode, "dm_presence", \
1325 __FILE__, __LINE__, __FUNCTION__); \
1326 &(_decl)->decl.presence; }))
1328 #define DECL_ABSENCE(d) __extension__ \
1329 (({ struct decl *const _decl = (d); \
1330 if (_decl->mode != dm_absence) \
1331 decl_mode_check_failed (_decl->mode, "dm_absence", \
1332 __FILE__, __LINE__, __FUNCTION__); \
1333 &(_decl)->decl.absence; }))
1335 #define DECL_RESERV(d) __extension__ \
1336 (({ struct decl *const _decl = (d); \
1337 if (_decl->mode != dm_reserv) \
1338 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1339 __FILE__, __LINE__, __FUNCTION__); \
1340 &(_decl)->decl.reserv; }))
1342 #define DECL_INSN_RESERV(d) __extension__ \
1343 (({ struct decl *const _decl = (d); \
1344 if (_decl->mode != dm_insn_reserv) \
1345 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1346 __FILE__, __LINE__, __FUNCTION__); \
1347 &(_decl)->decl.insn_reserv; }))
1349 static const char *decl_name
PARAMS ((enum decl_mode
));
1350 static void decl_mode_check_failed
PARAMS ((enum decl_mode
, const char *,
1351 const char *, int, const char *));
1353 /* Return string representation of declaration mode MODE. */
1356 enum decl_mode mode
;
1358 static char str
[100];
1360 if (mode
== dm_unit
)
1362 else if (mode
== dm_bypass
)
1364 else if (mode
== dm_automaton
)
1365 return "dm_automaton";
1366 else if (mode
== dm_excl
)
1368 else if (mode
== dm_presence
)
1369 return "dm_presence";
1370 else if (mode
== dm_absence
)
1371 return "dm_absence";
1372 else if (mode
== dm_reserv
)
1374 else if (mode
== dm_insn_reserv
)
1375 return "dm_insn_reserv";
1377 sprintf (str
, "unknown (%d)", (int) mode
);
1381 /* The function prints message about unexpected declaration and finish
1384 decl_mode_check_failed (mode
, expected_mode_str
, file
, line
, func
)
1385 enum decl_mode mode
;
1386 const char *expected_mode_str
;
1393 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1394 file
, line
, func
, expected_mode_str
, decl_name (mode
));
1399 #define REGEXP_UNIT(r) __extension__ \
1400 (({ struct regexp *const _regexp = (r); \
1401 if (_regexp->mode != rm_unit) \
1402 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1403 __FILE__, __LINE__, __FUNCTION__); \
1404 &(_regexp)->regexp.unit; }))
1406 #define REGEXP_RESERV(r) __extension__ \
1407 (({ struct regexp *const _regexp = (r); \
1408 if (_regexp->mode != rm_reserv) \
1409 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1410 __FILE__, __LINE__, __FUNCTION__); \
1411 &(_regexp)->regexp.reserv; }))
1413 #define REGEXP_SEQUENCE(r) __extension__ \
1414 (({ struct regexp *const _regexp = (r); \
1415 if (_regexp->mode != rm_sequence) \
1416 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1417 __FILE__, __LINE__, __FUNCTION__); \
1418 &(_regexp)->regexp.sequence; }))
1420 #define REGEXP_REPEAT(r) __extension__ \
1421 (({ struct regexp *const _regexp = (r); \
1422 if (_regexp->mode != rm_repeat) \
1423 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1424 __FILE__, __LINE__, __FUNCTION__); \
1425 &(_regexp)->regexp.repeat; }))
1427 #define REGEXP_ALLOF(r) __extension__ \
1428 (({ struct regexp *const _regexp = (r); \
1429 if (_regexp->mode != rm_allof) \
1430 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1431 __FILE__, __LINE__, __FUNCTION__); \
1432 &(_regexp)->regexp.allof; }))
1434 #define REGEXP_ONEOF(r) __extension__ \
1435 (({ struct regexp *const _regexp = (r); \
1436 if (_regexp->mode != rm_oneof) \
1437 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1438 __FILE__, __LINE__, __FUNCTION__); \
1439 &(_regexp)->regexp.oneof; }))
1441 static const char *regexp_name
PARAMS ((enum regexp_mode
));
1442 static void regexp_mode_check_failed
PARAMS ((enum regexp_mode
, const char *,
1447 /* Return string representation of regexp mode MODE. */
1450 enum regexp_mode mode
;
1452 static char str
[100];
1454 if (mode
== rm_unit
)
1456 else if (mode
== rm_reserv
)
1458 else if (mode
== rm_nothing
)
1459 return "rm_nothing";
1460 else if (mode
== rm_sequence
)
1461 return "rm_sequence";
1462 else if (mode
== rm_repeat
)
1464 else if (mode
== rm_allof
)
1466 else if (mode
== rm_oneof
)
1469 sprintf (str
, "unknown (%d)", (int) mode
);
1473 /* The function prints message about unexpected regexp and finish the
1476 regexp_mode_check_failed (mode
, expected_mode_str
, file
, line
, func
)
1477 enum regexp_mode mode
;
1478 const char *expected_mode_str
;
1485 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1486 file
, line
, func
, expected_mode_str
, regexp_name (mode
));
1490 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1492 #define DECL_UNIT(d) (&(d)->decl.unit)
1493 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1494 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1495 #define DECL_EXCL(d) (&(d)->decl.excl)
1496 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1497 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1498 #define DECL_RESERV(d) (&(d)->decl.reserv)
1499 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1501 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1502 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1503 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1504 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1505 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1506 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1508 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1510 /* Create IR structure (node). */
1517 obstack_blank (&irp
, size
);
1518 result
= obstack_base (&irp
);
1519 obstack_finish (&irp
);
1520 /* Default values of members are NULL and zero. */
1521 memset (result
, 0, size
);
1525 /* Copy IR structure (node). */
1527 copy_node (from
, size
)
1531 void *const result
= create_node (size
);
1532 memcpy (result
, from
, size
);
1536 /* The function checks that NAME does not contain quotes (`"'). */
1538 check_name (name
, pos
)
1540 pos_t pos ATTRIBUTE_UNUSED
;
1544 for (str
= name
; *str
!= '\0'; str
++)
1546 error ("Name `%s' contains quotes", name
);
1550 /* Pointers to all declarations during IR generation are stored in the
1552 static vla_ptr_t decls
;
1554 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1555 string containing the next separated element, taking parentheses
1556 into account if PAR_FLAG has nonzero value. Advance the pointer to
1557 after the string scanned, or the end-of-string. Return NULL if at
1560 next_sep_el (pstr
, sep
, par_flag
)
1570 /* Remove leading whitespaces. */
1571 while (ISSPACE ((int) **pstr
))
1578 for (pars_num
= 0, p
= *pstr
; *p
!= '\0'; p
++)
1580 if (par_flag
&& *p
== '(')
1582 else if (par_flag
&& *p
== ')')
1584 else if (pars_num
== 0 && *p
== sep
)
1586 if (pars_num
== 0 && ISSPACE ((int) *p
))
1590 for (; n_spaces
!= 0; n_spaces
--)
1591 obstack_1grow (&irp
, p
[-n_spaces
]);
1592 obstack_1grow (&irp
, *p
);
1595 obstack_1grow (&irp
, '\0');
1596 out_str
= obstack_base (&irp
);
1597 obstack_finish (&irp
);
1606 /* Given a string and a separator, return the number of separated
1607 elements in it, taking parentheses into account if PAR_FLAG has
1608 nonzero value. Return 0 for the null string, -1 if parantheses is
1611 n_sep_els (s
, sep
, par_flag
)
1622 for (pars_num
= 0, n
= 1; *s
; s
++)
1623 if (par_flag
&& *s
== '(')
1625 else if (par_flag
&& *s
== ')')
1627 else if (pars_num
== 0 && *s
== sep
)
1630 return (pars_num
!= 0 ? -1 : n
);
1633 /* Given a string and a separator, return vector of strings which are
1634 elements in the string and number of elements through els_num.
1635 Take parentheses into account if PAREN_P has nonzero value. The
1636 function also inserts the end marker NULL at the end of vector.
1637 Return 0 for the null string, -1 if parantheses are not balanced. */
1639 get_str_vect (str
, els_num
, sep
, paren_p
)
1649 *els_num
= n_sep_els (str
, sep
, paren_p
);
1652 obstack_blank (&irp
, sizeof (char *) * (*els_num
+ 1));
1653 vect
= (char **) obstack_base (&irp
);
1654 obstack_finish (&irp
);
1656 for (i
= 0; i
< *els_num
; i
++)
1657 vect
[i
] = next_sep_el (pstr
, sep
, paren_p
);
1658 if (next_sep_el (pstr
, sep
, paren_p
) != NULL
)
1664 /* Process a DEFINE_CPU_UNIT.
1666 This gives information about a unit contained in CPU. We fill a
1667 struct unit_decl with information used later by `expand_automata'. */
1673 char **str_cpu_units
;
1677 str_cpu_units
= get_str_vect ((char *) XSTR (def
, 0), &vect_length
, ',',
1679 if (str_cpu_units
== NULL
)
1680 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def
, 0));
1681 for (i
= 0; i
< vect_length
; i
++)
1683 decl
= create_node (sizeof (struct decl
));
1684 decl
->mode
= dm_unit
;
1686 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1687 DECL_UNIT (decl
)->automaton_name
= (char *) XSTR (def
, 1);
1688 DECL_UNIT (decl
)->query_p
= 0;
1689 DECL_UNIT (decl
)->min_occ_cycle_num
= -1;
1690 DECL_UNIT (decl
)->in_set_p
= 0;
1691 VLA_PTR_ADD (decls
, decl
);
1696 /* Process a DEFINE_QUERY_CPU_UNIT.
1698 This gives information about a unit contained in CPU. We fill a
1699 struct unit_decl with information used later by `expand_automata'. */
1701 gen_query_cpu_unit (def
)
1705 char **str_cpu_units
;
1709 str_cpu_units
= get_str_vect ((char *) XSTR (def
, 0), &vect_length
, ',',
1711 if (str_cpu_units
== NULL
)
1712 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def
, 0));
1713 for (i
= 0; i
< vect_length
; i
++)
1715 decl
= create_node (sizeof (struct decl
));
1716 decl
->mode
= dm_unit
;
1718 DECL_UNIT (decl
)->name
= check_name (str_cpu_units
[i
], decl
->pos
);
1719 DECL_UNIT (decl
)->automaton_name
= (char *) XSTR (def
, 1);
1720 DECL_UNIT (decl
)->query_p
= 1;
1721 VLA_PTR_ADD (decls
, decl
);
1726 /* Process a DEFINE_BYPASS.
1728 This gives information about a unit contained in the CPU. We fill
1729 in a struct bypass_decl with information used later by
1730 `expand_automata'. */
1742 out_insns
= get_str_vect ((char *) XSTR (def
, 1), &out_length
, ',', FALSE
);
1743 if (out_insns
== NULL
)
1744 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 1));
1745 in_insns
= get_str_vect ((char *) XSTR (def
, 2), &in_length
, ',', FALSE
);
1746 if (in_insns
== NULL
)
1747 fatal ("invalid string `%s' in define_bypass", XSTR (def
, 2));
1748 for (i
= 0; i
< out_length
; i
++)
1749 for (j
= 0; j
< in_length
; j
++)
1751 decl
= create_node (sizeof (struct decl
));
1752 decl
->mode
= dm_bypass
;
1754 DECL_BYPASS (decl
)->latency
= XINT (def
, 0);
1755 DECL_BYPASS (decl
)->out_insn_name
= out_insns
[i
];
1756 DECL_BYPASS (decl
)->in_insn_name
= in_insns
[j
];
1757 DECL_BYPASS (decl
)->bypass_guard_name
= (char *) XSTR (def
, 3);
1758 VLA_PTR_ADD (decls
, decl
);
1763 /* Process an EXCLUSION_SET.
1765 This gives information about a cpu unit conflicts. We fill a
1766 struct excl_rel_decl (excl) with information used later by
1767 `expand_automata'. */
1773 char **first_str_cpu_units
;
1774 char **second_str_cpu_units
;
1775 int first_vect_length
;
1780 = get_str_vect ((char *) XSTR (def
, 0), &first_vect_length
, ',', FALSE
);
1781 if (first_str_cpu_units
== NULL
)
1782 fatal ("invalid first string `%s' in exclusion_set", XSTR (def
, 0));
1783 second_str_cpu_units
= get_str_vect ((char *) XSTR (def
, 1), &length
, ',',
1785 if (second_str_cpu_units
== NULL
)
1786 fatal ("invalid second string `%s' in exclusion_set", XSTR (def
, 1));
1787 length
+= first_vect_length
;
1788 decl
= create_node (sizeof (struct decl
) + (length
- 1) * sizeof (char *));
1789 decl
->mode
= dm_excl
;
1791 DECL_EXCL (decl
)->all_names_num
= length
;
1792 DECL_EXCL (decl
)->first_list_length
= first_vect_length
;
1793 for (i
= 0; i
< length
; i
++)
1794 if (i
< first_vect_length
)
1795 DECL_EXCL (decl
)->names
[i
] = first_str_cpu_units
[i
];
1797 DECL_EXCL (decl
)->names
[i
]
1798 = second_str_cpu_units
[i
- first_vect_length
];
1799 VLA_PTR_ADD (decls
, decl
);
1803 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1804 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1806 This gives information about a cpu unit reservation requirements.
1807 We fill a struct unit_pattern_rel_decl with information used later
1808 by `expand_automata'. */
1810 gen_presence_absence_set (def
, presence_p
, final_p
)
1816 char **str_cpu_units
;
1817 char ***str_patterns
;
1818 int cpu_units_length
;
1820 int patterns_length
;
1823 str_cpu_units
= get_str_vect ((char *) XSTR (def
, 0), &cpu_units_length
, ',',
1825 if (str_cpu_units
== NULL
)
1828 ? "invalid first string `%s' in final_presence_set"
1829 : "invalid first string `%s' in presence_set")
1831 ? "invalid first string `%s' in final_absence_set"
1832 : "invalid first string `%s' in absence_set")),
1834 str_patterns
= (char ***) get_str_vect ((char *) XSTR (def
, 1),
1835 &patterns_length
, ',', FALSE
);
1836 if (str_patterns
== NULL
)
1839 ? "invalid second string `%s' in final_presence_set"
1840 : "invalid second string `%s' in presence_set")
1842 ? "invalid second string `%s' in final_absence_set"
1843 : "invalid second string `%s' in absence_set")), XSTR (def
, 1));
1844 for (i
= 0; i
< patterns_length
; i
++)
1846 str_patterns
[i
] = get_str_vect ((char *) str_patterns
[i
], &length
, ' ',
1848 if (str_patterns
[i
] == NULL
)
1851 decl
= create_node (sizeof (struct decl
));
1855 decl
->mode
= dm_presence
;
1856 DECL_PRESENCE (decl
)->names_num
= cpu_units_length
;
1857 DECL_PRESENCE (decl
)->names
= str_cpu_units
;
1858 DECL_PRESENCE (decl
)->patterns
= str_patterns
;
1859 DECL_PRESENCE (decl
)->patterns_num
= patterns_length
;
1860 DECL_PRESENCE (decl
)->final_p
= final_p
;
1864 decl
->mode
= dm_absence
;
1865 DECL_ABSENCE (decl
)->names_num
= cpu_units_length
;
1866 DECL_ABSENCE (decl
)->names
= str_cpu_units
;
1867 DECL_ABSENCE (decl
)->patterns
= str_patterns
;
1868 DECL_ABSENCE (decl
)->patterns_num
= patterns_length
;
1869 DECL_ABSENCE (decl
)->final_p
= final_p
;
1871 VLA_PTR_ADD (decls
, decl
);
1875 /* Process a PRESENCE_SET.
1877 This gives information about a cpu unit reservation requirements.
1878 We fill a struct unit_pattern_rel_decl (presence) with information
1879 used later by `expand_automata'. */
1881 gen_presence_set (def
)
1884 gen_presence_absence_set (def
, TRUE
, FALSE
);
1887 /* Process a FINAL_PRESENCE_SET.
1889 This gives information about a cpu unit reservation requirements.
1890 We fill a struct unit_pattern_rel_decl (presence) with information
1891 used later by `expand_automata'. */
1893 gen_final_presence_set (def
)
1896 gen_presence_absence_set (def
, TRUE
, TRUE
);
1899 /* Process an ABSENCE_SET.
1901 This gives information about a cpu unit reservation requirements.
1902 We fill a struct unit_pattern_rel_decl (absence) with information
1903 used later by `expand_automata'. */
1905 gen_absence_set (def
)
1908 gen_presence_absence_set (def
, FALSE
, FALSE
);
1911 /* Process a FINAL_ABSENCE_SET.
1913 This gives information about a cpu unit reservation requirements.
1914 We fill a struct unit_pattern_rel_decl (absence) with information
1915 used later by `expand_automata'. */
1917 gen_final_absence_set (def
)
1920 gen_presence_absence_set (def
, FALSE
, TRUE
);
1923 /* Process a DEFINE_AUTOMATON.
1925 This gives information about a finite state automaton used for
1926 recognizing pipeline hazards. We fill a struct automaton_decl
1927 with information used later by `expand_automata'. */
1933 char **str_automata
;
1937 str_automata
= get_str_vect ((char *) XSTR (def
, 0), &vect_length
, ',',
1939 if (str_automata
== NULL
)
1940 fatal ("invalid string `%s' in define_automaton", XSTR (def
, 0));
1941 for (i
= 0; i
< vect_length
; i
++)
1943 decl
= create_node (sizeof (struct decl
));
1944 decl
->mode
= dm_automaton
;
1946 DECL_AUTOMATON (decl
)->name
= check_name (str_automata
[i
], decl
->pos
);
1947 VLA_PTR_ADD (decls
, decl
);
1952 /* Process an AUTOMATA_OPTION.
1954 This gives information how to generate finite state automaton used
1955 for recognizing pipeline hazards. */
1957 gen_automata_option (def
)
1960 if (strcmp ((char *) XSTR (def
, 0), NO_MINIMIZATION_OPTION
+ 1) == 0)
1961 no_minimization_flag
= 1;
1962 else if (strcmp ((char *) XSTR (def
, 0), TIME_OPTION
+ 1) == 0)
1964 else if (strcmp ((char *) XSTR (def
, 0), V_OPTION
+ 1) == 0)
1966 else if (strcmp ((char *) XSTR (def
, 0), W_OPTION
+ 1) == 0)
1968 else if (strcmp ((char *) XSTR (def
, 0), NDFA_OPTION
+ 1) == 0)
1971 fatal ("invalid option `%s' in automata_option", XSTR (def
, 0));
1974 /* Name in reservation to denote absence reservation. */
1975 #define NOTHING_NAME "nothing"
1977 /* The following string contains original reservation string being
1979 static char *reserv_str
;
1981 /* Parse an element in STR. */
1992 if (str
[len
- 1] != ')')
1993 fatal ("garbage after ) in reservation `%s'", reserv_str
);
1994 str
[len
- 1] = '\0';
1995 regexp
= gen_regexp_sequence (str
+ 1);
1997 else if (strcmp (str
, NOTHING_NAME
) == 0)
1999 regexp
= create_node (sizeof (struct decl
));
2000 regexp
->mode
= rm_nothing
;
2004 regexp
= create_node (sizeof (struct decl
));
2005 regexp
->mode
= rm_unit
;
2006 REGEXP_UNIT (regexp
)->name
= str
;
2011 /* Parse construction `repeat' in STR. */
2013 gen_regexp_repeat (str
)
2022 repeat_vect
= get_str_vect (str
, &els_num
, '*', TRUE
);
2023 if (repeat_vect
== NULL
)
2024 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
2027 regexp
= gen_regexp_el (repeat_vect
[0]);
2028 for (i
= 1; i
< els_num
; i
++)
2030 repeat
= create_node (sizeof (struct regexp
));
2031 repeat
->mode
= rm_repeat
;
2032 REGEXP_REPEAT (repeat
)->regexp
= regexp
;
2033 REGEXP_REPEAT (repeat
)->repeat_num
= atoi (repeat_vect
[i
]);
2034 if (REGEXP_REPEAT (repeat
)->repeat_num
<= 1)
2035 fatal ("repetition `%s' <= 1 in reservation `%s'",
2042 return gen_regexp_el (str
);
2045 /* Parse reservation STR which possibly contains separator '+'. */
2047 gen_regexp_allof (str
)
2055 allof_vect
= get_str_vect (str
, &els_num
, '+', TRUE
);
2056 if (allof_vect
== NULL
)
2057 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
2060 allof
= create_node (sizeof (struct regexp
)
2061 + sizeof (regexp_t
) * (els_num
- 1));
2062 allof
->mode
= rm_allof
;
2063 REGEXP_ALLOF (allof
)->regexps_num
= els_num
;
2064 for (i
= 0; i
< els_num
; i
++)
2065 REGEXP_ALLOF (allof
)->regexps
[i
] = gen_regexp_repeat (allof_vect
[i
]);
2069 return gen_regexp_repeat (str
);
2072 /* Parse reservation STR which possibly contains separator '|'. */
2074 gen_regexp_oneof (str
)
2082 oneof_vect
= get_str_vect (str
, &els_num
, '|', TRUE
);
2083 if (oneof_vect
== NULL
)
2084 fatal ("invalid `%s' in reservation `%s'", str
, reserv_str
);
2087 oneof
= create_node (sizeof (struct regexp
)
2088 + sizeof (regexp_t
) * (els_num
- 1));
2089 oneof
->mode
= rm_oneof
;
2090 REGEXP_ONEOF (oneof
)->regexps_num
= els_num
;
2091 for (i
= 0; i
< els_num
; i
++)
2092 REGEXP_ONEOF (oneof
)->regexps
[i
] = gen_regexp_allof (oneof_vect
[i
]);
2096 return gen_regexp_allof (str
);
2099 /* Parse reservation STR which possibly contains separator ','. */
2101 gen_regexp_sequence (str
)
2105 char **sequence_vect
;
2109 sequence_vect
= get_str_vect (str
, &els_num
, ',', TRUE
);
2112 sequence
= create_node (sizeof (struct regexp
)
2113 + sizeof (regexp_t
) * (els_num
- 1));
2114 sequence
->mode
= rm_sequence
;
2115 REGEXP_SEQUENCE (sequence
)->regexps_num
= els_num
;
2116 for (i
= 0; i
< els_num
; i
++)
2117 REGEXP_SEQUENCE (sequence
)->regexps
[i
]
2118 = gen_regexp_oneof (sequence_vect
[i
]);
2122 return gen_regexp_oneof (str
);
2125 /* Parse construction reservation STR. */
2131 return gen_regexp_sequence (str
);;
2134 /* Process a DEFINE_RESERVATION.
2136 This gives information about a reservation of cpu units. We fill
2137 in a struct reserv_decl with information used later by
2138 `expand_automata'. */
2145 decl
= create_node (sizeof (struct decl
));
2146 decl
->mode
= dm_reserv
;
2148 DECL_RESERV (decl
)->name
= check_name ((char *) XSTR (def
, 0), decl
->pos
);
2149 DECL_RESERV (decl
)->regexp
= gen_regexp ((char *) XSTR (def
, 1));
2150 VLA_PTR_ADD (decls
, decl
);
2154 /* Process a DEFINE_INSN_RESERVATION.
2156 This gives information about the reservation of cpu units by an
2157 insn. We fill a struct insn_reserv_decl with information used
2158 later by `expand_automata'. */
2160 gen_insn_reserv (def
)
2165 decl
= create_node (sizeof (struct decl
));
2166 decl
->mode
= dm_insn_reserv
;
2168 DECL_INSN_RESERV (decl
)->name
2169 = check_name ((char *) XSTR (def
, 0), decl
->pos
);
2170 DECL_INSN_RESERV (decl
)->default_latency
= XINT (def
, 1);
2171 DECL_INSN_RESERV (decl
)->condexp
= XEXP (def
, 2);
2172 DECL_INSN_RESERV (decl
)->regexp
= gen_regexp ((char *) XSTR (def
, 3));
2173 VLA_PTR_ADD (decls
, decl
);
2179 /* The function evaluates hash value (0..UINT_MAX) of string. */
2181 string_hash (string
)
2186 for (result
= i
= 0;*string
++ != '\0'; i
++)
2187 result
+= ((unsigned char) *string
<< (i
% CHAR_BIT
));
2193 /* This page contains abstract data `table of automaton declarations'.
2194 Elements of the table is nodes representing automaton declarations.
2195 Key of the table elements is name of given automaton. Remember
2196 that automaton names have own space. */
2198 /* The function evaluates hash value of an automaton declaration. The
2199 function is used by abstract data `hashtab'. The function returns
2200 hash value (0..UINT_MAX) of given automaton declaration. */
2202 automaton_decl_hash (automaton_decl
)
2203 const void *automaton_decl
;
2205 const decl_t decl
= (decl_t
) automaton_decl
;
2207 if (decl
->mode
== dm_automaton
&& DECL_AUTOMATON (decl
)->name
== NULL
)
2209 return string_hash (DECL_AUTOMATON (decl
)->name
);
2212 /* The function tests automaton declarations on equality of their
2213 keys. The function is used by abstract data `hashtab'. The
2214 function returns 1 if the declarations have the same key, 0
2217 automaton_decl_eq_p (automaton_decl_1
, automaton_decl_2
)
2218 const void* automaton_decl_1
;
2219 const void* automaton_decl_2
;
2221 const decl_t decl1
= (decl_t
) automaton_decl_1
;
2222 const decl_t decl2
= (decl_t
) automaton_decl_2
;
2224 if (decl1
->mode
!= dm_automaton
|| DECL_AUTOMATON (decl1
)->name
== NULL
2225 || decl2
->mode
!= dm_automaton
|| DECL_AUTOMATON (decl2
)->name
== NULL
)
2227 return strcmp (DECL_AUTOMATON (decl1
)->name
,
2228 DECL_AUTOMATON (decl2
)->name
) == 0;
2231 /* The automaton declaration table itself is represented by the
2232 following variable. */
2233 static htab_t automaton_decl_table
;
2235 /* The function inserts automaton declaration into the table. The
2236 function does nothing if an automaton declaration with the same key
2237 exists already in the table. The function returns automaton
2238 declaration node in the table with the same key as given automaton
2239 declaration node. */
2241 insert_automaton_decl (automaton_decl
)
2242 decl_t automaton_decl
;
2246 entry_ptr
= htab_find_slot (automaton_decl_table
, automaton_decl
, 1);
2247 if (*entry_ptr
== NULL
)
2248 *entry_ptr
= (void *) automaton_decl
;
2249 return (decl_t
) *entry_ptr
;
2252 /* The following variable value is node representing automaton
2253 declaration. The node used for searching automaton declaration
2255 static struct decl work_automaton_decl
;
2257 /* The function searches for automaton declaration in the table with
2258 the same key as node representing name of the automaton
2259 declaration. The function returns node found in the table, NULL if
2260 such node does not exist in the table. */
2262 find_automaton_decl (name
)
2267 work_automaton_decl
.mode
= dm_automaton
;
2268 DECL_AUTOMATON (&work_automaton_decl
)->name
= name
;
2269 entry
= htab_find (automaton_decl_table
, &work_automaton_decl
);
2270 return (decl_t
) entry
;
2273 /* The function creates empty automaton declaration table and node
2274 representing automaton declaration and used for searching automaton
2275 declaration with given name. The function must be called only once
2276 before any work with the automaton declaration table. */
2278 initiate_automaton_decl_table ()
2280 work_automaton_decl
.mode
= dm_automaton
;
2281 automaton_decl_table
= htab_create (10, automaton_decl_hash
,
2282 automaton_decl_eq_p
, (htab_del
) 0);
2285 /* The function deletes the automaton declaration table. Only call of
2286 function `initiate_automaton_decl_table' is possible immediately
2287 after this function call. */
2289 finish_automaton_decl_table ()
2291 htab_delete (automaton_decl_table
);
2296 /* This page contains abstract data `table of insn declarations'.
2297 Elements of the table is nodes representing insn declarations. Key
2298 of the table elements is name of given insn (in corresponding
2299 define_insn_reservation). Remember that insn names have own
2302 /* The function evaluates hash value of an insn declaration. The
2303 function is used by abstract data `hashtab'. The function returns
2304 hash value (0..UINT_MAX) of given insn declaration. */
2306 insn_decl_hash (insn_decl
)
2307 const void *insn_decl
;
2309 const decl_t decl
= (decl_t
) insn_decl
;
2311 if (decl
->mode
!= dm_insn_reserv
|| DECL_INSN_RESERV (decl
)->name
== NULL
)
2313 return string_hash (DECL_INSN_RESERV (decl
)->name
);
2316 /* The function tests insn declarations on equality of their keys.
2317 The function is used by abstract data `hashtab'. The function
2318 returns 1 if declarations have the same key, 0 otherwise. */
2320 insn_decl_eq_p (insn_decl_1
, insn_decl_2
)
2321 const void *insn_decl_1
;
2322 const void *insn_decl_2
;
2324 const decl_t decl1
= (decl_t
) insn_decl_1
;
2325 const decl_t decl2
= (decl_t
) insn_decl_2
;
2327 if (decl1
->mode
!= dm_insn_reserv
|| DECL_INSN_RESERV (decl1
)->name
== NULL
2328 || decl2
->mode
!= dm_insn_reserv
2329 || DECL_INSN_RESERV (decl2
)->name
== NULL
)
2331 return strcmp (DECL_INSN_RESERV (decl1
)->name
,
2332 DECL_INSN_RESERV (decl2
)->name
) == 0;
2335 /* The insn declaration table itself is represented by the following
2336 variable. The table does not contain insn reservation
2338 static htab_t insn_decl_table
;
2340 /* The function inserts insn declaration into the table. The function
2341 does nothing if an insn declaration with the same key exists
2342 already in the table. The function returns insn declaration node
2343 in the table with the same key as given insn declaration node. */
2345 insert_insn_decl (insn_decl
)
2350 entry_ptr
= htab_find_slot (insn_decl_table
, insn_decl
, 1);
2351 if (*entry_ptr
== NULL
)
2352 *entry_ptr
= (void *) insn_decl
;
2353 return (decl_t
) *entry_ptr
;
2356 /* The following variable value is node representing insn reservation
2357 declaration. The node used for searching insn reservation
2358 declaration with given name. */
2359 static struct decl work_insn_decl
;
2361 /* The function searches for insn reservation declaration in the table
2362 with the same key as node representing name of the insn reservation
2363 declaration. The function returns node found in the table, NULL if
2364 such node does not exist in the table. */
2366 find_insn_decl (name
)
2371 work_insn_decl
.mode
= dm_insn_reserv
;
2372 DECL_INSN_RESERV (&work_insn_decl
)->name
= name
;
2373 entry
= htab_find (insn_decl_table
, &work_insn_decl
);
2374 return (decl_t
) entry
;
2377 /* The function creates empty insn declaration table and node
2378 representing insn declaration and used for searching insn
2379 declaration with given name. The function must be called only once
2380 before any work with the insn declaration table. */
2382 initiate_insn_decl_table ()
2384 work_insn_decl
.mode
= dm_insn_reserv
;
2385 insn_decl_table
= htab_create (10, insn_decl_hash
, insn_decl_eq_p
,
2389 /* The function deletes the insn declaration table. Only call of
2390 function `initiate_insn_decl_table' is possible immediately after
2391 this function call. */
2393 finish_insn_decl_table ()
2395 htab_delete (insn_decl_table
);
2400 /* This page contains abstract data `table of declarations'. Elements
2401 of the table is nodes representing declarations (of units and
2402 reservations). Key of the table elements is names of given
2405 /* The function evaluates hash value of a declaration. The function
2406 is used by abstract data `hashtab'. The function returns hash
2407 value (0..UINT_MAX) of given declaration. */
2412 const decl_t d
= (const decl_t
) decl
;
2414 if ((d
->mode
!= dm_unit
|| DECL_UNIT (d
)->name
== NULL
)
2415 && (d
->mode
!= dm_reserv
|| DECL_RESERV (d
)->name
== NULL
))
2417 return string_hash (d
->mode
== dm_unit
2418 ? DECL_UNIT (d
)->name
: DECL_RESERV (d
)->name
);
2421 /* The function tests declarations on equality of their keys. The
2422 function is used by abstract data `hashtab'. The function
2423 returns 1 if the declarations have the same key, 0 otherwise. */
2425 decl_eq_p (decl_1
, decl_2
)
2429 const decl_t d1
= (const decl_t
) decl_1
;
2430 const decl_t d2
= (const decl_t
) decl_2
;
2432 if (((d1
->mode
!= dm_unit
|| DECL_UNIT (d1
)->name
== NULL
)
2433 && (d1
->mode
!= dm_reserv
|| DECL_RESERV (d1
)->name
== NULL
))
2434 || ((d2
->mode
!= dm_unit
|| DECL_UNIT (d2
)->name
== NULL
)
2435 && (d2
->mode
!= dm_reserv
|| DECL_RESERV (d2
)->name
== NULL
)))
2437 return strcmp ((d1
->mode
== dm_unit
2438 ? DECL_UNIT (d1
)->name
: DECL_RESERV (d1
)->name
),
2439 (d2
->mode
== dm_unit
2440 ? DECL_UNIT (d2
)->name
: DECL_RESERV (d2
)->name
)) == 0;
2443 /* The declaration table itself is represented by the following
2445 static htab_t decl_table
;
2447 /* The function inserts declaration into the table. The function does
2448 nothing if a declaration with the same key exists already in the
2449 table. The function returns declaration node in the table with the
2450 same key as given declaration node. */
2458 entry_ptr
= htab_find_slot (decl_table
, decl
, 1);
2459 if (*entry_ptr
== NULL
)
2460 *entry_ptr
= (void *) decl
;
2461 return (decl_t
) *entry_ptr
;
2464 /* The following variable value is node representing declaration. The
2465 node used for searching declaration with given name. */
2466 static struct decl work_decl
;
2468 /* The function searches for declaration in the table with the same
2469 key as node representing name of the declaration. The function
2470 returns node found in the table, NULL if such node does not exist
2478 work_decl
.mode
= dm_unit
;
2479 DECL_UNIT (&work_decl
)->name
= name
;
2480 entry
= htab_find (decl_table
, &work_decl
);
2481 return (decl_t
) entry
;
2484 /* The function creates empty declaration table and node representing
2485 declaration and used for searching declaration with given name.
2486 The function must be called only once before any work with the
2487 declaration table. */
2489 initiate_decl_table ()
2491 work_decl
.mode
= dm_unit
;
2492 decl_table
= htab_create (10, decl_hash
, decl_eq_p
, (htab_del
) 0);
2495 /* The function deletes the declaration table. Only call of function
2496 `initiate_declaration_table' is possible immediately after this
2499 finish_decl_table ()
2501 htab_delete (decl_table
);
2506 /* This page contains checker of pipeline hazard description. */
2508 /* Checking NAMES in an exclusion clause vector and returning formed
2509 unit_set_el_list. */
2510 static unit_set_el_t
2511 process_excls (names
, num
, excl_pos
)
2514 pos_t excl_pos ATTRIBUTE_UNUSED
;
2516 unit_set_el_t el_list
;
2517 unit_set_el_t last_el
;
2518 unit_set_el_t new_el
;
2519 decl_t decl_in_table
;
2524 for (i
= 0; i
< num
; i
++)
2526 decl_in_table
= find_decl (names
[i
]);
2527 if (decl_in_table
== NULL
)
2528 error ("unit `%s' in exclusion is not declared", names
[i
]);
2529 else if (decl_in_table
->mode
!= dm_unit
)
2530 error ("`%s' in exclusion is not unit", names
[i
]);
2533 new_el
= create_node (sizeof (struct unit_set_el
));
2534 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2535 new_el
->next_unit_set_el
= NULL
;
2536 if (last_el
== NULL
)
2537 el_list
= last_el
= new_el
;
2540 last_el
->next_unit_set_el
= new_el
;
2541 last_el
= last_el
->next_unit_set_el
;
2548 /* The function adds each element from SOURCE_LIST to the exclusion
2549 list of the each element from DEST_LIST. Checking situation "unit
2550 excludes itself". */
2552 add_excls (dest_list
, source_list
, excl_pos
)
2553 unit_set_el_t dest_list
;
2554 unit_set_el_t source_list
;
2555 pos_t excl_pos ATTRIBUTE_UNUSED
;
2559 unit_set_el_t curr_el
;
2560 unit_set_el_t prev_el
;
2563 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2564 for (src
= source_list
; src
!= NULL
; src
= src
->next_unit_set_el
)
2566 if (dst
->unit_decl
== src
->unit_decl
)
2568 error ("unit `%s' excludes itself", src
->unit_decl
->name
);
2571 if (dst
->unit_decl
->automaton_name
!= NULL
2572 && src
->unit_decl
->automaton_name
!= NULL
2573 && strcmp (dst
->unit_decl
->automaton_name
,
2574 src
->unit_decl
->automaton_name
) != 0)
2576 error ("units `%s' and `%s' in exclusion set belong to different automata",
2577 src
->unit_decl
->name
, dst
->unit_decl
->name
);
2580 for (curr_el
= dst
->unit_decl
->excl_list
, prev_el
= NULL
;
2582 prev_el
= curr_el
, curr_el
= curr_el
->next_unit_set_el
)
2583 if (curr_el
->unit_decl
== src
->unit_decl
)
2585 if (curr_el
== NULL
)
2587 /* Element not found - insert. */
2588 copy
= copy_node (src
, sizeof (*src
));
2589 copy
->next_unit_set_el
= NULL
;
2590 if (prev_el
== NULL
)
2591 dst
->unit_decl
->excl_list
= copy
;
2593 prev_el
->next_unit_set_el
= copy
;
2598 /* Checking NAMES in presence/absence clause and returning the
2599 formed unit_set_el_list. The function is called only after
2600 processing all exclusion sets. */
2601 static unit_set_el_t
2602 process_presence_absence_names (names
, num
, req_pos
, presence_p
, final_p
)
2605 pos_t req_pos ATTRIBUTE_UNUSED
;
2609 unit_set_el_t el_list
;
2610 unit_set_el_t last_el
;
2611 unit_set_el_t new_el
;
2612 decl_t decl_in_table
;
2617 for (i
= 0; i
< num
; i
++)
2619 decl_in_table
= find_decl (names
[i
]);
2620 if (decl_in_table
== NULL
)
2623 ? "unit `%s' in final presence set is not declared"
2624 : "unit `%s' in presence set is not declared")
2626 ? "unit `%s' in final absence set is not declared"
2627 : "unit `%s' in absence set is not declared")), names
[i
]);
2628 else if (decl_in_table
->mode
!= dm_unit
)
2631 ? "`%s' in final presence set is not unit"
2632 : "`%s' in presence set is not unit")
2634 ? "`%s' in final absence set is not unit"
2635 : "`%s' in absence set is not unit")), names
[i
]);
2638 new_el
= create_node (sizeof (struct unit_set_el
));
2639 new_el
->unit_decl
= DECL_UNIT (decl_in_table
);
2640 new_el
->next_unit_set_el
= NULL
;
2641 if (last_el
== NULL
)
2642 el_list
= last_el
= new_el
;
2645 last_el
->next_unit_set_el
= new_el
;
2646 last_el
= last_el
->next_unit_set_el
;
2653 /* Checking NAMES in patterns of a presence/absence clause and
2654 returning the formed pattern_set_el_list. The function is called
2655 only after processing all exclusion sets. */
2656 static pattern_set_el_t
2657 process_presence_absence_patterns (patterns
, num
, req_pos
, presence_p
, final_p
)
2660 pos_t req_pos ATTRIBUTE_UNUSED
;
2664 pattern_set_el_t el_list
;
2665 pattern_set_el_t last_el
;
2666 pattern_set_el_t new_el
;
2667 decl_t decl_in_table
;
2672 for (i
= 0; i
< num
; i
++)
2674 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2676 new_el
= create_node (sizeof (struct pattern_set_el
)
2677 + sizeof (struct unit_decl
*) * j
);
2679 = (struct unit_decl
**) ((char *) new_el
2680 + sizeof (struct pattern_set_el
));
2681 new_el
->next_pattern_set_el
= NULL
;
2682 if (last_el
== NULL
)
2683 el_list
= last_el
= new_el
;
2686 last_el
->next_pattern_set_el
= new_el
;
2687 last_el
= last_el
->next_pattern_set_el
;
2689 new_el
->units_num
= 0;
2690 for (j
= 0; patterns
[i
] [j
] != NULL
; j
++)
2692 decl_in_table
= find_decl (patterns
[i
] [j
]);
2693 if (decl_in_table
== NULL
)
2696 ? "unit `%s' in final presence set is not declared"
2697 : "unit `%s' in presence set is not declared")
2699 ? "unit `%s' in final absence set is not declared"
2700 : "unit `%s' in absence set is not declared")),
2702 else if (decl_in_table
->mode
!= dm_unit
)
2705 ? "`%s' in final presence set is not unit"
2706 : "`%s' in presence set is not unit")
2708 ? "`%s' in final absence set is not unit"
2709 : "`%s' in absence set is not unit")),
2713 new_el
->unit_decls
[new_el
->units_num
]
2714 = DECL_UNIT (decl_in_table
);
2715 new_el
->units_num
++;
2722 /* The function adds each element from PATTERN_LIST to presence (if
2723 PRESENCE_P) or absence list of the each element from DEST_LIST.
2724 Checking situations "unit requires own absence", and "unit excludes
2725 and requires presence of ...", "unit requires absence and presence
2726 of ...", "units in (final) presence set belong to different
2727 automata", and "units in (final) absence set belong to different
2728 automata". Remember that we process absence sets only after all
2731 add_presence_absence (dest_list
, pattern_list
, req_pos
, presence_p
, final_p
)
2732 unit_set_el_t dest_list
;
2733 pattern_set_el_t pattern_list
;
2734 pos_t req_pos ATTRIBUTE_UNUSED
;
2739 pattern_set_el_t pat
;
2740 struct unit_decl
*unit
;
2741 unit_set_el_t curr_excl_el
;
2742 pattern_set_el_t curr_pat_el
;
2743 pattern_set_el_t prev_el
;
2744 pattern_set_el_t copy
;
2748 for (dst
= dest_list
; dst
!= NULL
; dst
= dst
->next_unit_set_el
)
2749 for (pat
= pattern_list
; pat
!= NULL
; pat
= pat
->next_pattern_set_el
)
2751 for (i
= 0; i
< pat
->units_num
; i
++)
2753 unit
= pat
->unit_decls
[i
];
2754 if (dst
->unit_decl
== unit
&& pat
->units_num
== 1 && !presence_p
)
2756 error ("unit `%s' requires own absence", unit
->name
);
2759 if (dst
->unit_decl
->automaton_name
!= NULL
2760 && unit
->automaton_name
!= NULL
2761 && strcmp (dst
->unit_decl
->automaton_name
,
2762 unit
->automaton_name
) != 0)
2766 ? "units `%s' and `%s' in final presence set belong to different automata"
2767 : "units `%s' and `%s' in presence set belong to different automata")
2769 ? "units `%s' and `%s' in final absence set belong to different automata"
2770 : "units `%s' and `%s' in absence set belong to different automata")),
2771 unit
->name
, dst
->unit_decl
->name
);
2776 for (curr_excl_el
= dst
->unit_decl
->excl_list
;
2777 curr_excl_el
!= NULL
;
2778 curr_excl_el
= curr_excl_el
->next_unit_set_el
)
2780 if (unit
== curr_excl_el
->unit_decl
&& pat
->units_num
== 1)
2784 error ("unit `%s' excludes and requires presence of `%s'",
2785 dst
->unit_decl
->name
, unit
->name
);
2790 ("unit `%s' excludes and requires presence of `%s'",
2791 dst
->unit_decl
->name
, unit
->name
);
2794 else if (pat
->units_num
== 1)
2795 for (curr_pat_el
= dst
->unit_decl
->presence_list
;
2796 curr_pat_el
!= NULL
;
2797 curr_pat_el
= curr_pat_el
->next_pattern_set_el
)
2798 if (curr_pat_el
->units_num
== 1
2799 && unit
== curr_pat_el
->unit_decls
[0])
2804 ("unit `%s' requires absence and presence of `%s'",
2805 dst
->unit_decl
->name
, unit
->name
);
2810 ("unit `%s' requires absence and presence of `%s'",
2811 dst
->unit_decl
->name
, unit
->name
);
2815 for (prev_el
= (presence_p
2817 ? dst
->unit_decl
->final_presence_list
2818 : dst
->unit_decl
->final_presence_list
)
2820 ? dst
->unit_decl
->final_absence_list
2821 : dst
->unit_decl
->absence_list
));
2822 prev_el
!= NULL
&& prev_el
->next_pattern_set_el
!= NULL
;
2823 prev_el
= prev_el
->next_pattern_set_el
)
2825 copy
= copy_node (pat
, sizeof (*pat
));
2826 copy
->next_pattern_set_el
= NULL
;
2827 if (prev_el
== NULL
)
2832 dst
->unit_decl
->final_presence_list
= copy
;
2834 dst
->unit_decl
->presence_list
= copy
;
2837 dst
->unit_decl
->final_absence_list
= copy
;
2839 dst
->unit_decl
->absence_list
= copy
;
2842 prev_el
->next_pattern_set_el
= copy
;
2849 /* The function searches for bypass with given IN_INSN_RESERV in given
2851 static struct bypass_decl
*
2852 find_bypass (bypass_list
, in_insn_reserv
)
2853 struct bypass_decl
*bypass_list
;
2854 struct insn_reserv_decl
*in_insn_reserv
;
2856 struct bypass_decl
*bypass
;
2858 for (bypass
= bypass_list
; bypass
!= NULL
; bypass
= bypass
->next
)
2859 if (bypass
->in_insn_reserv
== in_insn_reserv
)
2864 /* The function processes pipeline description declarations, checks
2865 their correctness, and forms exclusion/presence/absence sets. */
2870 decl_t automaton_decl
;
2871 decl_t decl_in_table
;
2872 decl_t out_insn_reserv
;
2873 decl_t in_insn_reserv
;
2874 struct bypass_decl
*bypass
;
2875 int automaton_presence
;
2878 /* Checking repeated automata declarations. */
2879 automaton_presence
= 0;
2880 for (i
= 0; i
< description
->decls_num
; i
++)
2882 decl
= description
->decls
[i
];
2883 if (decl
->mode
== dm_automaton
)
2885 automaton_presence
= 1;
2886 decl_in_table
= insert_automaton_decl (decl
);
2887 if (decl_in_table
!= decl
)
2890 error ("repeated declaration of automaton `%s'",
2891 DECL_AUTOMATON (decl
)->name
);
2893 warning ("repeated declaration of automaton `%s'",
2894 DECL_AUTOMATON (decl
)->name
);
2898 /* Checking undeclared automata, repeated declarations (except for
2899 automata) and correctness of their attributes (insn latency times
2901 for (i
= 0; i
< description
->decls_num
; i
++)
2903 decl
= description
->decls
[i
];
2904 if (decl
->mode
== dm_insn_reserv
)
2906 DECL_INSN_RESERV (decl
)->condexp
2907 = check_attr_test (DECL_INSN_RESERV (decl
)->condexp
, 0, 0);
2908 if (DECL_INSN_RESERV (decl
)->default_latency
< 0)
2909 error ("define_insn_reservation `%s' has negative latency time",
2910 DECL_INSN_RESERV (decl
)->name
);
2911 DECL_INSN_RESERV (decl
)->insn_num
= description
->insns_num
;
2912 description
->insns_num
++;
2913 decl_in_table
= insert_insn_decl (decl
);
2914 if (decl_in_table
!= decl
)
2915 error ("`%s' is already used as insn reservation name",
2916 DECL_INSN_RESERV (decl
)->name
);
2918 else if (decl
->mode
== dm_bypass
)
2920 if (DECL_BYPASS (decl
)->latency
< 0)
2921 error ("define_bypass `%s - %s' has negative latency time",
2922 DECL_BYPASS (decl
)->out_insn_name
,
2923 DECL_BYPASS (decl
)->in_insn_name
);
2925 else if (decl
->mode
== dm_unit
|| decl
->mode
== dm_reserv
)
2927 if (decl
->mode
== dm_unit
)
2929 DECL_UNIT (decl
)->automaton_decl
= NULL
;
2930 if (DECL_UNIT (decl
)->automaton_name
!= NULL
)
2933 = find_automaton_decl (DECL_UNIT (decl
)->automaton_name
);
2934 if (automaton_decl
== NULL
)
2935 error ("automaton `%s' is not declared",
2936 DECL_UNIT (decl
)->automaton_name
);
2939 DECL_AUTOMATON (automaton_decl
)->automaton_is_used
= 1;
2940 DECL_UNIT (decl
)->automaton_decl
2941 = DECL_AUTOMATON (automaton_decl
);
2944 else if (automaton_presence
)
2945 error ("define_unit `%s' without automaton when one defined",
2946 DECL_UNIT (decl
)->name
);
2947 DECL_UNIT (decl
)->unit_num
= description
->units_num
;
2948 description
->units_num
++;
2949 if (strcmp (DECL_UNIT (decl
)->name
, NOTHING_NAME
) == 0)
2951 error ("`%s' is declared as cpu unit", NOTHING_NAME
);
2954 decl_in_table
= find_decl (DECL_UNIT (decl
)->name
);
2958 if (strcmp (DECL_RESERV (decl
)->name
, NOTHING_NAME
) == 0)
2960 error ("`%s' is declared as cpu reservation", NOTHING_NAME
);
2963 decl_in_table
= find_decl (DECL_RESERV (decl
)->name
);
2965 if (decl_in_table
== NULL
)
2966 decl_in_table
= insert_decl (decl
);
2969 if (decl
->mode
== dm_unit
)
2970 error ("repeated declaration of unit `%s'",
2971 DECL_UNIT (decl
)->name
);
2973 error ("repeated declaration of reservation `%s'",
2974 DECL_RESERV (decl
)->name
);
2978 /* Check bypasses and form list of bypasses for each (output)
2980 for (i
= 0; i
< description
->decls_num
; i
++)
2982 decl
= description
->decls
[i
];
2983 if (decl
->mode
== dm_bypass
)
2985 out_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->out_insn_name
);
2986 in_insn_reserv
= find_insn_decl (DECL_BYPASS (decl
)->in_insn_name
);
2987 if (out_insn_reserv
== NULL
)
2988 error ("there is no insn reservation `%s'",
2989 DECL_BYPASS (decl
)->out_insn_name
);
2990 else if (in_insn_reserv
== NULL
)
2991 error ("there is no insn reservation `%s'",
2992 DECL_BYPASS (decl
)->in_insn_name
);
2995 DECL_BYPASS (decl
)->out_insn_reserv
2996 = DECL_INSN_RESERV (out_insn_reserv
);
2997 DECL_BYPASS (decl
)->in_insn_reserv
2998 = DECL_INSN_RESERV (in_insn_reserv
);
3000 = find_bypass (DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
,
3001 DECL_BYPASS (decl
)->in_insn_reserv
);
3004 if (DECL_BYPASS (decl
)->latency
== bypass
->latency
)
3008 ("the same bypass `%s - %s' is already defined",
3009 DECL_BYPASS (decl
)->out_insn_name
,
3010 DECL_BYPASS (decl
)->in_insn_name
);
3013 ("the same bypass `%s - %s' is already defined",
3014 DECL_BYPASS (decl
)->out_insn_name
,
3015 DECL_BYPASS (decl
)->in_insn_name
);
3018 error ("bypass `%s - %s' is already defined",
3019 DECL_BYPASS (decl
)->out_insn_name
,
3020 DECL_BYPASS (decl
)->in_insn_name
);
3024 DECL_BYPASS (decl
)->next
3025 = DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
;
3026 DECL_INSN_RESERV (out_insn_reserv
)->bypass_list
3027 = DECL_BYPASS (decl
);
3033 /* Check exclusion set declarations and form exclusion sets. */
3034 for (i
= 0; i
< description
->decls_num
; i
++)
3036 decl
= description
->decls
[i
];
3037 if (decl
->mode
== dm_excl
)
3039 unit_set_el_t unit_set_el_list
;
3040 unit_set_el_t unit_set_el_list_2
;
3043 = process_excls (DECL_EXCL (decl
)->names
,
3044 DECL_EXCL (decl
)->first_list_length
, decl
->pos
);
3046 = process_excls (&DECL_EXCL (decl
)->names
3047 [DECL_EXCL (decl
)->first_list_length
],
3048 DECL_EXCL (decl
)->all_names_num
3049 - DECL_EXCL (decl
)->first_list_length
,
3051 add_excls (unit_set_el_list
, unit_set_el_list_2
, decl
->pos
);
3052 add_excls (unit_set_el_list_2
, unit_set_el_list
, decl
->pos
);
3056 /* Check presence set declarations and form presence sets. */
3057 for (i
= 0; i
< description
->decls_num
; i
++)
3059 decl
= description
->decls
[i
];
3060 if (decl
->mode
== dm_presence
)
3062 unit_set_el_t unit_set_el_list
;
3063 pattern_set_el_t pattern_set_el_list
;
3066 = process_presence_absence_names
3067 (DECL_PRESENCE (decl
)->names
, DECL_PRESENCE (decl
)->names_num
,
3068 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
3070 = process_presence_absence_patterns
3071 (DECL_PRESENCE (decl
)->patterns
,
3072 DECL_PRESENCE (decl
)->patterns_num
,
3073 decl
->pos
, TRUE
, DECL_PRESENCE (decl
)->final_p
);
3074 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
3076 DECL_PRESENCE (decl
)->final_p
);
3080 /* Check absence set declarations and form absence sets. */
3081 for (i
= 0; i
< description
->decls_num
; i
++)
3083 decl
= description
->decls
[i
];
3084 if (decl
->mode
== dm_absence
)
3086 unit_set_el_t unit_set_el_list
;
3087 pattern_set_el_t pattern_set_el_list
;
3090 = process_presence_absence_names
3091 (DECL_ABSENCE (decl
)->names
, DECL_ABSENCE (decl
)->names_num
,
3092 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
3094 = process_presence_absence_patterns
3095 (DECL_ABSENCE (decl
)->patterns
,
3096 DECL_ABSENCE (decl
)->patterns_num
,
3097 decl
->pos
, FALSE
, DECL_ABSENCE (decl
)->final_p
);
3098 add_presence_absence (unit_set_el_list
, pattern_set_el_list
,
3100 DECL_ABSENCE (decl
)->final_p
);
3105 /* The following function checks that declared automaton is used. If
3106 the automaton is not used, the function fixes error/warning. The
3107 following function must be called only after `process_decls'. */
3109 check_automaton_usage ()
3114 for (i
= 0; i
< description
->decls_num
; i
++)
3116 decl
= description
->decls
[i
];
3117 if (decl
->mode
== dm_automaton
3118 && !DECL_AUTOMATON (decl
)->automaton_is_used
)
3121 error ("automaton `%s' is not used", DECL_AUTOMATON (decl
)->name
);
3123 warning ("automaton `%s' is not used",
3124 DECL_AUTOMATON (decl
)->name
);
3129 /* The following recursive function processes all regexp in order to
3130 fix usage of units or reservations and to fix errors of undeclared
3131 name. The function may change unit_regexp onto reserv_regexp.
3132 Remember that reserv_regexp does not exist before the function
3135 process_regexp (regexp
)
3138 decl_t decl_in_table
;
3139 regexp_t new_regexp
;
3142 if (regexp
->mode
== rm_unit
)
3144 decl_in_table
= find_decl (REGEXP_UNIT (regexp
)->name
);
3145 if (decl_in_table
== NULL
)
3146 error ("undeclared unit or reservation `%s'",
3147 REGEXP_UNIT (regexp
)->name
);
3148 else if (decl_in_table
->mode
== dm_unit
)
3150 DECL_UNIT (decl_in_table
)->unit_is_used
= 1;
3151 REGEXP_UNIT (regexp
)->unit_decl
= DECL_UNIT (decl_in_table
);
3153 else if (decl_in_table
->mode
== dm_reserv
)
3155 DECL_RESERV (decl_in_table
)->reserv_is_used
= 1;
3156 new_regexp
= create_node (sizeof (struct regexp
));
3157 new_regexp
->mode
= rm_reserv
;
3158 new_regexp
->pos
= regexp
->pos
;
3159 REGEXP_RESERV (new_regexp
)->name
= REGEXP_UNIT (regexp
)->name
;
3160 REGEXP_RESERV (new_regexp
)->reserv_decl
3161 = DECL_RESERV (decl_in_table
);
3162 regexp
= new_regexp
;
3167 else if (regexp
->mode
== rm_sequence
)
3168 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3169 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
3170 = process_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
3171 else if (regexp
->mode
== rm_allof
)
3172 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3173 REGEXP_ALLOF (regexp
)->regexps
[i
]
3174 = process_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
3175 else if (regexp
->mode
== rm_oneof
)
3176 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3177 REGEXP_ONEOF (regexp
)->regexps
[i
]
3178 = process_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
3179 else if (regexp
->mode
== rm_repeat
)
3180 REGEXP_REPEAT (regexp
)->regexp
3181 = process_regexp (REGEXP_REPEAT (regexp
)->regexp
);
3182 else if (regexp
->mode
!= rm_nothing
)
3187 /* The following function processes regexp of define_reservation and
3188 define_insn_reservation with the aid of function
3189 `process_regexp'. */
3191 process_regexp_decls ()
3196 for (i
= 0; i
< description
->decls_num
; i
++)
3198 decl
= description
->decls
[i
];
3199 if (decl
->mode
== dm_reserv
)
3200 DECL_RESERV (decl
)->regexp
3201 = process_regexp (DECL_RESERV (decl
)->regexp
);
3202 else if (decl
->mode
== dm_insn_reserv
)
3203 DECL_INSN_RESERV (decl
)->regexp
3204 = process_regexp (DECL_INSN_RESERV (decl
)->regexp
);
3208 /* The following function checks that declared unit is used. If the
3209 unit is not used, the function fixes errors/warnings. The
3210 following function must be called only after `process_decls',
3211 `process_regexp_decls'. */
3218 for (i
= 0; i
< description
->decls_num
; i
++)
3220 decl
= description
->decls
[i
];
3221 if (decl
->mode
== dm_unit
&& !DECL_UNIT (decl
)->unit_is_used
)
3224 error ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
3226 warning ("unit `%s' is not used", DECL_UNIT (decl
)->name
);
3228 else if (decl
->mode
== dm_reserv
&& !DECL_RESERV (decl
)->reserv_is_used
)
3231 error ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
3233 warning ("reservation `%s' is not used", DECL_RESERV (decl
)->name
);
3238 /* The following variable value is number of reservation being
3239 processed on loop recognition. */
3240 static int curr_loop_pass_num
;
3242 /* The following recursive function returns nonzero value if REGEXP
3243 contains given decl or reservations in given regexp refers for
3246 loop_in_regexp (regexp
, start_decl
)
3254 if (regexp
->mode
== rm_unit
)
3256 else if (regexp
->mode
== rm_reserv
)
3258 if (start_decl
->mode
== dm_reserv
3259 && REGEXP_RESERV (regexp
)->reserv_decl
== DECL_RESERV (start_decl
))
3261 else if (REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
3262 == curr_loop_pass_num
)
3263 /* declaration has been processed. */
3267 REGEXP_RESERV (regexp
)->reserv_decl
->loop_pass_num
3268 = curr_loop_pass_num
;
3269 return loop_in_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
3273 else if (regexp
->mode
== rm_sequence
)
3275 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3276 if (loop_in_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
], start_decl
))
3280 else if (regexp
->mode
== rm_allof
)
3282 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3283 if (loop_in_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
], start_decl
))
3287 else if (regexp
->mode
== rm_oneof
)
3289 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3290 if (loop_in_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
], start_decl
))
3294 else if (regexp
->mode
== rm_repeat
)
3295 return loop_in_regexp (REGEXP_REPEAT (regexp
)->regexp
, start_decl
);
3298 if (regexp
->mode
!= rm_nothing
)
3304 /* The following function fixes errors "cycle in definition ...". The
3305 function uses function `loop_in_regexp' for that. */
3307 check_loops_in_regexps ()
3312 for (i
= 0; i
< description
->decls_num
; i
++)
3314 decl
= description
->decls
[i
];
3315 if (decl
->mode
== dm_reserv
)
3316 DECL_RESERV (decl
)->loop_pass_num
= 0;
3318 for (i
= 0; i
< description
->decls_num
; i
++)
3320 decl
= description
->decls
[i
];
3321 curr_loop_pass_num
= i
;
3323 if (decl
->mode
== dm_reserv
)
3325 DECL_RESERV (decl
)->loop_pass_num
= curr_loop_pass_num
;
3326 if (loop_in_regexp (DECL_RESERV (decl
)->regexp
, decl
))
3328 if (DECL_RESERV (decl
)->regexp
== NULL
)
3330 error ("cycle in definition of reservation `%s'",
3331 DECL_RESERV (decl
)->name
);
3337 /* The function recursively processes IR of reservation and defines
3338 max and min cycle for reservation of unit. */
3340 process_regexp_cycles (regexp
, max_start_cycle
, min_start_cycle
,
3341 max_finish_cycle
, min_finish_cycle
)
3343 int max_start_cycle
, min_start_cycle
;
3344 int *max_finish_cycle
, *min_finish_cycle
;
3348 if (regexp
->mode
== rm_unit
)
3350 if (REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
< max_start_cycle
)
3351 REGEXP_UNIT (regexp
)->unit_decl
->max_occ_cycle_num
= max_start_cycle
;
3352 if (REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
> min_start_cycle
3353 || REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
== -1)
3354 REGEXP_UNIT (regexp
)->unit_decl
->min_occ_cycle_num
= min_start_cycle
;
3355 *max_finish_cycle
= max_start_cycle
;
3356 *min_finish_cycle
= min_start_cycle
;
3358 else if (regexp
->mode
== rm_reserv
)
3359 process_regexp_cycles (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
,
3360 max_start_cycle
, min_start_cycle
,
3361 max_finish_cycle
, min_finish_cycle
);
3362 else if (regexp
->mode
== rm_repeat
)
3364 for (i
= 0; i
< REGEXP_REPEAT (regexp
)->repeat_num
; i
++)
3366 process_regexp_cycles (REGEXP_REPEAT (regexp
)->regexp
,
3367 max_start_cycle
, min_start_cycle
,
3368 max_finish_cycle
, min_finish_cycle
);
3369 max_start_cycle
= *max_finish_cycle
+ 1;
3370 min_start_cycle
= *min_finish_cycle
+ 1;
3373 else if (regexp
->mode
== rm_sequence
)
3375 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
3377 process_regexp_cycles (REGEXP_SEQUENCE (regexp
)->regexps
[i
],
3378 max_start_cycle
, min_start_cycle
,
3379 max_finish_cycle
, min_finish_cycle
);
3380 max_start_cycle
= *max_finish_cycle
+ 1;
3381 min_start_cycle
= *min_finish_cycle
+ 1;
3384 else if (regexp
->mode
== rm_allof
)
3389 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
3391 process_regexp_cycles (REGEXP_ALLOF (regexp
)->regexps
[i
],
3392 max_start_cycle
, min_start_cycle
,
3393 max_finish_cycle
, min_finish_cycle
);
3394 if (max_cycle
< *max_finish_cycle
)
3395 max_cycle
= *max_finish_cycle
;
3396 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3397 min_cycle
= *min_finish_cycle
;
3399 *max_finish_cycle
= max_cycle
;
3400 *min_finish_cycle
= min_cycle
;
3402 else if (regexp
->mode
== rm_oneof
)
3407 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
3409 process_regexp_cycles (REGEXP_ONEOF (regexp
)->regexps
[i
],
3410 max_start_cycle
, min_start_cycle
,
3411 max_finish_cycle
, min_finish_cycle
);
3412 if (max_cycle
< *max_finish_cycle
)
3413 max_cycle
= *max_finish_cycle
;
3414 if (i
== 0 || min_cycle
> *min_finish_cycle
)
3415 min_cycle
= *min_finish_cycle
;
3417 *max_finish_cycle
= max_cycle
;
3418 *min_finish_cycle
= min_cycle
;
3422 if (regexp
->mode
!= rm_nothing
)
3424 *max_finish_cycle
= max_start_cycle
;
3425 *min_finish_cycle
= min_start_cycle
;
3429 /* The following function is called only for correct program. The
3430 function defines max reservation of insns in cycles. */
3432 evaluate_max_reserv_cycles ()
3434 int max_insn_cycles_num
;
3435 int min_insn_cycles_num
;
3439 description
->max_insn_reserv_cycles
= 0;
3440 for (i
= 0; i
< description
->decls_num
; i
++)
3442 decl
= description
->decls
[i
];
3443 if (decl
->mode
== dm_insn_reserv
)
3445 process_regexp_cycles (DECL_INSN_RESERV (decl
)->regexp
, 0, 0,
3446 &max_insn_cycles_num
, &min_insn_cycles_num
);
3447 if (description
->max_insn_reserv_cycles
< max_insn_cycles_num
)
3448 description
->max_insn_reserv_cycles
= max_insn_cycles_num
;
3451 description
->max_insn_reserv_cycles
++;
3454 /* The following function calls functions for checking all
3457 check_all_description ()
3460 check_automaton_usage ();
3461 process_regexp_decls ();
3463 check_loops_in_regexps ();
3465 evaluate_max_reserv_cycles ();
3470 /* The page contains abstract data `ticker'. This data is used to
3471 report time of different phases of building automata. It is
3472 possibly to write a description for which automata will be built
3473 during several minutes even on fast machine. */
3475 /* The following function creates ticker and makes it active. */
3481 ticker
.modified_creation_time
= get_run_time ();
3482 ticker
.incremented_off_time
= 0;
3486 /* The following function switches off given ticker. */
3491 if (ticker
->incremented_off_time
== 0)
3492 ticker
->incremented_off_time
= get_run_time () + 1;
3495 /* The following function switches on given ticker. */
3500 if (ticker
->incremented_off_time
!= 0)
3502 ticker
->modified_creation_time
3503 += get_run_time () - ticker
->incremented_off_time
+ 1;
3504 ticker
->incremented_off_time
= 0;
3508 /* The following function returns current time in milliseconds since
3509 the moment when given ticker was created. */
3511 active_time (ticker
)
3514 if (ticker
.incremented_off_time
!= 0)
3515 return ticker
.incremented_off_time
- 1 - ticker
.modified_creation_time
;
3517 return get_run_time () - ticker
.modified_creation_time
;
3520 /* The following function returns string representation of active time
3521 of given ticker. The result is string representation of seconds
3522 with accuracy of 1/100 second. Only result of the last call of the
3523 function exists. Therefore the following code is not correct
3525 printf ("parser time: %s\ngeneration time: %s\n",
3526 active_time_string (parser_ticker),
3527 active_time_string (generation_ticker));
3529 Correct code has to be the following
3531 printf ("parser time: %s\n", active_time_string (parser_ticker));
3532 printf ("generation time: %s\n",
3533 active_time_string (generation_ticker));
3537 print_active_time (f
, ticker
)
3543 msecs
= active_time (ticker
);
3544 fprintf (f
, "%d.%06d", msecs
/ 1000000, msecs
% 1000000);
3549 /* The following variable value is number of automaton which are
3550 really being created. This value is defined on the base of
3551 argument of option `-split'. If the variable has zero value the
3552 number of automata is defined by the constructions `%automaton'.
3553 This case occurs when option `-split' is absent or has zero
3554 argument. If constructions `define_automaton' is absent only one
3555 automaton is created. */
3556 static int automata_num
;
3558 /* The following variable values are times of
3559 o transformation of regular expressions
3560 o building NDFA (DFA if !ndfa_flag)
3561 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3563 o building insn equivalence classes
3566 static ticker_t transform_time
;
3567 static ticker_t NDFA_time
;
3568 static ticker_t NDFA_to_DFA_time
;
3569 static ticker_t minimize_time
;
3570 static ticker_t equiv_time
;
3571 static ticker_t automaton_generation_time
;
3572 static ticker_t output_time
;
3574 /* The following variable values are times of
3577 all pipeline hazard translator work */
3578 static ticker_t check_time
;
3579 static ticker_t generation_time
;
3580 static ticker_t all_time
;
3584 /* Pseudo insn decl which denotes advancing cycle. */
3585 static decl_t advance_cycle_insn_decl
;
3587 add_advance_cycle_insn_decl ()
3589 advance_cycle_insn_decl
= create_node (sizeof (struct decl
));
3590 advance_cycle_insn_decl
->mode
= dm_insn_reserv
;
3591 advance_cycle_insn_decl
->pos
= no_pos
;
3592 DECL_INSN_RESERV (advance_cycle_insn_decl
)->regexp
= NULL
;
3593 DECL_INSN_RESERV (advance_cycle_insn_decl
)->name
= (char *) "$advance_cycle";
3594 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
3595 = description
->insns_num
;
3596 description
->decls
[description
->decls_num
] = advance_cycle_insn_decl
;
3597 description
->decls_num
++;
3598 description
->insns_num
++;
3603 /* Abstract data `alternative states' which represents
3604 nondeterministic nature of the description (see comments for
3605 structures alt_state and state). */
3607 /* List of free states. */
3608 static alt_state_t first_free_alt_state
;
3611 /* The following variables is maximal number of allocated nodes
3613 static int allocated_alt_states_num
= 0;
3616 /* The following function returns free node alt_state. It may be new
3617 allocated node or node freed earlier. */
3619 get_free_alt_state ()
3623 if (first_free_alt_state
!= NULL
)
3625 result
= first_free_alt_state
;
3626 first_free_alt_state
= first_free_alt_state
->next_alt_state
;
3631 allocated_alt_states_num
++;
3633 result
= create_node (sizeof (struct alt_state
));
3635 result
->state
= NULL
;
3636 result
->next_alt_state
= NULL
;
3637 result
->next_sorted_alt_state
= NULL
;
3641 /* The function frees node ALT_STATE. */
3643 free_alt_state (alt_state
)
3644 alt_state_t alt_state
;
3646 if (alt_state
== NULL
)
3648 alt_state
->next_alt_state
= first_free_alt_state
;
3649 first_free_alt_state
= alt_state
;
3652 /* The function frees list started with node ALT_STATE_LIST. */
3654 free_alt_states (alt_states_list
)
3655 alt_state_t alt_states_list
;
3657 alt_state_t curr_alt_state
;
3658 alt_state_t next_alt_state
;
3660 for (curr_alt_state
= alt_states_list
;
3661 curr_alt_state
!= NULL
;
3662 curr_alt_state
= next_alt_state
)
3664 next_alt_state
= curr_alt_state
->next_alt_state
;
3665 free_alt_state (curr_alt_state
);
3669 /* The function compares unique numbers of alt states. */
3671 alt_state_cmp (alt_state_ptr_1
, alt_state_ptr_2
)
3672 const void *alt_state_ptr_1
;
3673 const void *alt_state_ptr_2
;
3675 if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3676 == (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3678 else if ((*(alt_state_t
*) alt_state_ptr_1
)->state
->unique_num
3679 < (*(alt_state_t
*) alt_state_ptr_2
)->state
->unique_num
)
3685 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3686 states from the list. The comparison key is alt state unique
3689 uniq_sort_alt_states (alt_states_list
)
3690 alt_state_t alt_states_list
;
3692 alt_state_t curr_alt_state
;
3693 vla_ptr_t alt_states
;
3695 size_t prev_unique_state_ind
;
3697 alt_state_t
*result_ptr
;
3699 VLA_PTR_CREATE (alt_states
, 150, "alt_states");
3700 for (curr_alt_state
= alt_states_list
;
3701 curr_alt_state
!= NULL
;
3702 curr_alt_state
= curr_alt_state
->next_alt_state
)
3703 VLA_PTR_ADD (alt_states
, curr_alt_state
);
3704 qsort (VLA_PTR_BEGIN (alt_states
), VLA_PTR_LENGTH (alt_states
),
3705 sizeof (alt_state_t
), alt_state_cmp
);
3706 if (VLA_PTR_LENGTH (alt_states
) == 0)
3710 result_ptr
= VLA_PTR_BEGIN (alt_states
);
3711 prev_unique_state_ind
= 0;
3712 for (i
= 1; i
< VLA_PTR_LENGTH (alt_states
); i
++)
3713 if (result_ptr
[prev_unique_state_ind
]->state
!= result_ptr
[i
]->state
)
3715 prev_unique_state_ind
++;
3716 result_ptr
[prev_unique_state_ind
] = result_ptr
[i
];
3719 for (i
= prev_unique_state_ind
+ 1; i
< VLA_PTR_LENGTH (alt_states
); i
++)
3720 free_alt_state (result_ptr
[i
]);
3722 VLA_PTR_SHORTEN (alt_states
, i
- prev_unique_state_ind
- 1);
3723 result_ptr
= VLA_PTR_BEGIN (alt_states
);
3724 for (i
= 1; i
< VLA_PTR_LENGTH (alt_states
); i
++)
3725 result_ptr
[i
- 1]->next_sorted_alt_state
= result_ptr
[i
];
3726 result_ptr
[i
- 1]->next_sorted_alt_state
= NULL
;
3727 result
= *result_ptr
;
3729 VLA_PTR_DELETE (alt_states
);
3733 /* The function checks equality of alt state lists. Remember that the
3734 lists must be already sorted by the previous function. */
3736 alt_states_eq (alt_states_1
, alt_states_2
)
3737 alt_state_t alt_states_1
;
3738 alt_state_t alt_states_2
;
3740 while (alt_states_1
!= NULL
&& alt_states_2
!= NULL
3741 && alt_state_cmp (&alt_states_1
, &alt_states_2
) == 0)
3743 alt_states_1
= alt_states_1
->next_sorted_alt_state
;
3744 alt_states_2
= alt_states_2
->next_sorted_alt_state
;
3746 return alt_states_1
== alt_states_2
;
3749 /* Initialization of the abstract data. */
3751 initiate_alt_states ()
3753 first_free_alt_state
= NULL
;
3756 /* Finishing work with the abstract data. */
3758 finish_alt_states ()
3764 /* The page contains macros for work with bits strings. We could use
3765 standard gcc bitmap or sbitmap but it would result in difficulties
3766 of building canadian cross. */
3768 /* Set bit number bitno in the bit string. The macro is not side
3770 #define SET_BIT(bitstring, bitno) \
3771 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3773 #define CLEAR_BIT(bitstring, bitno) \
3774 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3776 /* Test if bit number bitno in the bitstring is set. The macro is not
3777 side effect proof. */
3778 #define TEST_BIT(bitstring, bitno) \
3779 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3783 /* This page contains abstract data `state'. */
3785 /* Maximal length of reservations in cycles (>= 1). */
3786 static int max_cycles_num
;
3788 /* Number of set elements (see type set_el_t) needed for
3789 representation of one cycle reservation. It is depended on units
3791 static int els_in_cycle_reserv
;
3793 /* Number of set elements (see type set_el_t) needed for
3794 representation of maximal length reservation. Deterministic
3795 reservation is stored as set (bit string) of length equal to the
3796 variable value * number of bits in set_el_t. */
3797 static int els_in_reservs
;
3799 /* VLA for representation of array of pointers to unit
3801 static vla_ptr_t units_container
;
3803 /* The start address of the array. */
3804 static unit_decl_t
*units_array
;
3806 /* Temporary reservation of maximal length. */
3807 static reserv_sets_t temp_reserv
;
3809 /* The state table itself is represented by the following variable. */
3810 static htab_t state_table
;
3812 /* VLA for representation of array of pointers to free nodes
3814 static vla_ptr_t free_states
;
3816 static int curr_unique_state_num
;
3819 /* The following variables is maximal number of allocated nodes
3821 static int allocated_states_num
= 0;
3824 /* Allocate new reservation set. */
3825 static reserv_sets_t
3826 alloc_empty_reserv_sets ()
3828 reserv_sets_t result
;
3830 obstack_blank (&irp
, els_in_reservs
* sizeof (set_el_t
));
3831 result
= (reserv_sets_t
) obstack_base (&irp
);
3832 obstack_finish (&irp
);
3833 memset (result
, 0, els_in_reservs
* sizeof (set_el_t
));
3837 /* Hash value of reservation set. */
3839 reserv_sets_hash_value (reservs
)
3840 reserv_sets_t reservs
;
3842 set_el_t hash_value
;
3845 set_el_t
*reserv_ptr
;
3848 reservs_num
= els_in_reservs
;
3849 reserv_ptr
= reservs
;
3851 while (reservs_num
!= 0)
3854 hash_value
+= ((*reserv_ptr
>> i
)
3855 | (*reserv_ptr
<< (sizeof (set_el_t
) * CHAR_BIT
- i
)));
3857 if (i
== sizeof (set_el_t
) * CHAR_BIT
)
3861 if (sizeof (set_el_t
) <= sizeof (unsigned))
3864 for (i
= sizeof (set_el_t
); i
> 0; i
-= sizeof (unsigned) - 1)
3866 result
+= (unsigned) hash_value
;
3867 hash_value
>>= (sizeof (unsigned) - 1) * CHAR_BIT
;
3872 /* Comparison of given reservation sets. */
3874 reserv_sets_cmp (reservs_1
, reservs_2
)
3875 reserv_sets_t reservs_1
;
3876 reserv_sets_t reservs_2
;
3879 set_el_t
*reserv_ptr_1
;
3880 set_el_t
*reserv_ptr_2
;
3882 if (reservs_1
== NULL
|| reservs_2
== NULL
)
3884 reservs_num
= els_in_reservs
;
3885 reserv_ptr_1
= reservs_1
;
3886 reserv_ptr_2
= reservs_2
;
3887 while (reservs_num
!= 0 && *reserv_ptr_1
== *reserv_ptr_2
)
3893 if (reservs_num
== 0)
3895 else if (*reserv_ptr_1
< *reserv_ptr_2
)
3901 /* The function checks equality of the reservation sets. */
3903 reserv_sets_eq (reservs_1
, reservs_2
)
3904 reserv_sets_t reservs_1
;
3905 reserv_sets_t reservs_2
;
3907 return reserv_sets_cmp (reservs_1
, reservs_2
) == 0;
3910 /* Set up in the reservation set that unit with UNIT_NUM is used on
3913 set_unit_reserv (reservs
, cycle_num
, unit_num
)
3914 reserv_sets_t reservs
;
3918 if (cycle_num
>= max_cycles_num
)
3920 SET_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3921 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3924 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3925 used on CYCLE_NUM. */
3927 test_unit_reserv (reservs
, cycle_num
, unit_num
)
3928 reserv_sets_t reservs
;
3932 if (cycle_num
>= max_cycles_num
)
3934 return TEST_BIT (reservs
, cycle_num
* els_in_cycle_reserv
3935 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
);
3938 /* The function checks that the reservation set represents no one unit
3941 it_is_empty_reserv_sets (operand
)
3942 reserv_sets_t operand
;
3944 set_el_t
*reserv_ptr
;
3947 if (operand
== NULL
)
3949 for (reservs_num
= els_in_reservs
, reserv_ptr
= operand
;
3951 reserv_ptr
++, reservs_num
--)
3952 if (*reserv_ptr
!= 0)
3957 /* The function checks that the reservation sets are intersected,
3958 i.e. there is a unit reservation on a cycle in both reservation
3961 reserv_sets_are_intersected (operand_1
, operand_2
)
3962 reserv_sets_t operand_1
;
3963 reserv_sets_t operand_2
;
3967 set_el_t
*cycle_ptr_1
;
3968 set_el_t
*cycle_ptr_2
;
3970 if (operand_1
== NULL
|| operand_2
== NULL
)
3972 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
;
3973 el_ptr_1
< operand_1
+ els_in_reservs
;
3974 el_ptr_1
++, el_ptr_2
++)
3975 if (*el_ptr_1
& *el_ptr_2
)
3977 reserv_sets_or (temp_reserv
, operand_1
, operand_2
);
3978 for (cycle_ptr_1
= operand_1
, cycle_ptr_2
= operand_2
;
3979 cycle_ptr_1
< operand_1
+ els_in_reservs
;
3980 cycle_ptr_1
+= els_in_cycle_reserv
, cycle_ptr_2
+= els_in_cycle_reserv
)
3982 for (el_ptr_1
= cycle_ptr_1
, el_ptr_2
= get_excl_set (cycle_ptr_2
);
3983 el_ptr_1
< cycle_ptr_1
+ els_in_cycle_reserv
;
3984 el_ptr_1
++, el_ptr_2
++)
3985 if (*el_ptr_1
& *el_ptr_2
)
3987 if (!check_presence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3989 if (!check_presence_pattern_sets (temp_reserv
+ (cycle_ptr_2
3993 if (!check_absence_pattern_sets (cycle_ptr_1
, cycle_ptr_2
, FALSE
))
3995 if (!check_absence_pattern_sets (temp_reserv
+ (cycle_ptr_2
- operand_2
),
4002 /* The function sets up RESULT bits by bits of OPERAND shifted on one
4003 cpu cycle. The remaining bits of OPERAND (representing the last
4004 cycle unit reservations) are not chenged. */
4006 reserv_sets_shift (result
, operand
)
4007 reserv_sets_t result
;
4008 reserv_sets_t operand
;
4012 if (result
== NULL
|| operand
== NULL
|| result
== operand
)
4014 for (i
= els_in_cycle_reserv
; i
< els_in_reservs
; i
++)
4015 result
[i
- els_in_cycle_reserv
] = operand
[i
];
4018 /* OR of the reservation sets. */
4020 reserv_sets_or (result
, operand_1
, operand_2
)
4021 reserv_sets_t result
;
4022 reserv_sets_t operand_1
;
4023 reserv_sets_t operand_2
;
4027 set_el_t
*result_set_el_ptr
;
4029 if (result
== NULL
|| operand_1
== NULL
|| operand_2
== NULL
)
4031 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
4032 el_ptr_1
< operand_1
+ els_in_reservs
;
4033 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
4034 *result_set_el_ptr
= *el_ptr_1
| *el_ptr_2
;
4037 /* AND of the reservation sets. */
4039 reserv_sets_and (result
, operand_1
, operand_2
)
4040 reserv_sets_t result
;
4041 reserv_sets_t operand_1
;
4042 reserv_sets_t operand_2
;
4046 set_el_t
*result_set_el_ptr
;
4048 if (result
== NULL
|| operand_1
== NULL
|| operand_2
== NULL
)
4050 for (el_ptr_1
= operand_1
, el_ptr_2
= operand_2
, result_set_el_ptr
= result
;
4051 el_ptr_1
< operand_1
+ els_in_reservs
;
4052 el_ptr_1
++, el_ptr_2
++, result_set_el_ptr
++)
4053 *result_set_el_ptr
= *el_ptr_1
& *el_ptr_2
;
4056 /* The function outputs string representation of units reservation on
4057 cycle START_CYCLE in the reservation set. The function uses repeat
4058 construction if REPETITION_NUM > 1. */
4060 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
)
4062 reserv_sets_t reservs
;
4067 int reserved_units_num
;
4069 reserved_units_num
= 0;
4070 for (unit_num
= 0; unit_num
< description
->units_num
; unit_num
++)
4071 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
4072 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
4073 reserved_units_num
++;
4074 if (repetition_num
<= 0)
4076 if (repetition_num
!= 1 && reserved_units_num
> 1)
4078 reserved_units_num
= 0;
4080 unit_num
< description
->units_num
;
4082 if (TEST_BIT (reservs
, start_cycle
* els_in_cycle_reserv
4083 * sizeof (set_el_t
) * CHAR_BIT
+ unit_num
))
4085 if (reserved_units_num
!= 0)
4087 reserved_units_num
++;
4088 fprintf (f
, "%s", units_array
[unit_num
]->name
);
4090 if (reserved_units_num
== 0)
4091 fprintf (f
, NOTHING_NAME
);
4092 if (repetition_num
<= 0)
4094 if (repetition_num
!= 1 && reserved_units_num
> 1)
4096 if (repetition_num
!= 1)
4097 fprintf (f
, "*%d", repetition_num
);
4100 /* The function outputs string representation of units reservation in
4101 the reservation set. */
4103 output_reserv_sets (f
, reservs
)
4105 reserv_sets_t reservs
;
4107 int start_cycle
= 0;
4112 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
4113 if (repetition_num
== 0)
4116 start_cycle
= cycle
;
4119 ((char *) reservs
+ start_cycle
* els_in_cycle_reserv
4120 * sizeof (set_el_t
),
4121 (char *) reservs
+ cycle
* els_in_cycle_reserv
4122 * sizeof (set_el_t
),
4123 els_in_cycle_reserv
* sizeof (set_el_t
)) == 0)
4127 if (start_cycle
!= 0)
4129 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
4131 start_cycle
= cycle
;
4133 if (start_cycle
< max_cycles_num
)
4135 if (start_cycle
!= 0)
4137 output_cycle_reservs (f
, reservs
, start_cycle
, repetition_num
);
4141 /* The following function returns free node state for AUTOMATON. It
4142 may be new allocated node or node freed earlier. The function also
4143 allocates reservation set if WITH_RESERVS has nonzero value. */
4145 get_free_state (with_reservs
, automaton
)
4147 automaton_t automaton
;
4151 if (max_cycles_num
<= 0 || automaton
== NULL
)
4153 if (VLA_PTR_LENGTH (free_states
) != 0)
4155 result
= VLA_PTR (free_states
, VLA_PTR_LENGTH (free_states
) - 1);
4156 VLA_PTR_SHORTEN (free_states
, 1);
4157 result
->automaton
= automaton
;
4158 result
->first_out_arc
= NULL
;
4159 result
->it_was_placed_in_stack_for_NDFA_forming
= 0;
4160 result
->it_was_placed_in_stack_for_DFA_forming
= 0;
4161 result
->component_states
= NULL
;
4162 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
4167 allocated_states_num
++;
4169 result
= create_node (sizeof (struct state
));
4170 result
->automaton
= automaton
;
4171 result
->first_out_arc
= NULL
;
4172 result
->unique_num
= curr_unique_state_num
;
4173 result
->longest_path_length
= UNDEFINED_LONGEST_PATH_LENGTH
;
4174 curr_unique_state_num
++;
4178 if (result
->reservs
== NULL
)
4179 result
->reservs
= alloc_empty_reserv_sets ();
4181 memset (result
->reservs
, 0, els_in_reservs
* sizeof (set_el_t
));
4186 /* The function frees node STATE. */
4191 free_alt_states (state
->component_states
);
4192 VLA_PTR_ADD (free_states
, state
);
4195 /* Hash value of STATE. If STATE represents deterministic state it is
4196 simply hash value of the corresponding reservation set. Otherwise
4197 it is formed from hash values of the component deterministic
4198 states. One more key is order number of state automaton. */
4203 unsigned int hash_value
;
4204 alt_state_t alt_state
;
4206 if (((state_t
) state
)->component_states
== NULL
)
4207 hash_value
= reserv_sets_hash_value (((state_t
) state
)->reservs
);
4211 for (alt_state
= ((state_t
) state
)->component_states
;
4213 alt_state
= alt_state
->next_sorted_alt_state
)
4214 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4215 | (hash_value
<< CHAR_BIT
))
4216 + alt_state
->state
->unique_num
);
4218 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4219 | (hash_value
<< CHAR_BIT
))
4220 + ((state_t
) state
)->automaton
->automaton_order_num
);
4224 /* Return nonzero value if the states are the same. */
4226 state_eq_p (state_1
, state_2
)
4227 const void *state_1
;
4228 const void *state_2
;
4230 alt_state_t alt_state_1
;
4231 alt_state_t alt_state_2
;
4233 if (((state_t
) state_1
)->automaton
!= ((state_t
) state_2
)->automaton
)
4235 else if (((state_t
) state_1
)->component_states
== NULL
4236 && ((state_t
) state_2
)->component_states
== NULL
)
4237 return reserv_sets_eq (((state_t
) state_1
)->reservs
,
4238 ((state_t
) state_2
)->reservs
);
4239 else if (((state_t
) state_1
)->component_states
!= NULL
4240 && ((state_t
) state_2
)->component_states
!= NULL
)
4242 for (alt_state_1
= ((state_t
) state_1
)->component_states
,
4243 alt_state_2
= ((state_t
) state_2
)->component_states
;
4244 alt_state_1
!= NULL
&& alt_state_2
!= NULL
;
4245 alt_state_1
= alt_state_1
->next_sorted_alt_state
,
4246 alt_state_2
= alt_state_2
->next_sorted_alt_state
)
4247 /* All state in the list must be already in the hash table.
4248 Also the lists must be sorted. */
4249 if (alt_state_1
->state
!= alt_state_2
->state
)
4251 return alt_state_1
== alt_state_2
;
4257 /* Insert STATE into the state table. */
4259 insert_state (state
)
4264 entry_ptr
= htab_find_slot (state_table
, (void *) state
, 1);
4265 if (*entry_ptr
== NULL
)
4266 *entry_ptr
= (void *) state
;
4267 return (state_t
) *entry_ptr
;
4270 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4271 deterministic STATE. */
4273 set_state_reserv (state
, cycle_num
, unit_num
)
4278 set_unit_reserv (state
->reservs
, cycle_num
, unit_num
);
4281 /* Return nonzero value if the deterministic states contains a
4282 reservation of the same cpu unit on the same cpu cycle. */
4284 intersected_state_reservs_p (state1
, state2
)
4288 if (state1
->automaton
!= state2
->automaton
)
4290 return reserv_sets_are_intersected (state1
->reservs
, state2
->reservs
);
4293 /* Return deterministic state (inserted into the table) which
4294 representing the automaton state which is union of reservations of
4295 the deterministic states masked by RESERVS. */
4297 states_union (state1
, state2
, reservs
)
4300 reserv_sets_t reservs
;
4303 state_t state_in_table
;
4305 if (state1
->automaton
!= state2
->automaton
)
4307 result
= get_free_state (1, state1
->automaton
);
4308 reserv_sets_or (result
->reservs
, state1
->reservs
, state2
->reservs
);
4309 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
4310 state_in_table
= insert_state (result
);
4311 if (result
!= state_in_table
)
4313 free_state (result
);
4314 result
= state_in_table
;
4319 /* Return deterministic state (inserted into the table) which
4320 represent the automaton state is obtained from deterministic STATE
4321 by advancing cpu cycle and masking by RESERVS. */
4323 state_shift (state
, reservs
)
4325 reserv_sets_t reservs
;
4328 state_t state_in_table
;
4330 result
= get_free_state (1, state
->automaton
);
4331 reserv_sets_shift (result
->reservs
, state
->reservs
);
4332 reserv_sets_and (result
->reservs
, result
->reservs
, reservs
);
4333 state_in_table
= insert_state (result
);
4334 if (result
!= state_in_table
)
4336 free_state (result
);
4337 result
= state_in_table
;
4342 /* Initialization of the abstract data. */
4349 VLA_PTR_CREATE (units_container
, description
->units_num
, "units_container");
4351 = (description
->decls_num
&& description
->units_num
4352 ? VLA_PTR_BEGIN (units_container
) : NULL
);
4353 for (i
= 0; i
< description
->decls_num
; i
++)
4355 decl
= description
->decls
[i
];
4356 if (decl
->mode
== dm_unit
)
4357 units_array
[DECL_UNIT (decl
)->unit_num
] = DECL_UNIT (decl
);
4359 max_cycles_num
= description
->max_insn_reserv_cycles
;
4361 = ((description
->units_num
+ sizeof (set_el_t
) * CHAR_BIT
- 1)
4362 / (sizeof (set_el_t
) * CHAR_BIT
));
4363 els_in_reservs
= els_in_cycle_reserv
* max_cycles_num
;
4364 curr_unique_state_num
= 0;
4365 initiate_alt_states ();
4366 VLA_PTR_CREATE (free_states
, 1500, "free states");
4367 state_table
= htab_create (1500, state_hash
, state_eq_p
, (htab_del
) 0);
4368 temp_reserv
= alloc_empty_reserv_sets ();
4371 /* Finishing work with the abstract data. */
4375 VLA_PTR_DELETE (units_container
);
4376 htab_delete (state_table
);
4377 VLA_PTR_DELETE (free_states
);
4378 finish_alt_states ();
4383 /* Abstract data `arcs'. */
4385 /* List of free arcs. */
4386 static arc_t first_free_arc
;
4389 /* The following variables is maximal number of allocated nodes
4391 static int allocated_arcs_num
= 0;
4394 /* The function frees node ARC. */
4399 arc
->next_out_arc
= first_free_arc
;
4400 first_free_arc
= arc
;
4403 /* The function removes and frees ARC staring from FROM_STATE. */
4405 remove_arc (from_state
, arc
)
4414 for (prev_arc
= NULL
, curr_arc
= from_state
->first_out_arc
;
4416 prev_arc
= curr_arc
, curr_arc
= curr_arc
->next_out_arc
)
4417 if (curr_arc
== arc
)
4419 if (curr_arc
== NULL
)
4421 if (prev_arc
== NULL
)
4422 from_state
->first_out_arc
= arc
->next_out_arc
;
4424 prev_arc
->next_out_arc
= arc
->next_out_arc
;
4428 /* The functions returns arc with given characteristics (or NULL if
4429 the arc does not exist). */
4431 find_arc (from_state
, to_state
, insn
)
4438 for (arc
= first_out_arc (from_state
); arc
!= NULL
; arc
= next_out_arc (arc
))
4439 if (arc
->to_state
== to_state
&& arc
->insn
== insn
)
4444 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4445 and with given STATE_ALTS. The function returns added arc (or
4446 already existing arc). */
4448 add_arc (from_state
, to_state
, ainsn
, state_alts
)
4456 new_arc
= find_arc (from_state
, to_state
, ainsn
);
4457 if (new_arc
!= NULL
)
4459 if (first_free_arc
== NULL
)
4462 allocated_arcs_num
++;
4464 new_arc
= create_node (sizeof (struct arc
));
4465 new_arc
->to_state
= NULL
;
4466 new_arc
->insn
= NULL
;
4467 new_arc
->next_out_arc
= NULL
;
4471 new_arc
= first_free_arc
;
4472 first_free_arc
= first_free_arc
->next_out_arc
;
4474 new_arc
->to_state
= to_state
;
4475 new_arc
->insn
= ainsn
;
4476 ainsn
->arc_exists_p
= 1;
4477 new_arc
->next_out_arc
= from_state
->first_out_arc
;
4478 from_state
->first_out_arc
= new_arc
;
4479 new_arc
->next_arc_marked_by_insn
= NULL
;
4480 new_arc
->state_alts
= state_alts
;
4484 /* The function returns the first arc starting from STATE. */
4486 first_out_arc (state
)
4489 return state
->first_out_arc
;
4492 /* The function returns next out arc after ARC. */
4497 return arc
->next_out_arc
;
4500 /* Initialization of the abstract data. */
4504 first_free_arc
= NULL
;
4507 /* Finishing work with the abstract data. */
4515 /* Abstract data `automata lists'. */
4517 /* List of free states. */
4518 static automata_list_el_t first_free_automata_list_el
;
4520 /* The list being formed. */
4521 static automata_list_el_t current_automata_list
;
4523 /* Hash table of automata lists. */
4524 static htab_t automata_list_table
;
4526 /* The following function returns free automata list el. It may be
4527 new allocated node or node freed earlier. */
4528 static automata_list_el_t
4529 get_free_automata_list_el ()
4531 automata_list_el_t result
;
4533 if (first_free_automata_list_el
!= NULL
)
4535 result
= first_free_automata_list_el
;
4536 first_free_automata_list_el
4537 = first_free_automata_list_el
->next_automata_list_el
;
4540 result
= create_node (sizeof (struct automata_list_el
));
4541 result
->automaton
= NULL
;
4542 result
->next_automata_list_el
= NULL
;
4546 /* The function frees node AUTOMATA_LIST_EL. */
4548 free_automata_list_el (automata_list_el
)
4549 automata_list_el_t automata_list_el
;
4551 if (automata_list_el
== NULL
)
4553 automata_list_el
->next_automata_list_el
= first_free_automata_list_el
;
4554 first_free_automata_list_el
= automata_list_el
;
4557 /* The function frees list AUTOMATA_LIST. */
4559 free_automata_list (automata_list
)
4560 automata_list_el_t automata_list
;
4562 automata_list_el_t curr_automata_list_el
;
4563 automata_list_el_t next_automata_list_el
;
4565 for (curr_automata_list_el
= automata_list
;
4566 curr_automata_list_el
!= NULL
;
4567 curr_automata_list_el
= next_automata_list_el
)
4569 next_automata_list_el
= curr_automata_list_el
->next_automata_list_el
;
4570 free_automata_list_el (curr_automata_list_el
);
4574 /* Hash value of AUTOMATA_LIST. */
4576 automata_list_hash (automata_list
)
4577 const void *automata_list
;
4579 unsigned int hash_value
;
4580 automata_list_el_t curr_automata_list_el
;
4583 for (curr_automata_list_el
= (automata_list_el_t
) automata_list
;
4584 curr_automata_list_el
!= NULL
;
4585 curr_automata_list_el
= curr_automata_list_el
->next_automata_list_el
)
4586 hash_value
= (((hash_value
>> (sizeof (unsigned) - 1) * CHAR_BIT
)
4587 | (hash_value
<< CHAR_BIT
))
4588 + curr_automata_list_el
->automaton
->automaton_order_num
);
4592 /* Return nonzero value if the automata_lists are the same. */
4594 automata_list_eq_p (automata_list_1
, automata_list_2
)
4595 const void *automata_list_1
;
4596 const void *automata_list_2
;
4598 automata_list_el_t automata_list_el_1
;
4599 automata_list_el_t automata_list_el_2
;
4601 for (automata_list_el_1
= (automata_list_el_t
) automata_list_1
,
4602 automata_list_el_2
= (automata_list_el_t
) automata_list_2
;
4603 automata_list_el_1
!= NULL
&& automata_list_el_2
!= NULL
;
4604 automata_list_el_1
= automata_list_el_1
->next_automata_list_el
,
4605 automata_list_el_2
= automata_list_el_2
->next_automata_list_el
)
4606 if (automata_list_el_1
->automaton
!= automata_list_el_2
->automaton
)
4608 return automata_list_el_1
== automata_list_el_2
;
4611 /* Initialization of the abstract data. */
4613 initiate_automata_lists ()
4615 first_free_automata_list_el
= NULL
;
4616 automata_list_table
= htab_create (1500, automata_list_hash
,
4617 automata_list_eq_p
, (htab_del
) 0);
4620 /* The following function starts new automata list and makes it the
4623 automata_list_start ()
4625 current_automata_list
= NULL
;
4628 /* The following function adds AUTOMATON to the current list. */
4630 automata_list_add (automaton
)
4631 automaton_t automaton
;
4633 automata_list_el_t el
;
4635 el
= get_free_automata_list_el ();
4636 el
->automaton
= automaton
;
4637 el
->next_automata_list_el
= current_automata_list
;
4638 current_automata_list
= el
;
4641 /* The following function finishes forming the current list, inserts
4642 it into the table and returns it. */
4643 static automata_list_el_t
4644 automata_list_finish ()
4648 if (current_automata_list
== NULL
)
4650 entry_ptr
= htab_find_slot (automata_list_table
,
4651 (void *) current_automata_list
, 1);
4652 if (*entry_ptr
== NULL
)
4653 *entry_ptr
= (void *) current_automata_list
;
4655 free_automata_list (current_automata_list
);
4656 current_automata_list
= NULL
;
4657 return (automata_list_el_t
) *entry_ptr
;
4660 /* Finishing work with the abstract data. */
4662 finish_automata_lists ()
4664 htab_delete (automata_list_table
);
4669 /* The page contains abstract data for work with exclusion sets (see
4670 exclusion_set in file rtl.def). */
4672 /* The following variable refers to an exclusion set returned by
4673 get_excl_set. This is bit string of length equal to cpu units
4674 number. If exclusion set for given unit contains 1 for a unit,
4675 then simultaneous reservation of the units is prohibited. */
4676 static reserv_sets_t excl_set
;
4678 /* The array contains exclusion sets for each unit. */
4679 static reserv_sets_t
*unit_excl_set_table
;
4681 /* The following function forms the array containing exclusion sets
4684 initiate_excl_sets ()
4687 reserv_sets_t unit_excl_set
;
4691 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4692 excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4693 obstack_finish (&irp
);
4694 obstack_blank (&irp
, description
->units_num
* sizeof (reserv_sets_t
));
4695 unit_excl_set_table
= (reserv_sets_t
*) obstack_base (&irp
);
4696 obstack_finish (&irp
);
4697 /* Evaluate unit exclusion sets. */
4698 for (i
= 0; i
< description
->decls_num
; i
++)
4700 decl
= description
->decls
[i
];
4701 if (decl
->mode
== dm_unit
)
4703 obstack_blank (&irp
, els_in_cycle_reserv
* sizeof (set_el_t
));
4704 unit_excl_set
= (reserv_sets_t
) obstack_base (&irp
);
4705 obstack_finish (&irp
);
4706 memset (unit_excl_set
, 0, els_in_cycle_reserv
* sizeof (set_el_t
));
4707 for (el
= DECL_UNIT (decl
)->excl_list
;
4709 el
= el
->next_unit_set_el
)
4711 SET_BIT (unit_excl_set
, el
->unit_decl
->unit_num
);
4712 el
->unit_decl
->in_set_p
= TRUE
;
4714 unit_excl_set_table
[DECL_UNIT (decl
)->unit_num
] = unit_excl_set
;
4719 /* The function sets up and return EXCL_SET which is union of
4720 exclusion sets for each unit in IN_SET. */
4721 static reserv_sets_t
4722 get_excl_set (in_set
)
4723 reserv_sets_t in_set
;
4731 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4732 memset (excl_set
, 0, chars_num
);
4733 for (excl_char_num
= 0; excl_char_num
< chars_num
; excl_char_num
++)
4734 if (((unsigned char *) in_set
) [excl_char_num
])
4735 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4736 if ((((unsigned char *) in_set
) [excl_char_num
] >> i
) & 1)
4738 start_unit_num
= excl_char_num
* CHAR_BIT
+ i
;
4739 if (start_unit_num
>= description
->units_num
)
4741 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4744 |= unit_excl_set_table
[start_unit_num
] [unit_num
];
4752 /* The page contains abstract data for work with presence/absence
4753 pattern sets (see presence_set/absence_set in file rtl.def). */
4755 /* The following arrays contain correspondingly presence, final
4756 presence, absence, and final absence patterns for each unit. */
4757 static pattern_reserv_t
*unit_presence_set_table
;
4758 static pattern_reserv_t
*unit_final_presence_set_table
;
4759 static pattern_reserv_t
*unit_absence_set_table
;
4760 static pattern_reserv_t
*unit_final_absence_set_table
;
4762 /* The following function forms list of reservation sets for given
4764 static pattern_reserv_t
4765 form_reserv_sets_list (pattern_list
)
4766 pattern_set_el_t pattern_list
;
4768 pattern_set_el_t el
;
4769 pattern_reserv_t first
, curr
, prev
;
4772 prev
= first
= NULL
;
4773 for (el
= pattern_list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
4775 curr
= create_node (sizeof (struct pattern_reserv
));
4776 curr
->reserv
= alloc_empty_reserv_sets ();
4777 curr
->next_pattern_reserv
= NULL
;
4778 for (i
= 0; i
< el
->units_num
; i
++)
4780 SET_BIT (curr
->reserv
, el
->unit_decls
[i
]->unit_num
);
4781 el
->unit_decls
[i
]->in_set_p
= TRUE
;
4784 prev
->next_pattern_reserv
= curr
;
4792 /* The following function forms the array containing presence and
4793 absence pattern sets for each unit. */
4795 initiate_presence_absence_pattern_sets ()
4800 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4801 unit_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4802 obstack_finish (&irp
);
4803 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4804 unit_final_presence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4805 obstack_finish (&irp
);
4806 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4807 unit_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4808 obstack_finish (&irp
);
4809 obstack_blank (&irp
, description
->units_num
* sizeof (pattern_reserv_t
));
4810 unit_final_absence_set_table
= (pattern_reserv_t
*) obstack_base (&irp
);
4811 obstack_finish (&irp
);
4812 /* Evaluate unit presence/absence sets. */
4813 for (i
= 0; i
< description
->decls_num
; i
++)
4815 decl
= description
->decls
[i
];
4816 if (decl
->mode
== dm_unit
)
4818 unit_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4819 = form_reserv_sets_list (DECL_UNIT (decl
)->presence_list
);
4820 unit_final_presence_set_table
[DECL_UNIT (decl
)->unit_num
]
4821 = form_reserv_sets_list (DECL_UNIT (decl
)->final_presence_list
);
4822 unit_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4823 = form_reserv_sets_list (DECL_UNIT (decl
)->absence_list
);
4824 unit_final_absence_set_table
[DECL_UNIT (decl
)->unit_num
]
4825 = form_reserv_sets_list (DECL_UNIT (decl
)->final_absence_list
);
4830 /* The function checks that CHECKED_SET satisfies all presence pattern
4831 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4834 check_presence_pattern_sets (checked_set
, origional_set
, final_p
)
4835 reserv_sets_t checked_set
, origional_set
;
4844 pattern_reserv_t pat_reserv
;
4846 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4847 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4848 if (((unsigned char *) origional_set
) [char_num
])
4849 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4850 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4852 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4853 if (start_unit_num
>= description
->units_num
)
4856 && unit_final_presence_set_table
[start_unit_num
] == NULL
)
4858 && unit_presence_set_table
[start_unit_num
] == NULL
))
4861 for (pat_reserv
= (final_p
4862 ? unit_final_presence_set_table
[start_unit_num
]
4863 : unit_presence_set_table
[start_unit_num
]);
4865 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4867 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4868 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4869 != pat_reserv
->reserv
[unit_num
])
4871 presence_p
= presence_p
|| unit_num
>= els_in_cycle_reserv
;
4879 /* The function checks that CHECKED_SET satisfies all absence pattern
4880 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4883 check_absence_pattern_sets (checked_set
, origional_set
, final_p
)
4884 reserv_sets_t checked_set
, origional_set
;
4892 pattern_reserv_t pat_reserv
;
4894 chars_num
= els_in_cycle_reserv
* sizeof (set_el_t
);
4895 for (char_num
= 0; char_num
< chars_num
; char_num
++)
4896 if (((unsigned char *) origional_set
) [char_num
])
4897 for (i
= CHAR_BIT
- 1; i
>= 0; i
--)
4898 if ((((unsigned char *) origional_set
) [char_num
] >> i
) & 1)
4900 start_unit_num
= char_num
* CHAR_BIT
+ i
;
4901 if (start_unit_num
>= description
->units_num
)
4903 for (pat_reserv
= (final_p
4904 ? unit_final_absence_set_table
[start_unit_num
]
4905 : unit_absence_set_table
[start_unit_num
]);
4907 pat_reserv
= pat_reserv
->next_pattern_reserv
)
4909 for (unit_num
= 0; unit_num
< els_in_cycle_reserv
; unit_num
++)
4910 if ((checked_set
[unit_num
] & pat_reserv
->reserv
[unit_num
])
4911 != pat_reserv
->reserv
[unit_num
]
4912 && pat_reserv
->reserv
[unit_num
])
4914 if (unit_num
>= els_in_cycle_reserv
)
4923 /* This page contains code for transformation of original reservations
4924 described in .md file. The main goal of transformations is
4925 simplifying reservation and lifting up all `|' on the top of IR
4926 reservation representation. */
4929 /* The following function makes copy of IR representation of
4930 reservation. The function also substitutes all reservations
4931 defined by define_reservation by corresponding value during making
4934 copy_insn_regexp (regexp
)
4940 if (regexp
->mode
== rm_reserv
)
4941 result
= copy_insn_regexp (REGEXP_RESERV (regexp
)->reserv_decl
->regexp
);
4942 else if (regexp
->mode
== rm_unit
)
4943 result
= copy_node (regexp
, sizeof (struct regexp
));
4944 else if (regexp
->mode
== rm_repeat
)
4946 result
= copy_node (regexp
, sizeof (struct regexp
));
4947 REGEXP_REPEAT (result
)->regexp
4948 = copy_insn_regexp (REGEXP_REPEAT (regexp
)->regexp
);
4950 else if (regexp
->mode
== rm_sequence
)
4952 result
= copy_node (regexp
,
4953 sizeof (struct regexp
) + sizeof (regexp_t
)
4954 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
4955 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
4956 REGEXP_SEQUENCE (result
)->regexps
[i
]
4957 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
4959 else if (regexp
->mode
== rm_allof
)
4961 result
= copy_node (regexp
,
4962 sizeof (struct regexp
) + sizeof (regexp_t
)
4963 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
4964 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
4965 REGEXP_ALLOF (result
)->regexps
[i
]
4966 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
4968 else if (regexp
->mode
== rm_oneof
)
4970 result
= copy_node (regexp
,
4971 sizeof (struct regexp
) + sizeof (regexp_t
)
4972 * (REGEXP_ONEOF (regexp
)->regexps_num
- 1));
4973 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
4974 REGEXP_ONEOF (result
)->regexps
[i
]
4975 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
4979 if (regexp
->mode
!= rm_nothing
)
4981 result
= copy_node (regexp
, sizeof (struct regexp
));
4986 /* The following variable is set up 1 if a transformation has been
4988 static int regexp_transformed_p
;
4990 /* The function makes transformation
4993 transform_1 (regexp
)
5001 if (regexp
->mode
== rm_repeat
)
5003 repeat_num
= REGEXP_REPEAT (regexp
)->repeat_num
;
5004 if (repeat_num
<= 1)
5006 operand
= REGEXP_REPEAT (regexp
)->regexp
;
5008 regexp
= create_node (sizeof (struct regexp
) + sizeof (regexp_t
)
5009 * (repeat_num
- 1));
5010 regexp
->mode
= rm_sequence
;
5012 REGEXP_SEQUENCE (regexp
)->regexps_num
= repeat_num
;
5013 for (i
= 0; i
< repeat_num
; i
++)
5014 REGEXP_SEQUENCE (regexp
)->regexps
[i
] = copy_insn_regexp (operand
);
5015 regexp_transformed_p
= 1;
5020 /* The function makes transformations
5021 ...,(A,B,...),C,... -> ...,A,B,...,C,...
5022 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
5023 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
5025 transform_2 (regexp
)
5028 if (regexp
->mode
== rm_sequence
)
5030 regexp_t sequence
= NULL
;
5032 int sequence_index
= 0;
5035 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5036 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_sequence
)
5039 sequence
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
5042 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
5044 if ( REGEXP_SEQUENCE (sequence
)->regexps_num
<= 1
5045 || REGEXP_SEQUENCE (regexp
)->regexps_num
<= 1)
5047 result
= create_node (sizeof (struct regexp
)
5049 * (REGEXP_SEQUENCE (regexp
)->regexps_num
5050 + REGEXP_SEQUENCE (sequence
)->regexps_num
5052 result
->mode
= rm_sequence
;
5053 result
->pos
= regexp
->pos
;
5054 REGEXP_SEQUENCE (result
)->regexps_num
5055 = (REGEXP_SEQUENCE (regexp
)->regexps_num
5056 + REGEXP_SEQUENCE (sequence
)->regexps_num
- 1);
5057 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5058 if (i
< sequence_index
)
5059 REGEXP_SEQUENCE (result
)->regexps
[i
]
5060 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
5061 else if (i
> sequence_index
)
5062 REGEXP_SEQUENCE (result
)->regexps
5063 [i
+ REGEXP_SEQUENCE (sequence
)->regexps_num
- 1]
5064 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
5066 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
5067 REGEXP_SEQUENCE (result
)->regexps
[i
+ j
]
5068 = copy_insn_regexp (REGEXP_SEQUENCE (sequence
)->regexps
[j
]);
5069 regexp_transformed_p
= 1;
5073 else if (regexp
->mode
== rm_allof
)
5075 regexp_t allof
= NULL
;
5077 int allof_index
= 0;
5080 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5081 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_allof
)
5084 allof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
5087 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
5089 if (REGEXP_ALLOF (allof
)->regexps_num
<= 1
5090 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
5092 result
= create_node (sizeof (struct regexp
)
5094 * (REGEXP_ALLOF (regexp
)->regexps_num
5095 + REGEXP_ALLOF (allof
)->regexps_num
- 2));
5096 result
->mode
= rm_allof
;
5097 result
->pos
= regexp
->pos
;
5098 REGEXP_ALLOF (result
)->regexps_num
5099 = (REGEXP_ALLOF (regexp
)->regexps_num
5100 + REGEXP_ALLOF (allof
)->regexps_num
- 1);
5101 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5102 if (i
< allof_index
)
5103 REGEXP_ALLOF (result
)->regexps
[i
]
5104 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
5105 else if (i
> allof_index
)
5106 REGEXP_ALLOF (result
)->regexps
5107 [i
+ REGEXP_ALLOF (allof
)->regexps_num
- 1]
5108 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
5110 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
5111 REGEXP_ALLOF (result
)->regexps
[i
+ j
]
5112 = copy_insn_regexp (REGEXP_ALLOF (allof
)->regexps
[j
]);
5113 regexp_transformed_p
= 1;
5117 else if (regexp
->mode
== rm_oneof
)
5119 regexp_t oneof
= NULL
;
5121 int oneof_index
= 0;
5124 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
5125 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
5128 oneof
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5131 if (i
< REGEXP_ONEOF (regexp
)->regexps_num
)
5133 if (REGEXP_ONEOF (oneof
)->regexps_num
<= 1
5134 || REGEXP_ONEOF (regexp
)->regexps_num
<= 1)
5136 result
= create_node (sizeof (struct regexp
)
5138 * (REGEXP_ONEOF (regexp
)->regexps_num
5139 + REGEXP_ONEOF (oneof
)->regexps_num
- 2));
5140 result
->mode
= rm_oneof
;
5141 result
->pos
= regexp
->pos
;
5142 REGEXP_ONEOF (result
)->regexps_num
5143 = (REGEXP_ONEOF (regexp
)->regexps_num
5144 + REGEXP_ONEOF (oneof
)->regexps_num
- 1);
5145 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
5146 if (i
< oneof_index
)
5147 REGEXP_ONEOF (result
)->regexps
[i
]
5148 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
5149 else if (i
> oneof_index
)
5150 REGEXP_ONEOF (result
)->regexps
5151 [i
+ REGEXP_ONEOF (oneof
)->regexps_num
- 1]
5152 = copy_insn_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
5154 for (j
= 0; j
< REGEXP_ONEOF (oneof
)->regexps_num
; j
++)
5155 REGEXP_ONEOF (result
)->regexps
[i
+ j
]
5156 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[j
]);
5157 regexp_transformed_p
= 1;
5164 /* The function makes transformations
5165 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
5166 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
5167 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
5168 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
5170 transform_3 (regexp
)
5173 if (regexp
->mode
== rm_sequence
)
5175 regexp_t oneof
= NULL
;
5176 int oneof_index
= 0;
5181 for (i
= 0; i
<REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5182 if (REGEXP_SEQUENCE (regexp
)->regexps
[i
]->mode
== rm_oneof
)
5185 oneof
= REGEXP_SEQUENCE (regexp
)->regexps
[i
];
5188 if (i
< REGEXP_SEQUENCE (regexp
)->regexps_num
)
5190 if (REGEXP_ONEOF (oneof
)->regexps_num
<= 1
5191 || REGEXP_SEQUENCE (regexp
)->regexps_num
<= 1)
5193 result
= create_node (sizeof (struct regexp
)
5195 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
5196 result
->mode
= rm_oneof
;
5197 result
->pos
= regexp
->pos
;
5198 REGEXP_ONEOF (result
)->regexps_num
5199 = REGEXP_ONEOF (oneof
)->regexps_num
;
5200 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
5203 = create_node (sizeof (struct regexp
)
5205 * (REGEXP_SEQUENCE (regexp
)->regexps_num
- 1));
5206 sequence
->mode
= rm_sequence
;
5207 sequence
->pos
= regexp
->pos
;
5208 REGEXP_SEQUENCE (sequence
)->regexps_num
5209 = REGEXP_SEQUENCE (regexp
)->regexps_num
;
5210 REGEXP_ONEOF (result
)->regexps
[i
] = sequence
;
5211 for (j
= 0; j
< REGEXP_SEQUENCE (sequence
)->regexps_num
; j
++)
5212 if (j
!= oneof_index
)
5213 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
5214 = copy_insn_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[j
]);
5216 REGEXP_SEQUENCE (sequence
)->regexps
[j
]
5217 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
5219 regexp_transformed_p
= 1;
5223 else if (regexp
->mode
== rm_allof
)
5225 regexp_t oneof
= NULL
;
5227 int oneof_index
= 0;
5228 int max_seq_length
, allof_length
;
5230 regexp_t allof
= NULL
;
5231 regexp_t allof_op
= NULL
;
5234 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5235 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
5238 oneof
= REGEXP_ALLOF (regexp
)->regexps
[i
];
5241 if (i
< REGEXP_ALLOF (regexp
)->regexps_num
)
5243 if (REGEXP_ONEOF (oneof
)->regexps_num
<= 1
5244 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
5246 result
= create_node (sizeof (struct regexp
)
5248 * (REGEXP_ONEOF (oneof
)->regexps_num
- 1));
5249 result
->mode
= rm_oneof
;
5250 result
->pos
= regexp
->pos
;
5251 REGEXP_ONEOF (result
)->regexps_num
5252 = REGEXP_ONEOF (oneof
)->regexps_num
;
5253 for (i
= 0; i
< REGEXP_ONEOF (result
)->regexps_num
; i
++)
5256 = create_node (sizeof (struct regexp
)
5258 * (REGEXP_ALLOF (regexp
)->regexps_num
- 1));
5259 allof
->mode
= rm_allof
;
5260 allof
->pos
= regexp
->pos
;
5261 REGEXP_ALLOF (allof
)->regexps_num
5262 = REGEXP_ALLOF (regexp
)->regexps_num
;
5263 REGEXP_ONEOF (result
)->regexps
[i
] = allof
;
5264 for (j
= 0; j
< REGEXP_ALLOF (allof
)->regexps_num
; j
++)
5265 if (j
!= oneof_index
)
5266 REGEXP_ALLOF (allof
)->regexps
[j
]
5267 = copy_insn_regexp (REGEXP_ALLOF (regexp
)->regexps
[j
]);
5269 REGEXP_ALLOF (allof
)->regexps
[j
]
5270 = copy_insn_regexp (REGEXP_ONEOF (oneof
)->regexps
[i
]);
5272 regexp_transformed_p
= 1;
5276 if (regexp
->mode
== rm_allof
)
5277 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5278 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
5280 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
5281 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
5282 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
5284 else if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
!= rm_unit
5285 && REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
!= rm_nothing
)
5290 if (max_seq_length
!= 0)
5292 if (max_seq_length
== 1 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
5294 result
= create_node (sizeof (struct regexp
)
5295 + sizeof (regexp_t
) * (max_seq_length
- 1));
5296 result
->mode
= rm_sequence
;
5297 result
->pos
= regexp
->pos
;
5298 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
5299 for (i
= 0; i
< max_seq_length
; i
++)
5302 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
5303 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
5304 && (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5305 ->regexps
[j
])->regexps_num
)))
5308 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)->regexps
[j
])
5313 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5315 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5318 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
5321 if (allof_length
== 1)
5322 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
5325 allof
= create_node (sizeof (struct regexp
)
5327 * (allof_length
- 1));
5328 allof
->mode
= rm_allof
;
5329 allof
->pos
= regexp
->pos
;
5330 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
5331 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
5333 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
5334 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
5336 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5337 ->regexps
[j
])->regexps_num
)))
5339 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5342 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
5347 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5349 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5352 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
5353 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
5359 regexp_transformed_p
= 1;
5366 /* The function traverses IR of reservation and applies transformations
5367 implemented by FUNC. */
5369 regexp_transform_func (regexp
, func
)
5371 regexp_t (*func
) PARAMS ((regexp_t regexp
));
5375 if (regexp
->mode
== rm_sequence
)
5376 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5377 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
5378 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
], func
);
5379 else if (regexp
->mode
== rm_allof
)
5380 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5381 REGEXP_ALLOF (regexp
)->regexps
[i
]
5382 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
5383 else if (regexp
->mode
== rm_oneof
)
5384 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
5385 REGEXP_ONEOF (regexp
)->regexps
[i
]
5386 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
5387 else if (regexp
->mode
== rm_repeat
)
5388 REGEXP_REPEAT (regexp
)->regexp
5389 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
5390 else if (regexp
->mode
!= rm_nothing
&& regexp
->mode
!= rm_unit
)
5392 return (*func
) (regexp
);
5395 /* The function applies all transformations for IR representation of
5396 reservation REGEXP. */
5398 transform_regexp (regexp
)
5401 regexp
= regexp_transform_func (regexp
, transform_1
);
5404 regexp_transformed_p
= 0;
5405 regexp
= regexp_transform_func (regexp
, transform_2
);
5406 regexp
= regexp_transform_func (regexp
, transform_3
);
5408 while (regexp_transformed_p
);
5412 /* The function applys all transformations for reservations of all
5413 insn declarations. */
5415 transform_insn_regexps ()
5420 transform_time
= create_ticker ();
5421 add_advance_cycle_insn_decl ();
5422 fprintf (stderr
, "Reservation transformation...");
5424 for (i
= 0; i
< description
->decls_num
; i
++)
5426 decl
= description
->decls
[i
];
5427 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
5428 DECL_INSN_RESERV (decl
)->transformed_regexp
5429 = transform_regexp (copy_insn_regexp
5430 (DECL_INSN_RESERV (decl
)->regexp
));
5432 fprintf (stderr
, "done\n");
5433 ticker_off (&transform_time
);
5439 /* The following variable value is TRUE if the first annotated message
5440 about units to automata distribution has been output. */
5441 static int annotation_message_reported_p
;
5443 /* The function processes all alternative reservations on CYCLE in
5444 given REGEXP of insn reservation with INSN_RESERV_NAME to check the
5445 UNIT (or another unit from the same automaton) is not reserved on
5446 the all alternatives. If it is true, the function outputs message
5447 about the rule violation. */
5449 check_unit_distribution_in_reserv (insn_reserv_name
, unit
, regexp
, cycle
)
5450 const char *insn_reserv_name
;
5456 regexp_t seq
, allof
;
5457 unit_decl_t unit_decl
;
5459 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5461 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
5462 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5464 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5465 if (seq
->mode
== rm_sequence
)
5467 if (cycle
>= REGEXP_SEQUENCE (seq
)->regexps_num
)
5469 allof
= REGEXP_SEQUENCE (seq
)->regexps
[cycle
];
5470 if (allof
->mode
== rm_allof
)
5472 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5473 if (REGEXP_ALLOF (allof
)->regexps
[k
]->mode
== rm_unit
5474 && (REGEXP_UNIT (REGEXP_ALLOF (allof
)->regexps
[k
])
5475 ->unit_decl
->automaton_decl
5476 == unit_decl
->automaton_decl
))
5478 if (k
>= REGEXP_ALLOF (allof
)->regexps_num
)
5481 else if (allof
->mode
== rm_unit
5482 && (REGEXP_UNIT (allof
)->unit_decl
->automaton_decl
5483 != unit_decl
->automaton_decl
))
5486 else if (cycle
!= 0)
5488 else if (seq
->mode
== rm_allof
)
5490 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5491 if (REGEXP_ALLOF (seq
)->regexps
[k
]->mode
== rm_unit
5492 && (REGEXP_UNIT (REGEXP_ALLOF (seq
)->regexps
[k
])
5493 ->unit_decl
->automaton_decl
== unit_decl
->automaton_decl
))
5495 if (k
>= REGEXP_ALLOF (seq
)->regexps_num
)
5498 else if (seq
->mode
== rm_unit
5499 && (REGEXP_UNIT (seq
)->unit_decl
->automaton_decl
5500 != unit_decl
->automaton_decl
))
5505 if (!annotation_message_reported_p
)
5507 fprintf (stderr
, "\n");
5508 error ("The following units do not satisfy units-automata distribution rule");
5509 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5510 annotation_message_reported_p
= TRUE
;
5512 error ("Unit %s, reserv. %s, cycle %d",
5513 unit_decl
->name
, insn_reserv_name
, cycle
);
5517 /* The function processes given REGEXP to find units with the wrong
5520 check_regexp_units_distribution (insn_reserv_name
, regexp
)
5521 const char *insn_reserv_name
;
5525 regexp_t seq
, allof
, unit
;
5527 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5529 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5531 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5532 if (seq
->mode
== rm_sequence
)
5533 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
5535 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
5536 if (allof
->mode
== rm_allof
)
5537 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5539 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
5540 if (unit
->mode
== rm_unit
)
5541 check_unit_distribution_in_reserv (insn_reserv_name
, unit
,
5543 else if (unit
->mode
!= rm_nothing
)
5546 else if (allof
->mode
== rm_unit
)
5547 check_unit_distribution_in_reserv (insn_reserv_name
, allof
,
5549 else if (allof
->mode
!= rm_nothing
)
5552 else if (seq
->mode
== rm_allof
)
5553 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5555 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5556 if (unit
->mode
== rm_unit
)
5557 check_unit_distribution_in_reserv (insn_reserv_name
, unit
,
5559 else if (unit
->mode
!= rm_nothing
)
5562 else if (seq
->mode
== rm_unit
)
5563 check_unit_distribution_in_reserv (insn_reserv_name
, seq
, regexp
, 0);
5564 else if (seq
->mode
!= rm_nothing
)
5569 /* The function finds units which violates units to automata
5570 distribution rule. If the units exist, report about them. */
5572 check_unit_distributions_to_automata ()
5577 fprintf (stderr
, "Check unit distributions to automata...");
5578 annotation_message_reported_p
= FALSE
;
5579 for (i
= 0; i
< description
->decls_num
; i
++)
5581 decl
= description
->decls
[i
];
5582 if (decl
->mode
== dm_insn_reserv
)
5583 check_regexp_units_distribution
5584 (DECL_INSN_RESERV (decl
)->name
,
5585 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5587 fprintf (stderr
, "done\n");
5592 /* The page contains code for building alt_states (see comments for
5593 IR) describing all possible insns reservations of an automaton. */
5595 /* Current state being formed for which the current alt_state
5597 static state_t state_being_formed
;
5599 /* Current alt_state being formed. */
5600 static alt_state_t alt_state_being_formed
;
5602 /* This recursive function processes `,' and units in reservation
5603 REGEXP for forming alt_states of AUTOMATON. It is believed that
5604 CURR_CYCLE is start cycle of all reservation REGEXP. */
5606 process_seq_for_forming_states (regexp
, automaton
, curr_cycle
)
5608 automaton_t automaton
;
5615 else if (regexp
->mode
== rm_unit
)
5617 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5618 == automaton
->automaton_order_num
)
5619 set_state_reserv (state_being_formed
, curr_cycle
,
5620 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5623 else if (regexp
->mode
== rm_sequence
)
5625 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5627 = process_seq_for_forming_states
5628 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5631 else if (regexp
->mode
== rm_allof
)
5633 int finish_cycle
= 0;
5636 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5638 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5640 automaton
, curr_cycle
);
5641 if (finish_cycle
< cycle
)
5642 finish_cycle
= cycle
;
5644 return finish_cycle
;
5648 if (regexp
->mode
!= rm_nothing
)
5654 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5655 inserts alt_state into the table. */
5657 finish_forming_alt_state (alt_state
, automaton
)
5658 alt_state_t alt_state
;
5659 automaton_t automaton ATTRIBUTE_UNUSED
;
5661 state_t state_in_table
;
5662 state_t corresponding_state
;
5664 corresponding_state
= alt_state
->state
;
5665 state_in_table
= insert_state (corresponding_state
);
5666 if (state_in_table
!= corresponding_state
)
5668 free_state (corresponding_state
);
5669 alt_state
->state
= state_in_table
;
5673 /* The following variable value is current automaton insn for whose
5674 reservation the alt states are created. */
5675 static ainsn_t curr_ainsn
;
5677 /* This recursive function processes `|' in reservation REGEXP for
5678 forming alt_states of AUTOMATON. List of the alt states should
5679 have the same order as in the description. */
5681 process_alts_for_forming_states (regexp
, automaton
, inside_oneof_p
)
5683 automaton_t automaton
;
5688 if (regexp
->mode
!= rm_oneof
)
5690 alt_state_being_formed
= get_free_alt_state ();
5691 state_being_formed
= get_free_state (1, automaton
);
5692 alt_state_being_formed
->state
= state_being_formed
;
5693 /* We inserts in reverse order but we process alternatives also
5694 in reverse order. So we have the same order of alternative
5695 as in the description. */
5696 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5697 curr_ainsn
->alt_states
= alt_state_being_formed
;
5698 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5699 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5705 /* We processes it in reverse order to get list with the same
5706 order as in the description. See also the previous
5708 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5709 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5714 /* Create nodes alt_state for all AUTOMATON insns. */
5716 create_alt_states (automaton
)
5717 automaton_t automaton
;
5719 struct insn_reserv_decl
*reserv_decl
;
5721 for (curr_ainsn
= automaton
->ainsn_list
;
5723 curr_ainsn
= curr_ainsn
->next_ainsn
)
5725 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5726 if (reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5728 curr_ainsn
->alt_states
= NULL
;
5729 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5731 curr_ainsn
->sorted_alt_states
5732 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5739 /* The page contains major code for building DFA(s) for fast pipeline
5740 hazards recognition. */
5742 /* The function forms list of ainsns of AUTOMATON with the same
5745 form_ainsn_with_same_reservs (automaton
)
5746 automaton_t automaton
;
5750 vla_ptr_t first_insns
;
5751 vla_ptr_t last_insns
;
5753 VLA_PTR_CREATE (first_insns
, 150, "first insns with the same reservs");
5754 VLA_PTR_CREATE (last_insns
, 150, "last insns with the same reservs");
5755 for (curr_ainsn
= automaton
->ainsn_list
;
5757 curr_ainsn
= curr_ainsn
->next_ainsn
)
5758 if (curr_ainsn
->insn_reserv_decl
5759 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5761 curr_ainsn
->next_same_reservs_insn
= NULL
;
5762 curr_ainsn
->first_insn_with_same_reservs
= 1;
5766 for (i
= 0; i
< VLA_PTR_LENGTH (first_insns
); i
++)
5768 (curr_ainsn
->sorted_alt_states
,
5769 ((ainsn_t
) VLA_PTR (first_insns
, i
))->sorted_alt_states
))
5771 curr_ainsn
->next_same_reservs_insn
= NULL
;
5772 if (i
< VLA_PTR_LENGTH (first_insns
))
5774 curr_ainsn
->first_insn_with_same_reservs
= 0;
5775 ((ainsn_t
) VLA_PTR (last_insns
, i
))->next_same_reservs_insn
5777 VLA_PTR (last_insns
, i
) = curr_ainsn
;
5781 VLA_PTR_ADD (first_insns
, curr_ainsn
);
5782 VLA_PTR_ADD (last_insns
, curr_ainsn
);
5783 curr_ainsn
->first_insn_with_same_reservs
= 1;
5786 VLA_PTR_DELETE (first_insns
);
5787 VLA_PTR_DELETE (last_insns
);
5790 /* Forming unit reservations which can affect creating the automaton
5791 states achieved from a given state. It permits to build smaller
5792 automata in many cases. We would have the same automata after
5793 the minimization without such optimization, but the automaton
5794 right after the building could be huge. So in other words, usage
5795 of reservs_matter means some minimization during building the
5797 static reserv_sets_t
5798 form_reservs_matter (automaton
)
5799 automaton_t automaton
;
5802 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5804 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5805 for (unit
= 0; unit
< description
->units_num
; unit
++)
5806 if (units_array
[unit
]->automaton_decl
5807 == automaton
->corresponding_automaton_decl
5808 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5809 /* We can not remove queried unit from reservations. */
5810 || units_array
[unit
]->query_p
5811 /* We can not remove units which are used
5812 `exclusion_set', `presence_set',
5813 `final_presence_set', `absence_set', and
5814 `final_absence_set'. */
5815 || units_array
[unit
]->in_set_p
))
5816 set_unit_reserv (reservs_matter
, cycle
, unit
);
5817 return reservs_matter
;
5820 /* The following function creates all states of nondeterministic (if
5821 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5823 make_automaton (automaton
)
5824 automaton_t automaton
;
5827 struct insn_reserv_decl
*insn_reserv_decl
;
5828 alt_state_t alt_state
;
5830 state_t start_state
;
5832 ainsn_t advance_cycle_ainsn
;
5834 vla_ptr_t state_stack
;
5836 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5838 VLA_PTR_CREATE (state_stack
, 150, "state stack");
5839 /* Create the start state (empty state). */
5840 start_state
= insert_state (get_free_state (1, automaton
));
5841 automaton
->start_state
= start_state
;
5842 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5843 VLA_PTR_ADD (state_stack
, start_state
);
5845 while (VLA_PTR_LENGTH (state_stack
) != 0)
5847 state
= VLA_PTR (state_stack
, VLA_PTR_LENGTH (state_stack
) - 1);
5848 VLA_PTR_SHORTEN (state_stack
, 1);
5849 advance_cycle_ainsn
= NULL
;
5850 for (ainsn
= automaton
->ainsn_list
;
5852 ainsn
= ainsn
->next_ainsn
)
5853 if (ainsn
->first_insn_with_same_reservs
)
5855 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5856 if (insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5858 /* We process alt_states in the same order as they are
5859 present in the description. */
5861 for (alt_state
= ainsn
->alt_states
;
5863 alt_state
= alt_state
->next_alt_state
)
5865 state2
= alt_state
->state
;
5866 if (!intersected_state_reservs_p (state
, state2
))
5868 state2
= states_union (state
, state2
, reservs_matter
);
5869 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5871 state2
->it_was_placed_in_stack_for_NDFA_forming
5873 VLA_PTR_ADD (state_stack
, state2
);
5875 if (states_n
% 100 == 0)
5876 fprintf (stderr
, "*");
5878 added_arc
= add_arc (state
, state2
, ainsn
, 1);
5883 if (!ndfa_flag
&& added_arc
!= NULL
)
5885 added_arc
->state_alts
= 0;
5886 for (alt_state
= ainsn
->alt_states
;
5888 alt_state
= alt_state
->next_alt_state
)
5890 state2
= alt_state
->state
;
5891 if (!intersected_state_reservs_p (state
, state2
))
5892 added_arc
->state_alts
++;
5897 advance_cycle_ainsn
= ainsn
;
5899 /* Add transition to advance cycle. */
5900 state2
= state_shift (state
, reservs_matter
);
5901 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5903 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5904 VLA_PTR_ADD (state_stack
, state2
);
5906 if (states_n
% 100 == 0)
5907 fprintf (stderr
, "*");
5909 if (advance_cycle_ainsn
== NULL
)
5911 add_arc (state
, state2
, advance_cycle_ainsn
, 1);
5913 VLA_PTR_DELETE (state_stack
);
5916 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5918 form_arcs_marked_by_insn (state
)
5925 for (i
= 0; i
< description
->decls_num
; i
++)
5927 decl
= description
->decls
[i
];
5928 if (decl
->mode
== dm_insn_reserv
)
5929 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5931 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5933 if (arc
->insn
== NULL
)
5935 arc
->next_arc_marked_by_insn
5936 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5937 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5941 /* The function creates composed state (see comments for IR) from
5942 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5943 same insn. If the composed state is not in STATE_STACK yet, it is
5944 pushed into STATE_STACK. */
5946 create_composed_state (original_state
, arcs_marked_by_insn
, state_stack
)
5947 state_t original_state
;
5948 arc_t arcs_marked_by_insn
;
5949 vla_ptr_t
*state_stack
;
5952 alt_state_t alt_state
, curr_alt_state
;
5953 alt_state_t new_alt_state
;
5956 state_t state_in_table
;
5958 alt_state_t canonical_alt_states_list
;
5960 int new_state_p
= 0;
5962 if (arcs_marked_by_insn
== NULL
)
5964 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5965 state
= arcs_marked_by_insn
->to_state
;
5970 /* Create composed state. */
5971 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5972 curr_alt_state
= NULL
;
5973 for (curr_arc
= arcs_marked_by_insn
;
5975 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5976 if (curr_arc
->to_state
->component_states
== NULL
)
5978 new_alt_state
= get_free_alt_state ();
5979 new_alt_state
->next_alt_state
= curr_alt_state
;
5980 new_alt_state
->state
= curr_arc
->to_state
;
5981 curr_alt_state
= new_alt_state
;
5984 for (alt_state
= curr_arc
->to_state
->component_states
;
5986 alt_state
= alt_state
->next_sorted_alt_state
)
5988 new_alt_state
= get_free_alt_state ();
5989 new_alt_state
->next_alt_state
= curr_alt_state
;
5990 new_alt_state
->state
= alt_state
->state
;
5991 if (alt_state
->state
->component_states
!= NULL
)
5993 curr_alt_state
= new_alt_state
;
5995 /* There are not identical sets in the alt state list. */
5996 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5997 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
6000 state
= canonical_alt_states_list
->state
;
6001 free_state (temp_state
);
6005 state
->component_states
= canonical_alt_states_list
;
6006 state_in_table
= insert_state (state
);
6007 if (state_in_table
!= state
)
6009 if (!state_in_table
->it_was_placed_in_stack_for_DFA_forming
)
6012 state
= state_in_table
;
6016 if (state
->it_was_placed_in_stack_for_DFA_forming
)
6019 for (curr_alt_state
= state
->component_states
;
6020 curr_alt_state
!= NULL
;
6021 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
6022 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
6024 curr_arc
= next_out_arc (curr_arc
))
6025 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
, 1);
6027 arcs_marked_by_insn
->to_state
= state
;
6028 for (alts_number
= 0,
6029 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
6031 curr_arc
= next_arc
)
6033 next_arc
= curr_arc
->next_arc_marked_by_insn
;
6034 remove_arc (original_state
, curr_arc
);
6037 arcs_marked_by_insn
->state_alts
= alts_number
;
6040 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
6042 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
6043 VLA_PTR_ADD (*state_stack
, state
);
6048 /* The function transforms nondeterministic AUTOMATON into
6051 NDFA_to_DFA (automaton
)
6052 automaton_t automaton
;
6054 state_t start_state
;
6057 vla_ptr_t state_stack
;
6061 VLA_PTR_CREATE (state_stack
, 150, "state stack");
6062 /* Create the start state (empty state). */
6063 start_state
= automaton
->start_state
;
6064 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
6065 VLA_PTR_ADD (state_stack
, start_state
);
6067 while (VLA_PTR_LENGTH (state_stack
) != 0)
6069 state
= VLA_PTR (state_stack
, VLA_PTR_LENGTH (state_stack
) - 1);
6070 VLA_PTR_SHORTEN (state_stack
, 1);
6071 form_arcs_marked_by_insn (state
);
6072 for (i
= 0; i
< description
->decls_num
; i
++)
6074 decl
= description
->decls
[i
];
6075 if (decl
->mode
== dm_insn_reserv
6076 && create_composed_state
6077 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
6081 if (states_n
% 100 == 0)
6082 fprintf (stderr
, "*");
6086 VLA_PTR_DELETE (state_stack
);
6089 /* The following variable value is current number (1, 2, ...) of passing
6091 static int curr_state_graph_pass_num
;
6093 /* This recursive function passes all states achieved from START_STATE
6094 and applies APPLIED_FUNC to them. */
6096 pass_state_graph (start_state
, applied_func
)
6097 state_t start_state
;
6098 void (*applied_func
) PARAMS ((state_t state
));
6102 if (start_state
->pass_num
== curr_state_graph_pass_num
)
6104 start_state
->pass_num
= curr_state_graph_pass_num
;
6105 (*applied_func
) (start_state
);
6106 for (arc
= first_out_arc (start_state
);
6108 arc
= next_out_arc (arc
))
6109 pass_state_graph (arc
->to_state
, applied_func
);
6112 /* This recursive function passes all states of AUTOMATON and applies
6113 APPLIED_FUNC to them. */
6115 pass_states (automaton
, applied_func
)
6116 automaton_t automaton
;
6117 void (*applied_func
) PARAMS ((state_t state
));
6119 curr_state_graph_pass_num
++;
6120 pass_state_graph (automaton
->start_state
, applied_func
);
6123 /* The function initializes code for passing of all states. */
6125 initiate_pass_states ()
6127 curr_state_graph_pass_num
= 0;
6130 /* The following vla is used for storing pointers to all achieved
6132 static vla_ptr_t all_achieved_states
;
6134 /* This function is called by function pass_states to add an achieved
6137 add_achieved_state (state
)
6140 VLA_PTR_ADD (all_achieved_states
, state
);
6143 /* The function sets up equivalence numbers of insns which mark all
6144 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
6145 nonzero value) or by equiv_class_num_2 of the destination state.
6146 The function returns number of out arcs of STATE. */
6148 set_out_arc_insns_equiv_num (state
, odd_iteration_flag
)
6150 int odd_iteration_flag
;
6152 int state_out_arcs_num
;
6155 state_out_arcs_num
= 0;
6156 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6158 if (arc
->insn
->insn_reserv_decl
->equiv_class_num
!= 0
6159 || arc
->insn
->insn_reserv_decl
->state_alts
!= 0)
6161 state_out_arcs_num
++;
6162 arc
->insn
->insn_reserv_decl
->equiv_class_num
6163 = (odd_iteration_flag
6164 ? arc
->to_state
->equiv_class_num_1
6165 : arc
->to_state
->equiv_class_num_2
);
6166 arc
->insn
->insn_reserv_decl
->state_alts
= arc
->state_alts
;
6167 if (arc
->insn
->insn_reserv_decl
->equiv_class_num
== 0
6168 || arc
->insn
->insn_reserv_decl
->state_alts
<= 0)
6171 return state_out_arcs_num
;
6174 /* The function clears equivalence numbers and alt_states in all insns
6175 which mark all out arcs of STATE. */
6177 clear_arc_insns_equiv_num (state
)
6182 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6184 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
6185 arc
->insn
->insn_reserv_decl
->state_alts
= 0;
6189 /* The function copies pointers to equivalent states from vla FROM
6192 copy_equiv_class (to
, from
)
6194 const vla_ptr_t
*from
;
6198 VLA_PTR_NULLIFY (*to
);
6199 for (class_ptr
= VLA_PTR_BEGIN (*from
);
6200 class_ptr
<= (state_t
*) VLA_PTR_LAST (*from
);
6202 VLA_PTR_ADD (*to
, *class_ptr
);
6205 /* The following function returns TRUE if STATE reserves the unit with
6206 UNIT_NUM on the first cycle. */
6208 first_cycle_unit_presence (state
, unit_num
)
6214 if (state
->component_states
== NULL
)
6215 presence_p
= test_unit_reserv (state
->reservs
, 0, unit_num
);
6218 = test_unit_reserv (state
->component_states
->state
->reservs
,
6223 /* The function returns nonzero value if STATE is not equivalent to
6224 ANOTHER_STATE from the same current partition on equivalence
6225 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
6226 output arcs. Iteration of making equivalence partition is defined
6227 by ODD_ITERATION_FLAG. */
6229 state_is_differed (state
, another_state
, another_state_out_arcs_num
,
6231 state_t state
, another_state
;
6232 int another_state_out_arcs_num
;
6233 int odd_iteration_flag
;
6236 int state_out_arcs_num
;
6237 int i
, presence1_p
, presence2_p
;
6239 state_out_arcs_num
= 0;
6240 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6242 state_out_arcs_num
++;
6243 if ((odd_iteration_flag
6244 ? arc
->to_state
->equiv_class_num_1
6245 : arc
->to_state
->equiv_class_num_2
)
6246 != arc
->insn
->insn_reserv_decl
->equiv_class_num
6247 || (arc
->insn
->insn_reserv_decl
->state_alts
!= arc
->state_alts
))
6250 if (state_out_arcs_num
!= another_state_out_arcs_num
)
6252 /* Now we are looking at the states with the point of view of query
6254 for (i
= 0; i
< description
->units_num
; i
++)
6255 if (units_array
[i
]->query_p
)
6257 presence1_p
= first_cycle_unit_presence (state
, i
);
6258 presence2_p
= first_cycle_unit_presence (another_state
, i
);
6259 if ((presence1_p
&& !presence2_p
) || (!presence1_p
&& presence2_p
))
6265 /* The function makes initial partition of STATES on equivalent
6268 init_equiv_class (states
, states_num
)
6273 state_t result_equiv_class
;
6275 result_equiv_class
= NULL
;
6276 for (state_ptr
= states
; state_ptr
< states
+ states_num
; state_ptr
++)
6278 (*state_ptr
)->equiv_class_num_1
= 1;
6279 (*state_ptr
)->next_equiv_class_state
= result_equiv_class
;
6280 result_equiv_class
= *state_ptr
;
6282 return result_equiv_class
;
6285 /* The function processes equivalence class given by its pointer
6286 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
6287 are not equivalent states, the function partitions the class
6288 removing nonequivalent states and placing them in
6289 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6290 assigns it to the state equivalence number. If the class has been
6291 partitioned, the function returns nonzero value. */
6293 partition_equiv_class (equiv_class_ptr
, odd_iteration_flag
,
6294 next_iteration_classes
, new_equiv_class_num_ptr
)
6295 state_t
*equiv_class_ptr
;
6296 int odd_iteration_flag
;
6297 vla_ptr_t
*next_iteration_classes
;
6298 int *new_equiv_class_num_ptr
;
6300 state_t new_equiv_class
;
6302 state_t first_state
;
6309 if (*equiv_class_ptr
== NULL
)
6311 for (first_state
= *equiv_class_ptr
;
6312 first_state
!= NULL
;
6313 first_state
= new_equiv_class
)
6315 new_equiv_class
= NULL
;
6316 if (first_state
->next_equiv_class_state
!= NULL
)
6318 /* There are more one states in the class equivalence. */
6319 out_arcs_num
= set_out_arc_insns_equiv_num (first_state
,
6320 odd_iteration_flag
);
6321 for (prev_state
= first_state
,
6322 curr_state
= first_state
->next_equiv_class_state
;
6324 curr_state
= next_state
)
6326 next_state
= curr_state
->next_equiv_class_state
;
6327 if (state_is_differed (curr_state
, first_state
, out_arcs_num
,
6328 odd_iteration_flag
))
6330 /* Remove curr state from the class equivalence. */
6331 prev_state
->next_equiv_class_state
= next_state
;
6332 /* Add curr state to the new class equivalence. */
6333 curr_state
->next_equiv_class_state
= new_equiv_class
;
6334 if (new_equiv_class
== NULL
)
6335 (*new_equiv_class_num_ptr
)++;
6336 if (odd_iteration_flag
)
6337 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
6339 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
6340 new_equiv_class
= curr_state
;
6344 prev_state
= curr_state
;
6346 clear_arc_insns_equiv_num (first_state
);
6348 if (new_equiv_class
!= NULL
)
6349 VLA_PTR_ADD (*next_iteration_classes
, new_equiv_class
);
6354 /* The function finds equivalent states of AUTOMATON. */
6356 evaluate_equiv_classes (automaton
, equiv_classes
)
6357 automaton_t automaton
;
6358 vla_ptr_t
*equiv_classes
;
6360 state_t new_equiv_class
;
6361 int new_equiv_class_num
;
6362 int odd_iteration_flag
;
6364 vla_ptr_t next_iteration_classes
;
6365 state_t
*equiv_class_ptr
;
6368 VLA_PTR_CREATE (all_achieved_states
, 1500, "all achieved states");
6369 pass_states (automaton
, add_achieved_state
);
6370 new_equiv_class
= init_equiv_class (VLA_PTR_BEGIN (all_achieved_states
),
6371 VLA_PTR_LENGTH (all_achieved_states
));
6372 odd_iteration_flag
= 0;
6373 new_equiv_class_num
= 1;
6374 VLA_PTR_CREATE (next_iteration_classes
, 150, "next iteration classes");
6375 VLA_PTR_ADD (next_iteration_classes
, new_equiv_class
);
6378 odd_iteration_flag
= !odd_iteration_flag
;
6380 copy_equiv_class (equiv_classes
, &next_iteration_classes
);
6381 /* Transfer equiv numbers for the next iteration. */
6382 for (state_ptr
= VLA_PTR_BEGIN (all_achieved_states
);
6383 state_ptr
<= (state_t
*) VLA_PTR_LAST (all_achieved_states
);
6385 if (odd_iteration_flag
)
6386 (*state_ptr
)->equiv_class_num_2
= (*state_ptr
)->equiv_class_num_1
;
6388 (*state_ptr
)->equiv_class_num_1
= (*state_ptr
)->equiv_class_num_2
;
6389 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6390 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6392 if (partition_equiv_class (equiv_class_ptr
, odd_iteration_flag
,
6393 &next_iteration_classes
,
6394 &new_equiv_class_num
))
6397 while (!finish_flag
);
6398 VLA_PTR_DELETE (next_iteration_classes
);
6399 VLA_PTR_DELETE (all_achieved_states
);
6402 /* The function merges equivalent states of AUTOMATON. */
6404 merge_states (automaton
, equiv_classes
)
6405 automaton_t automaton
;
6406 vla_ptr_t
*equiv_classes
;
6408 state_t
*equiv_class_ptr
;
6411 state_t first_class_state
;
6412 alt_state_t alt_states
;
6413 alt_state_t alt_state
, new_alt_state
;
6417 /* Create states corresponding to equivalence classes containing two
6419 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6420 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6422 if ((*equiv_class_ptr
)->next_equiv_class_state
!= NULL
)
6424 /* There are more one states in the class equivalence. */
6425 /* Create new compound state. */
6426 new_state
= get_free_state (0, automaton
);
6428 first_class_state
= *equiv_class_ptr
;
6429 for (curr_state
= first_class_state
;
6431 curr_state
= curr_state
->next_equiv_class_state
)
6433 curr_state
->equiv_class_state
= new_state
;
6434 if (curr_state
->component_states
== NULL
)
6436 new_alt_state
= get_free_alt_state ();
6437 new_alt_state
->state
= curr_state
;
6438 new_alt_state
->next_alt_state
= alt_states
;
6439 alt_states
= new_alt_state
;
6442 for (alt_state
= curr_state
->component_states
;
6444 alt_state
= alt_state
->next_sorted_alt_state
)
6446 new_alt_state
= get_free_alt_state ();
6447 new_alt_state
->state
= alt_state
->state
;
6448 new_alt_state
->next_alt_state
= alt_states
;
6449 alt_states
= new_alt_state
;
6452 /* Its is important that alt states were sorted before and
6453 after merging to have the same quering results. */
6454 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
6457 (*equiv_class_ptr
)->equiv_class_state
= *equiv_class_ptr
;
6458 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6459 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6461 if ((*equiv_class_ptr
)->next_equiv_class_state
!= NULL
)
6463 first_class_state
= *equiv_class_ptr
;
6464 /* Create new arcs output from the state corresponding to
6466 for (curr_arc
= first_out_arc (first_class_state
);
6468 curr_arc
= next_out_arc (curr_arc
))
6469 add_arc (first_class_state
->equiv_class_state
,
6470 curr_arc
->to_state
->equiv_class_state
,
6471 curr_arc
->insn
, curr_arc
->state_alts
);
6472 /* Delete output arcs from states of given class equivalence. */
6473 for (curr_state
= first_class_state
;
6475 curr_state
= curr_state
->next_equiv_class_state
)
6477 if (automaton
->start_state
== curr_state
)
6478 automaton
->start_state
= curr_state
->equiv_class_state
;
6479 /* Delete the state and its output arcs. */
6480 for (curr_arc
= first_out_arc (curr_state
);
6482 curr_arc
= next_arc
)
6484 next_arc
= next_out_arc (curr_arc
);
6485 free_arc (curr_arc
);
6491 /* Change `to_state' of arcs output from the state of given
6492 equivalence class. */
6493 for (curr_arc
= first_out_arc (*equiv_class_ptr
);
6495 curr_arc
= next_out_arc (curr_arc
))
6496 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
6500 /* The function sets up new_cycle_p for states if there is arc to the
6501 state marked by advance_cycle_insn_decl. */
6503 set_new_cycle_flags (state
)
6508 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6509 if (arc
->insn
->insn_reserv_decl
6510 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6511 arc
->to_state
->new_cycle_p
= 1;
6514 /* The top level function for minimization of deterministic
6517 minimize_DFA (automaton
)
6518 automaton_t automaton
;
6520 vla_ptr_t equiv_classes
;
6522 VLA_PTR_CREATE (equiv_classes
, 1500, "equivalence classes");
6523 evaluate_equiv_classes (automaton
, &equiv_classes
);
6524 merge_states (automaton
, &equiv_classes
);
6525 pass_states (automaton
, set_new_cycle_flags
);
6526 VLA_PTR_DELETE (equiv_classes
);
6529 /* Values of two variables are counted number of states and arcs in an
6531 static int curr_counted_states_num
;
6532 static int curr_counted_arcs_num
;
6534 /* The function is called by function `pass_states' to count states
6535 and arcs of an automaton. */
6537 incr_states_and_arcs_nums (state
)
6542 curr_counted_states_num
++;
6543 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6544 curr_counted_arcs_num
++;
6547 /* The function counts states and arcs of AUTOMATON. */
6549 count_states_and_arcs (automaton
, states_num
, arcs_num
)
6550 automaton_t automaton
;
6554 curr_counted_states_num
= 0;
6555 curr_counted_arcs_num
= 0;
6556 pass_states (automaton
, incr_states_and_arcs_nums
);
6557 *states_num
= curr_counted_states_num
;
6558 *arcs_num
= curr_counted_arcs_num
;
6561 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6562 recognition after checking and simplifying IR of the
6565 build_automaton (automaton
)
6566 automaton_t automaton
;
6571 ticker_on (&NDFA_time
);
6572 if (automaton
->corresponding_automaton_decl
== NULL
)
6573 fprintf (stderr
, "Create anonymous automaton (1 star is 100 new states):");
6575 fprintf (stderr
, "Create automaton `%s' (1 star is 100 new states):",
6576 automaton
->corresponding_automaton_decl
->name
);
6577 make_automaton (automaton
);
6578 fprintf (stderr
, " done\n");
6579 ticker_off (&NDFA_time
);
6580 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6581 automaton
->NDFA_states_num
= states_num
;
6582 automaton
->NDFA_arcs_num
= arcs_num
;
6583 ticker_on (&NDFA_to_DFA_time
);
6584 if (automaton
->corresponding_automaton_decl
== NULL
)
6585 fprintf (stderr
, "Make anonymous DFA (1 star is 100 new states):");
6587 fprintf (stderr
, "Make DFA `%s' (1 star is 100 new states):",
6588 automaton
->corresponding_automaton_decl
->name
);
6589 NDFA_to_DFA (automaton
);
6590 fprintf (stderr
, " done\n");
6591 ticker_off (&NDFA_to_DFA_time
);
6592 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6593 automaton
->DFA_states_num
= states_num
;
6594 automaton
->DFA_arcs_num
= arcs_num
;
6595 if (!no_minimization_flag
)
6597 ticker_on (&minimize_time
);
6598 if (automaton
->corresponding_automaton_decl
== NULL
)
6599 fprintf (stderr
, "Minimize anonymous DFA...");
6601 fprintf (stderr
, "Minimize DFA `%s'...",
6602 automaton
->corresponding_automaton_decl
->name
);
6603 minimize_DFA (automaton
);
6604 fprintf (stderr
, "done\n");
6605 ticker_off (&minimize_time
);
6606 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6607 automaton
->minimal_DFA_states_num
= states_num
;
6608 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6614 /* The page contains code for enumeration of all states of an automaton. */
6616 /* Variable used for enumeration of all states of an automaton. Its
6617 value is current number of automaton states. */
6618 static int curr_state_order_num
;
6620 /* The function is called by function `pass_states' for enumerating
6623 set_order_state_num (state
)
6626 state
->order_state_num
= curr_state_order_num
;
6627 curr_state_order_num
++;
6630 /* The function enumerates all states of AUTOMATON. */
6632 enumerate_states (automaton
)
6633 automaton_t automaton
;
6635 curr_state_order_num
= 0;
6636 pass_states (automaton
, set_order_state_num
);
6637 automaton
->achieved_states_num
= curr_state_order_num
;
6642 /* The page contains code for finding equivalent automaton insns
6645 /* The function inserts AINSN into cyclic list
6646 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6648 insert_ainsn_into_equiv_class (ainsn
, cyclic_equiv_class_insn_list
)
6650 ainsn_t cyclic_equiv_class_insn_list
;
6652 if (cyclic_equiv_class_insn_list
== NULL
)
6653 ainsn
->next_equiv_class_insn
= ainsn
;
6656 ainsn
->next_equiv_class_insn
6657 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6658 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6663 /* The function deletes equiv_class_insn into cyclic list of
6664 equivalent ainsns. */
6666 delete_ainsn_from_equiv_class (equiv_class_insn
)
6667 ainsn_t equiv_class_insn
;
6669 ainsn_t curr_equiv_class_insn
;
6670 ainsn_t prev_equiv_class_insn
;
6672 prev_equiv_class_insn
= equiv_class_insn
;
6673 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6674 curr_equiv_class_insn
!= equiv_class_insn
;
6675 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6676 prev_equiv_class_insn
= curr_equiv_class_insn
;
6677 if (prev_equiv_class_insn
!= equiv_class_insn
)
6678 prev_equiv_class_insn
->next_equiv_class_insn
6679 = equiv_class_insn
->next_equiv_class_insn
;
6682 /* The function processes AINSN of a state in order to find equivalent
6683 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6686 process_insn_equiv_class (ainsn
, insn_arcs_array
)
6688 arc_t
*insn_arcs_array
;
6692 ainsn_t cyclic_insn_list
;
6695 if (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
] == NULL
)
6698 /* New class of ainsns which are not equivalent to given ainsn. */
6699 cyclic_insn_list
= NULL
;
6702 next_insn
= curr_insn
->next_equiv_class_insn
;
6703 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6705 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6708 delete_ainsn_from_equiv_class (curr_insn
);
6709 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6712 curr_insn
= next_insn
;
6714 while (curr_insn
!= ainsn
);
6717 /* The function processes STATE in order to find equivalent ainsns. */
6719 process_state_for_insn_equiv_partition (state
)
6723 arc_t
*insn_arcs_array
;
6725 vla_ptr_t insn_arcs_vect
;
6727 VLA_PTR_CREATE (insn_arcs_vect
, 500, "insn arcs vector");
6728 VLA_PTR_EXPAND (insn_arcs_vect
, description
->insns_num
);
6729 insn_arcs_array
= VLA_PTR_BEGIN (insn_arcs_vect
);
6730 /* Process insns of the arcs. */
6731 for (i
= 0; i
< description
->insns_num
; i
++)
6732 insn_arcs_array
[i
] = NULL
;
6733 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6734 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6735 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6736 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6737 VLA_PTR_DELETE (insn_arcs_vect
);
6740 /* The function searches for equivalent ainsns of AUTOMATON. */
6742 set_insn_equiv_classes (automaton
)
6743 automaton_t automaton
;
6748 ainsn_t cyclic_insn_list
;
6749 ainsn_t insn_with_same_reservs
;
6750 int equiv_classes_num
;
6752 /* All insns are included in one equivalence class. */
6753 cyclic_insn_list
= NULL
;
6754 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6755 if (ainsn
->first_insn_with_same_reservs
)
6756 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6758 /* Process insns in order to make equivalence partition. */
6759 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6760 /* Enumerate equiv classes. */
6761 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6762 /* Set undefined value. */
6763 ainsn
->insn_equiv_class_num
= -1;
6764 equiv_classes_num
= 0;
6765 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6766 if (ainsn
->insn_equiv_class_num
< 0)
6769 if (!first_insn
->first_insn_with_same_reservs
)
6771 first_insn
->first_ainsn_with_given_equialence_num
= 1;
6772 curr_insn
= first_insn
;
6775 for (insn_with_same_reservs
= curr_insn
;
6776 insn_with_same_reservs
!= NULL
;
6777 insn_with_same_reservs
6778 = insn_with_same_reservs
->next_same_reservs_insn
)
6779 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6780 curr_insn
= curr_insn
->next_equiv_class_insn
;
6782 while (curr_insn
!= first_insn
);
6783 equiv_classes_num
++;
6785 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6790 /* This page contains code for creating DFA(s) and calls functions
6794 /* The following value is used to prevent floating point overflow for
6795 estimating an automaton bound. The value should be less DBL_MAX on
6796 the host machine. We use here approximate minimum of maximal
6797 double floating point value required by ANSI C standard. It
6798 will work for non ANSI sun compiler too. */
6800 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6802 /* The function estimate size of the single DFA used by PHR (pipeline
6803 hazards recognizer). */
6805 estimate_one_automaton_bound ()
6808 double one_automaton_estimation_bound
;
6812 one_automaton_estimation_bound
= 1.0;
6813 for (i
= 0; i
< description
->decls_num
; i
++)
6815 decl
= description
->decls
[i
];
6816 if (decl
->mode
== dm_unit
)
6818 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6819 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6821 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6822 > one_automaton_estimation_bound
)
6823 one_automaton_estimation_bound
*= root_value
;
6826 return one_automaton_estimation_bound
;
6829 /* The function compares unit declarations according to their maximal
6830 cycle in reservations. */
6832 compare_max_occ_cycle_nums (unit_decl_1
, unit_decl_2
)
6833 const void *unit_decl_1
;
6834 const void *unit_decl_2
;
6836 if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6837 < (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6839 else if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6840 == (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6846 /* The function makes heuristic assigning automata to units. Actually
6847 efficacy of the algorithm has been checked yet??? */
6849 units_to_automata_heuristic_distr ()
6851 double estimation_bound
;
6853 decl_t
*unit_decl_ptr
;
6857 vla_ptr_t unit_decls
;
6860 if (description
->units_num
== 0)
6862 estimation_bound
= estimate_one_automaton_bound ();
6863 VLA_PTR_CREATE (unit_decls
, 150, "unit decls");
6864 for (i
= 0; i
< description
->decls_num
; i
++)
6866 decl
= description
->decls
[i
];
6867 if (decl
->mode
== dm_unit
)
6868 VLA_PTR_ADD (unit_decls
, decl
);
6870 qsort (VLA_PTR_BEGIN (unit_decls
), VLA_PTR_LENGTH (unit_decls
),
6871 sizeof (decl_t
), compare_max_occ_cycle_nums
);
6873 unit_decl_ptr
= VLA_PTR_BEGIN (unit_decls
);
6874 bound_value
= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6875 DECL_UNIT (*unit_decl_ptr
)->corresponding_automaton_num
= automaton_num
;
6876 for (unit_decl_ptr
++;
6877 unit_decl_ptr
<= (decl_t
*) VLA_PTR_LAST (unit_decls
);
6881 = ((decl_t
*) VLA_PTR_LAST (unit_decls
) - unit_decl_ptr
+ 1);
6882 if (automata_num
- automaton_num
- 1 > rest_units_num
)
6884 if (automaton_num
< automata_num
- 1
6885 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6888 / (DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
)))))
6890 bound_value
= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6894 bound_value
*= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6895 DECL_UNIT (*unit_decl_ptr
)->corresponding_automaton_num
= automaton_num
;
6897 if (automaton_num
!= automata_num
- 1)
6899 VLA_PTR_DELETE (unit_decls
);
6902 /* The functions creates automaton insns for each automata. Automaton
6903 insn is simply insn for given automaton which makes reservation
6904 only of units of the automaton. */
6909 ainsn_t first_ainsn
;
6916 for (i
= 0; i
< description
->decls_num
; i
++)
6918 decl
= description
->decls
[i
];
6919 if (decl
->mode
== dm_insn_reserv
)
6921 curr_ainsn
= create_node (sizeof (struct ainsn
));
6922 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6923 curr_ainsn
->important_p
= FALSE
;
6924 curr_ainsn
->next_ainsn
= NULL
;
6925 if (prev_ainsn
== NULL
)
6926 first_ainsn
= curr_ainsn
;
6928 prev_ainsn
->next_ainsn
= curr_ainsn
;
6929 prev_ainsn
= curr_ainsn
;
6935 /* The function assigns automata to units according to constructions
6936 `define_automaton' in the description. */
6938 units_to_automata_distr ()
6943 for (i
= 0; i
< description
->decls_num
; i
++)
6945 decl
= description
->decls
[i
];
6946 if (decl
->mode
== dm_unit
)
6948 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6949 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6951 /* Distribute to the first automaton. */
6952 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6954 DECL_UNIT (decl
)->corresponding_automaton_num
6955 = (DECL_UNIT (decl
)->automaton_decl
6956 ->corresponding_automaton
->automaton_order_num
);
6961 /* The function creates DFA(s) for fast pipeline hazards recognition
6962 after checking and simplifying IR of the description. */
6966 automaton_t curr_automaton
;
6967 automaton_t prev_automaton
;
6969 int curr_automaton_num
;
6972 if (automata_num
!= 0)
6974 units_to_automata_heuristic_distr ();
6975 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6976 curr_automaton_num
< automata_num
;
6977 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6979 curr_automaton
= create_node (sizeof (struct automaton
));
6980 curr_automaton
->ainsn_list
= create_ainsns ();
6981 curr_automaton
->corresponding_automaton_decl
= NULL
;
6982 curr_automaton
->next_automaton
= NULL
;
6983 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6984 if (prev_automaton
== NULL
)
6985 description
->first_automaton
= curr_automaton
;
6987 prev_automaton
->next_automaton
= curr_automaton
;
6992 curr_automaton_num
= 0;
6993 prev_automaton
= NULL
;
6994 for (i
= 0; i
< description
->decls_num
; i
++)
6996 decl
= description
->decls
[i
];
6997 if (decl
->mode
== dm_automaton
6998 && DECL_AUTOMATON (decl
)->automaton_is_used
)
7000 curr_automaton
= create_node (sizeof (struct automaton
));
7001 curr_automaton
->ainsn_list
= create_ainsns ();
7002 curr_automaton
->corresponding_automaton_decl
7003 = DECL_AUTOMATON (decl
);
7004 curr_automaton
->next_automaton
= NULL
;
7005 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
7006 curr_automaton
->automaton_order_num
= curr_automaton_num
;
7007 if (prev_automaton
== NULL
)
7008 description
->first_automaton
= curr_automaton
;
7010 prev_automaton
->next_automaton
= curr_automaton
;
7011 curr_automaton_num
++;
7012 prev_automaton
= curr_automaton
;
7015 if (curr_automaton_num
== 0)
7017 curr_automaton
= create_node (sizeof (struct automaton
));
7018 curr_automaton
->ainsn_list
= create_ainsns ();
7019 curr_automaton
->corresponding_automaton_decl
= NULL
;
7020 curr_automaton
->next_automaton
= NULL
;
7021 description
->first_automaton
= curr_automaton
;
7023 units_to_automata_distr ();
7025 NDFA_time
= create_ticker ();
7026 ticker_off (&NDFA_time
);
7027 NDFA_to_DFA_time
= create_ticker ();
7028 ticker_off (&NDFA_to_DFA_time
);
7029 minimize_time
= create_ticker ();
7030 ticker_off (&minimize_time
);
7031 equiv_time
= create_ticker ();
7032 ticker_off (&equiv_time
);
7033 for (curr_automaton
= description
->first_automaton
;
7034 curr_automaton
!= NULL
;
7035 curr_automaton
= curr_automaton
->next_automaton
)
7037 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
7038 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
7040 fprintf (stderr
, "Prepare automaton `%s' creation...",
7041 curr_automaton
->corresponding_automaton_decl
->name
);
7042 create_alt_states (curr_automaton
);
7043 form_ainsn_with_same_reservs (curr_automaton
);
7044 fprintf (stderr
, "done\n");
7045 build_automaton (curr_automaton
);
7046 enumerate_states (curr_automaton
);
7047 ticker_on (&equiv_time
);
7048 set_insn_equiv_classes (curr_automaton
);
7049 ticker_off (&equiv_time
);
7055 /* This page contains code for forming string representation of
7056 regexp. The representation is formed on IR obstack. So you should
7057 not work with IR obstack between regexp_representation and
7058 finish_regexp_representation calls. */
7060 /* This recursive function forms string representation of regexp
7061 (without tailing '\0'). */
7063 form_regexp (regexp
)
7068 if (regexp
->mode
== rm_unit
|| regexp
->mode
== rm_reserv
)
7070 const char *name
= (regexp
->mode
== rm_unit
7071 ? REGEXP_UNIT (regexp
)->name
7072 : REGEXP_RESERV (regexp
)->name
);
7074 obstack_grow (&irp
, name
, strlen (name
));
7076 else if (regexp
->mode
== rm_sequence
)
7077 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
7080 obstack_1grow (&irp
, ',');
7081 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
7083 else if (regexp
->mode
== rm_allof
)
7085 obstack_1grow (&irp
, '(');
7086 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
7089 obstack_1grow (&irp
, '+');
7090 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
7091 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
7092 obstack_1grow (&irp
, '(');
7093 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
7094 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
7095 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
7096 obstack_1grow (&irp
, ')');
7098 obstack_1grow (&irp
, ')');
7100 else if (regexp
->mode
== rm_oneof
)
7101 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
7104 obstack_1grow (&irp
, '|');
7105 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
7106 obstack_1grow (&irp
, '(');
7107 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
7108 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
7109 obstack_1grow (&irp
, ')');
7111 else if (regexp
->mode
== rm_repeat
)
7115 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
7116 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
7117 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
7118 obstack_1grow (&irp
, '(');
7119 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
7120 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
7121 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
7122 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
7123 obstack_1grow (&irp
, ')');
7124 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
7125 obstack_grow (&irp
, digits
, strlen (digits
));
7127 else if (regexp
->mode
== rm_nothing
)
7128 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
7133 /* The function returns string representation of REGEXP on IR
7136 regexp_representation (regexp
)
7139 form_regexp (regexp
);
7140 obstack_1grow (&irp
, '\0');
7141 return obstack_base (&irp
);
7144 /* The function frees memory allocated for last formed string
7145 representation of regexp. */
7147 finish_regexp_representation ()
7149 int length
= obstack_object_size (&irp
);
7151 obstack_blank_fast (&irp
, -length
);
7156 /* This page contains code for output PHR (pipeline hazards recognizer). */
7158 /* The function outputs minimal C type which is sufficient for
7159 representation numbers in range min_range_value and
7160 max_range_value. Because host machine and build machine may be
7161 different, we use here minimal values required by ANSI C standard
7162 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
7166 output_range_type (f
, min_range_value
, max_range_value
)
7168 long int min_range_value
;
7169 long int max_range_value
;
7171 if (min_range_value
>= 0 && max_range_value
<= 255)
7172 fprintf (f
, "unsigned char");
7173 else if (min_range_value
>= -127 && max_range_value
<= 127)
7174 fprintf (f
, "signed char");
7175 else if (min_range_value
>= 0 && max_range_value
<= 65535)
7176 fprintf (f
, "unsigned short");
7177 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
7178 fprintf (f
, "short");
7183 /* The following macro value is used as value of member
7184 `longest_path_length' of state when we are processing path and the
7185 state on the path. */
7187 #define ON_THE_PATH -2
7189 /* The following recursive function searches for the length of the
7190 longest path starting from STATE which does not contain cycles and
7191 `cycle advance' arcs. */
7194 longest_path_length (state
)
7200 if (state
->longest_path_length
== ON_THE_PATH
)
7201 /* We don't expect the path cycle here. Our graph may contain
7202 only cycles with one state on the path not containing `cycle
7203 advance' arcs -- see comment below. */
7205 else if (state
->longest_path_length
!= UNDEFINED_LONGEST_PATH_LENGTH
)
7206 /* We alreday visited the state. */
7207 return state
->longest_path_length
;
7210 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7211 /* Ignore cycles containing one state and `cycle advance' arcs. */
7212 if (arc
->to_state
!= state
7213 && (arc
->insn
->insn_reserv_decl
7214 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7216 length
= longest_path_length (arc
->to_state
);
7217 if (length
> result
)
7220 state
->longest_path_length
= result
+ 1;
7224 /* The following variable value is value of the corresponding global
7225 variable in the automaton based pipeline interface. */
7227 static int max_dfa_issue_rate
;
7229 /* The following function processes the longest path length staring
7230 from STATE to find MAX_DFA_ISSUE_RATE. */
7233 process_state_longest_path_length (state
)
7238 value
= longest_path_length (state
);
7239 if (value
> max_dfa_issue_rate
)
7240 max_dfa_issue_rate
= value
;
7243 /* The following macro value is name of the corresponding global
7244 variable in the automaton based pipeline interface. */
7246 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
7248 /* The following function calculates value of the corresponding
7249 global variable and outputs its declaration. */
7252 output_dfa_max_issue_rate ()
7254 automaton_t automaton
;
7256 if (UNDEFINED_LONGEST_PATH_LENGTH
== ON_THE_PATH
|| ON_THE_PATH
>= 0)
7258 max_dfa_issue_rate
= 0;
7259 for (automaton
= description
->first_automaton
;
7261 automaton
= automaton
->next_automaton
)
7262 pass_states (automaton
, process_state_longest_path_length
);
7263 fprintf (output_file
, "\nint %s = %d;\n",
7264 MAX_DFA_ISSUE_RATE_VAR_NAME
, max_dfa_issue_rate
);
7267 /* The function outputs all initialization values of VECT with length
7270 output_vect (vect
, vect_length
)
7277 if (vect_length
== 0)
7278 fprintf (output_file
,
7279 "0 /* This is dummy el because the vect is empty */");
7284 fprintf (output_file
, "%5ld", (long) *vect
);
7286 if (els_on_line
== 10)
7289 fprintf (output_file
, ",\n");
7291 else if (vect_length
!= 0)
7292 fprintf (output_file
, ", ");
7296 while (vect_length
!= 0);
7300 /* The following is name of the structure which represents DFA(s) for
7302 #define CHIP_NAME "DFA_chip"
7304 /* The following is name of member which represents state of a DFA for
7307 output_chip_member_name (f
, automaton
)
7309 automaton_t automaton
;
7311 if (automaton
->corresponding_automaton_decl
== NULL
)
7312 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
7314 fprintf (f
, "%s_automaton_state",
7315 automaton
->corresponding_automaton_decl
->name
);
7318 /* The following is name of temporary variable which stores state of a
7321 output_temp_chip_member_name (f
, automaton
)
7323 automaton_t automaton
;
7326 output_chip_member_name (f
, automaton
);
7329 /* This is name of macro value which is code of pseudo_insn
7330 representing advancing cpu cycle. Its value is used as internal
7331 code unknown insn. */
7332 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7334 /* Output name of translate vector for given automaton. */
7336 output_translate_vect_name (f
, automaton
)
7338 automaton_t automaton
;
7340 if (automaton
->corresponding_automaton_decl
== NULL
)
7341 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
7343 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
7346 /* Output name for simple transition table representation. */
7348 output_trans_full_vect_name (f
, automaton
)
7350 automaton_t automaton
;
7352 if (automaton
->corresponding_automaton_decl
== NULL
)
7353 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7355 fprintf (f
, "%s_transitions",
7356 automaton
->corresponding_automaton_decl
->name
);
7359 /* Output name of comb vector of the transition table for given
7362 output_trans_comb_vect_name (f
, automaton
)
7364 automaton_t automaton
;
7366 if (automaton
->corresponding_automaton_decl
== NULL
)
7367 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7369 fprintf (f
, "%s_transitions",
7370 automaton
->corresponding_automaton_decl
->name
);
7373 /* Output name of check vector of the transition table for given
7376 output_trans_check_vect_name (f
, automaton
)
7378 automaton_t automaton
;
7380 if (automaton
->corresponding_automaton_decl
== NULL
)
7381 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
7383 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
7386 /* Output name of base vector of the transition table for given
7389 output_trans_base_vect_name (f
, automaton
)
7391 automaton_t automaton
;
7393 if (automaton
->corresponding_automaton_decl
== NULL
)
7394 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
7396 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
7399 /* Output name for simple alternatives number representation. */
7401 output_state_alts_full_vect_name (f
, automaton
)
7403 automaton_t automaton
;
7405 if (automaton
->corresponding_automaton_decl
== NULL
)
7406 fprintf (f
, "state_alts_%d", automaton
->automaton_order_num
);
7408 fprintf (f
, "%s_state_alts",
7409 automaton
->corresponding_automaton_decl
->name
);
7412 /* Output name of comb vector of the alternatives number table for given
7415 output_state_alts_comb_vect_name (f
, automaton
)
7417 automaton_t automaton
;
7419 if (automaton
->corresponding_automaton_decl
== NULL
)
7420 fprintf (f
, "state_alts_%d", automaton
->automaton_order_num
);
7422 fprintf (f
, "%s_state_alts",
7423 automaton
->corresponding_automaton_decl
->name
);
7426 /* Output name of check vector of the alternatives number table for given
7429 output_state_alts_check_vect_name (f
, automaton
)
7431 automaton_t automaton
;
7433 if (automaton
->corresponding_automaton_decl
== NULL
)
7434 fprintf (f
, "check_state_alts_%d", automaton
->automaton_order_num
);
7436 fprintf (f
, "%s_check_state_alts",
7437 automaton
->corresponding_automaton_decl
->name
);
7440 /* Output name of base vector of the alternatives number table for given
7443 output_state_alts_base_vect_name (f
, automaton
)
7445 automaton_t automaton
;
7447 if (automaton
->corresponding_automaton_decl
== NULL
)
7448 fprintf (f
, "base_state_alts_%d", automaton
->automaton_order_num
);
7450 fprintf (f
, "%s_base_state_alts",
7451 automaton
->corresponding_automaton_decl
->name
);
7454 /* Output name of simple min issue delay table representation. */
7456 output_min_issue_delay_vect_name (f
, automaton
)
7458 automaton_t automaton
;
7460 if (automaton
->corresponding_automaton_decl
== NULL
)
7461 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
7463 fprintf (f
, "%s_min_issue_delay",
7464 automaton
->corresponding_automaton_decl
->name
);
7467 /* Output name of deadlock vector for given automaton. */
7469 output_dead_lock_vect_name (f
, automaton
)
7471 automaton_t automaton
;
7473 if (automaton
->corresponding_automaton_decl
== NULL
)
7474 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
7476 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
7479 /* Output name of reserved units table for AUTOMATON into file F. */
7481 output_reserved_units_table_name (f
, automaton
)
7483 automaton_t automaton
;
7485 if (automaton
->corresponding_automaton_decl
== NULL
)
7486 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
7488 fprintf (f
, "%s_reserved_units",
7489 automaton
->corresponding_automaton_decl
->name
);
7492 /* Name of the PHR interface macro. */
7493 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7495 /* Name of the PHR interface macro. */
7496 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7498 /* Names of an internal functions: */
7499 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7501 /* This is external type of DFA(s) state. */
7502 #define STATE_TYPE_NAME "state_t"
7504 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7506 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7508 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7510 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7512 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7514 /* Name of cache of insn dfa codes. */
7515 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7517 /* Name of length of cache of insn dfa codes. */
7518 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7520 /* Names of the PHR interface functions: */
7521 #define SIZE_FUNC_NAME "state_size"
7523 #define TRANSITION_FUNC_NAME "state_transition"
7525 #define STATE_ALTS_FUNC_NAME "state_alts"
7527 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7529 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7531 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7533 #define RESET_FUNC_NAME "state_reset"
7535 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7537 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7539 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7541 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7543 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7545 #define DFA_START_FUNC_NAME "dfa_start"
7547 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7549 /* Names of parameters of the PHR interface functions. */
7550 #define STATE_NAME "state"
7552 #define INSN_PARAMETER_NAME "insn"
7554 #define INSN2_PARAMETER_NAME "insn2"
7556 #define CHIP_PARAMETER_NAME "chip"
7558 #define FILE_PARAMETER_NAME "f"
7560 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7562 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7564 /* Names of the variables whose values are internal insn code of rtx
7566 #define INTERNAL_INSN_CODE_NAME "insn_code"
7568 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7570 /* Names of temporary variables in some functions. */
7571 #define TEMPORARY_VARIABLE_NAME "temp"
7573 #define I_VARIABLE_NAME "i"
7575 /* Name of result variable in some functions. */
7576 #define RESULT_VARIABLE_NAME "res"
7578 /* Name of function (attribute) to translate insn into number of insn
7579 alternatives reservation. */
7580 #define INSN_ALTS_FUNC_NAME "insn_alts"
7582 /* Name of function (attribute) to translate insn into internal insn
7584 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7586 /* Name of function (attribute) to translate insn into internal insn
7587 code with caching. */
7588 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7590 /* Name of function (attribute) to translate insn into internal insn
7592 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7594 /* Name of function (attribute) to translate insn into internal insn
7596 #define BYPASS_P_FUNC_NAME "bypass_p"
7598 /* Output C type which is used for representation of codes of states
7601 output_state_member_type (f
, automaton
)
7603 automaton_t automaton
;
7605 output_range_type (f
, 0, automaton
->achieved_states_num
);
7608 /* Output definition of the structure representing current DFA(s)
7611 output_chip_definitions ()
7613 automaton_t automaton
;
7615 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
7616 for (automaton
= description
->first_automaton
;
7618 automaton
= automaton
->next_automaton
)
7620 fprintf (output_file
, " ");
7621 output_state_member_type (output_file
, automaton
);
7622 fprintf (output_file
, " ");
7623 output_chip_member_name (output_file
, automaton
);
7624 fprintf (output_file
, ";\n");
7626 fprintf (output_file
, "};\n\n");
7628 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
7633 /* The function outputs translate vector of internal insn code into
7634 insn equivalence class number. The equivalence class number is
7635 used to access to table and vectors representing DFA(s). */
7637 output_translate_vect (automaton
)
7638 automaton_t automaton
;
7642 vla_hwint_t translate_vect
;
7644 VLA_HWINT_CREATE (translate_vect
, 250, "translate vector");
7645 VLA_HWINT_EXPAND (translate_vect
, description
->insns_num
);
7646 for (insn_value
= 0; insn_value
<= description
->insns_num
; insn_value
++)
7647 /* Undefined value */
7648 VLA_HWINT (translate_vect
, insn_value
) = automaton
->insn_equiv_classes_num
;
7649 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7650 VLA_HWINT (translate_vect
, ainsn
->insn_reserv_decl
->insn_num
)
7651 = ainsn
->insn_equiv_class_num
;
7652 fprintf (output_file
,
7653 "/* Vector translating external insn codes to internal ones.*/\n");
7654 fprintf (output_file
, "static const ");
7655 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7656 fprintf (output_file
, " ");
7657 output_translate_vect_name (output_file
, automaton
);
7658 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7659 output_vect (VLA_HWINT_BEGIN (translate_vect
),
7660 VLA_HWINT_LENGTH (translate_vect
));
7661 fprintf (output_file
, "};\n\n");
7662 VLA_HWINT_DELETE (translate_vect
);
7665 /* The value in a table state x ainsn -> something which represents
7667 static int undefined_vect_el_value
;
7669 /* The following function returns nonzero value if the best
7670 representation of the table is comb vector. */
7673 state_ainsn_table_t tab
;
7675 return (2 * VLA_HWINT_LENGTH (tab
->full_vect
)
7676 > 5 * VLA_HWINT_LENGTH (tab
->comb_vect
));
7679 /* The following function creates new table for AUTOMATON. */
7680 static state_ainsn_table_t
7681 create_state_ainsn_table (automaton
)
7682 automaton_t automaton
;
7684 state_ainsn_table_t tab
;
7685 int full_vect_length
;
7688 tab
= create_node (sizeof (struct state_ainsn_table
));
7689 tab
->automaton
= automaton
;
7690 VLA_HWINT_CREATE (tab
->comb_vect
, 10000, "comb vector");
7691 VLA_HWINT_CREATE (tab
->check_vect
, 10000, "check vector");
7692 VLA_HWINT_CREATE (tab
->base_vect
, 1000, "base vector");
7693 VLA_HWINT_EXPAND (tab
->base_vect
, automaton
->achieved_states_num
);
7694 VLA_HWINT_CREATE (tab
->full_vect
, 10000, "full vector");
7695 full_vect_length
= (automaton
->insn_equiv_classes_num
7696 * automaton
->achieved_states_num
);
7697 VLA_HWINT_EXPAND (tab
->full_vect
, full_vect_length
);
7698 for (i
= 0; i
< full_vect_length
; i
++)
7699 VLA_HWINT (tab
->full_vect
, i
) = undefined_vect_el_value
;
7700 tab
->min_base_vect_el_value
= 0;
7701 tab
->max_base_vect_el_value
= 0;
7702 tab
->min_comb_vect_el_value
= 0;
7703 tab
->max_comb_vect_el_value
= 0;
7707 /* The following function outputs the best C representation of the
7708 table TAB of given TABLE_NAME. */
7710 output_state_ainsn_table (tab
, table_name
, output_full_vect_name_func
,
7711 output_comb_vect_name_func
,
7712 output_check_vect_name_func
,
7713 output_base_vect_name_func
)
7714 state_ainsn_table_t tab
;
7716 void (*output_full_vect_name_func
) PARAMS ((FILE *, automaton_t
));
7717 void (*output_comb_vect_name_func
) PARAMS ((FILE *, automaton_t
));
7718 void (*output_check_vect_name_func
) PARAMS ((FILE *, automaton_t
));
7719 void (*output_base_vect_name_func
) PARAMS ((FILE *, automaton_t
));
7721 if (!comb_vect_p (tab
))
7723 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7724 fprintf (output_file
, "static const ");
7725 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7726 tab
->max_comb_vect_el_value
);
7727 fprintf (output_file
, " ");
7728 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7729 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7730 output_vect (VLA_HWINT_BEGIN (tab
->full_vect
),
7731 VLA_HWINT_LENGTH (tab
->full_vect
));
7732 fprintf (output_file
, "};\n\n");
7736 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7737 fprintf (output_file
, "static const ");
7738 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7739 tab
->max_comb_vect_el_value
);
7740 fprintf (output_file
, " ");
7741 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7742 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7743 output_vect (VLA_HWINT_BEGIN (tab
->comb_vect
),
7744 VLA_HWINT_LENGTH (tab
->comb_vect
));
7745 fprintf (output_file
, "};\n\n");
7746 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7747 fprintf (output_file
, "static const ");
7748 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7749 fprintf (output_file
, " ");
7750 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7751 fprintf (output_file
, "[] = {\n");
7752 output_vect (VLA_HWINT_BEGIN (tab
->check_vect
),
7753 VLA_HWINT_LENGTH (tab
->check_vect
));
7754 fprintf (output_file
, "};\n\n");
7755 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7756 fprintf (output_file
, "static const ");
7757 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7758 tab
->max_base_vect_el_value
);
7759 fprintf (output_file
, " ");
7760 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7761 fprintf (output_file
, "[] = {\n");
7762 output_vect (VLA_HWINT_BEGIN (tab
->base_vect
),
7763 VLA_HWINT_LENGTH (tab
->base_vect
));
7764 fprintf (output_file
, "};\n\n");
7768 /* The following function adds vector with length VECT_LENGTH and
7769 elements pointed by VECT to table TAB as its line with number
7772 add_vect (tab
, vect_num
, vect
, vect_length
)
7773 state_ainsn_table_t tab
;
7778 int real_vect_length
;
7779 vect_el_t
*comb_vect_start
;
7780 vect_el_t
*check_vect_start
;
7781 int comb_vect_index
;
7782 int comb_vect_els_num
;
7784 int first_unempty_vect_index
;
7785 int additional_els_num
;
7790 if (vect_length
== 0)
7792 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7793 if (vect
[vect_length
- 1] == undefined_vect_el_value
)
7795 /* Form full vector in the table: */
7796 for (i
= 0; i
< vect_length
; i
++)
7797 VLA_HWINT (tab
->full_vect
,
7798 i
+ tab
->automaton
->insn_equiv_classes_num
* vect_num
)
7800 /* Form comb vector in the table: */
7801 if (VLA_HWINT_LENGTH (tab
->comb_vect
) != VLA_HWINT_LENGTH (tab
->check_vect
))
7803 comb_vect_start
= VLA_HWINT_BEGIN (tab
->comb_vect
);
7804 comb_vect_els_num
= VLA_HWINT_LENGTH (tab
->comb_vect
);
7805 for (first_unempty_vect_index
= 0;
7806 first_unempty_vect_index
< vect_length
;
7807 first_unempty_vect_index
++)
7808 if (vect
[first_unempty_vect_index
] != undefined_vect_el_value
)
7810 /* Search for the place in comb vect for the inserted vect. */
7811 for (comb_vect_index
= 0;
7812 comb_vect_index
< comb_vect_els_num
;
7815 for (vect_index
= first_unempty_vect_index
;
7816 vect_index
< vect_length
7817 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7819 if (vect
[vect_index
] != undefined_vect_el_value
7820 && (comb_vect_start
[vect_index
+ comb_vect_index
]
7821 != undefined_vect_el_value
))
7823 if (vect_index
>= vect_length
7824 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7827 /* Slot was found. */
7828 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7829 if (additional_els_num
< 0)
7830 additional_els_num
= 0;
7831 /* Expand comb and check vectors. */
7832 vect_el
= undefined_vect_el_value
;
7833 no_state_value
= tab
->automaton
->achieved_states_num
;
7834 while (additional_els_num
> 0)
7836 VLA_HWINT_ADD (tab
->comb_vect
, vect_el
);
7837 VLA_HWINT_ADD (tab
->check_vect
, no_state_value
);
7838 additional_els_num
--;
7840 comb_vect_start
= VLA_HWINT_BEGIN (tab
->comb_vect
);
7841 check_vect_start
= VLA_HWINT_BEGIN (tab
->check_vect
);
7842 if (VLA_HWINT_LENGTH (tab
->comb_vect
)
7843 < (size_t) (comb_vect_index
+ real_vect_length
))
7845 /* Fill comb and check vectors. */
7846 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7847 if (vect
[vect_index
] != undefined_vect_el_value
)
7849 if (comb_vect_start
[comb_vect_index
+ vect_index
]
7850 != undefined_vect_el_value
)
7852 comb_vect_start
[comb_vect_index
+ vect_index
] = vect
[vect_index
];
7853 if (vect
[vect_index
] < 0)
7855 if (tab
->max_comb_vect_el_value
< vect
[vect_index
])
7856 tab
->max_comb_vect_el_value
= vect
[vect_index
];
7857 if (tab
->min_comb_vect_el_value
> vect
[vect_index
])
7858 tab
->min_comb_vect_el_value
= vect
[vect_index
];
7859 check_vect_start
[comb_vect_index
+ vect_index
] = vect_num
;
7861 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7862 tab
->max_base_vect_el_value
= comb_vect_index
;
7863 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7864 tab
->min_base_vect_el_value
= comb_vect_index
;
7865 VLA_HWINT (tab
->base_vect
, vect_num
) = comb_vect_index
;
7868 /* Return number of out arcs of STATE. */
7870 out_state_arcs_num (state
)
7877 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7879 if (arc
->insn
== NULL
)
7881 if (arc
->insn
->first_ainsn_with_given_equialence_num
)
7887 /* Compare number of possible transitions from the states. */
7889 compare_transition_els_num (state_ptr_1
, state_ptr_2
)
7890 const void *state_ptr_1
;
7891 const void *state_ptr_2
;
7893 int transition_els_num_1
;
7894 int transition_els_num_2
;
7896 transition_els_num_1
= out_state_arcs_num (*(state_t
*) state_ptr_1
);
7897 transition_els_num_2
= out_state_arcs_num (*(state_t
*) state_ptr_2
);
7898 if (transition_els_num_1
< transition_els_num_2
)
7900 else if (transition_els_num_1
== transition_els_num_2
)
7906 /* The function adds element EL_VALUE to vector VECT for a table state
7909 add_vect_el (vect
, ainsn
, el_value
)
7914 int equiv_class_num
;
7919 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7920 for (vect_index
= VLA_HWINT_LENGTH (*vect
);
7921 vect_index
<= equiv_class_num
;
7923 VLA_HWINT_ADD (*vect
, undefined_vect_el_value
);
7924 VLA_HWINT (*vect
, equiv_class_num
) = el_value
;
7927 /* This is for forming vector of states of an automaton. */
7928 static vla_ptr_t output_states_vect
;
7930 /* The function is called by function pass_states. The function adds
7931 STATE to `output_states_vect'. */
7933 add_states_vect_el (state
)
7936 VLA_PTR_ADD (output_states_vect
, state
);
7939 /* Form and output vectors (comb, check, base or full vector)
7940 representing transition table of AUTOMATON. */
7942 output_trans_table (automaton
)
7943 automaton_t automaton
;
7947 vla_hwint_t transition_vect
;
7949 undefined_vect_el_value
= automaton
->achieved_states_num
;
7950 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7951 /* Create vect of pointers to states ordered by num of transitions
7952 from the state (state with the maximum num is the first). */
7953 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7954 pass_states (automaton
, add_states_vect_el
);
7955 qsort (VLA_PTR_BEGIN (output_states_vect
),
7956 VLA_PTR_LENGTH (output_states_vect
),
7957 sizeof (state_t
), compare_transition_els_num
);
7958 VLA_HWINT_CREATE (transition_vect
, 500, "transition vector");
7959 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7960 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7963 VLA_HWINT_NULLIFY (transition_vect
);
7964 for (arc
= first_out_arc (*state_ptr
);
7966 arc
= next_out_arc (arc
))
7968 if (arc
->insn
== NULL
)
7970 if (arc
->insn
->first_ainsn_with_given_equialence_num
)
7971 add_vect_el (&transition_vect
, arc
->insn
,
7972 arc
->to_state
->order_state_num
);
7974 add_vect (automaton
->trans_table
, (*state_ptr
)->order_state_num
,
7975 VLA_HWINT_BEGIN (transition_vect
),
7976 VLA_HWINT_LENGTH (transition_vect
));
7978 output_state_ainsn_table
7979 (automaton
->trans_table
, (char *) "state transitions",
7980 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7981 output_trans_check_vect_name
, output_trans_base_vect_name
);
7982 VLA_PTR_DELETE (output_states_vect
);
7983 VLA_HWINT_DELETE (transition_vect
);
7986 /* Form and output vectors (comb, check, base or simple vect)
7987 representing alts number table of AUTOMATON. The table is state x
7988 ainsn -> number of possible alternative reservations by the
7991 output_state_alts_table (automaton
)
7992 automaton_t automaton
;
7996 vla_hwint_t state_alts_vect
;
7998 undefined_vect_el_value
= 0; /* no alts when transition is not possible */
7999 automaton
->state_alts_table
= create_state_ainsn_table (automaton
);
8000 /* Create vect of pointers to states ordered by num of transitions
8001 from the state (state with the maximum num is the first). */
8002 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8003 pass_states (automaton
, add_states_vect_el
);
8004 qsort (VLA_PTR_BEGIN (output_states_vect
),
8005 VLA_PTR_LENGTH (output_states_vect
),
8006 sizeof (state_t
), compare_transition_els_num
);
8007 /* Create base, comb, and check vectors. */
8008 VLA_HWINT_CREATE (state_alts_vect
, 500, "state alts vector");
8009 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8010 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8013 VLA_HWINT_NULLIFY (state_alts_vect
);
8014 for (arc
= first_out_arc (*state_ptr
);
8016 arc
= next_out_arc (arc
))
8018 if (arc
->insn
== NULL
)
8020 if (arc
->insn
->first_ainsn_with_given_equialence_num
)
8021 add_vect_el (&state_alts_vect
, arc
->insn
, arc
->state_alts
);
8023 add_vect (automaton
->state_alts_table
, (*state_ptr
)->order_state_num
,
8024 VLA_HWINT_BEGIN (state_alts_vect
),
8025 VLA_HWINT_LENGTH (state_alts_vect
));
8027 output_state_ainsn_table
8028 (automaton
->state_alts_table
, (char *) "state insn alternatives",
8029 output_state_alts_full_vect_name
, output_state_alts_comb_vect_name
,
8030 output_state_alts_check_vect_name
, output_state_alts_base_vect_name
);
8031 VLA_PTR_DELETE (output_states_vect
);
8032 VLA_HWINT_DELETE (state_alts_vect
);
8035 /* The current number of passing states to find minimal issue delay
8036 value for an ainsn and state. */
8037 static int curr_state_pass_num
;
8039 /* This recursive function passes states to find minimal issue delay
8040 value for AINSN. The state being visited is STATE. The function
8041 returns minimal issue delay value for AINSN in STATE or -1 if we
8042 enter into a loop. */
8044 min_issue_delay_pass_states (state
, ainsn
)
8049 int min_insn_issue_delay
, insn_issue_delay
;
8051 if (state
->state_pass_num
== curr_state_pass_num
8052 || state
->min_insn_issue_delay
!= -1)
8053 /* We've entered into a loop or already have the correct value for
8054 given state and ainsn. */
8055 return state
->min_insn_issue_delay
;
8056 state
->state_pass_num
= curr_state_pass_num
;
8057 min_insn_issue_delay
= -1;
8058 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
8059 if (arc
->insn
== ainsn
)
8061 min_insn_issue_delay
= 0;
8066 insn_issue_delay
= min_issue_delay_pass_states (arc
->to_state
, ainsn
);
8067 if (insn_issue_delay
!= -1)
8069 if (arc
->insn
->insn_reserv_decl
8070 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
8072 if (min_insn_issue_delay
== -1
8073 || min_insn_issue_delay
> insn_issue_delay
)
8075 min_insn_issue_delay
= insn_issue_delay
;
8076 if (insn_issue_delay
== 0)
8081 return min_insn_issue_delay
;
8084 /* The function searches minimal issue delay value for AINSN in STATE.
8085 The function can return negative value if we can not issue AINSN. We
8086 will report about it later. */
8088 min_issue_delay (state
, ainsn
)
8092 curr_state_pass_num
++;
8093 state
->min_insn_issue_delay
= min_issue_delay_pass_states (state
, ainsn
);
8094 return state
->min_insn_issue_delay
;
8097 /* The function initiates code for finding minimal issue delay values.
8098 It should be called only once. */
8100 initiate_min_issue_delay_pass_states ()
8102 curr_state_pass_num
= 0;
8105 /* Form and output vectors representing minimal issue delay table of
8106 AUTOMATON. The table is state x ainsn -> minimal issue delay of
8109 output_min_issue_delay_table (automaton
)
8110 automaton_t automaton
;
8112 vla_hwint_t min_issue_delay_vect
;
8113 vla_hwint_t compressed_min_issue_delay_vect
;
8114 vect_el_t min_delay
;
8119 /* Create vect of pointers to states ordered by num of transitions
8120 from the state (state with the maximum num is the first). */
8121 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8122 pass_states (automaton
, add_states_vect_el
);
8123 VLA_HWINT_CREATE (min_issue_delay_vect
, 1500, "min issue delay vector");
8124 VLA_HWINT_EXPAND (min_issue_delay_vect
,
8125 VLA_HWINT_LENGTH (output_states_vect
)
8126 * automaton
->insn_equiv_classes_num
);
8128 i
< ((int) VLA_HWINT_LENGTH (output_states_vect
)
8129 * automaton
->insn_equiv_classes_num
);
8131 VLA_HWINT (min_issue_delay_vect
, i
) = 0;
8132 automaton
->max_min_delay
= 0;
8133 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
8134 if (ainsn
->first_ainsn_with_given_equialence_num
)
8136 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8137 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8139 (*state_ptr
)->min_insn_issue_delay
= -1;
8140 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8141 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8144 min_delay
= min_issue_delay (*state_ptr
, ainsn
);
8145 if (automaton
->max_min_delay
< min_delay
)
8146 automaton
->max_min_delay
= min_delay
;
8147 VLA_HWINT (min_issue_delay_vect
,
8148 (*state_ptr
)->order_state_num
8149 * automaton
->insn_equiv_classes_num
8150 + ainsn
->insn_equiv_class_num
) = min_delay
;
8153 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
8154 fprintf (output_file
, "static const ");
8155 output_range_type (output_file
, 0, automaton
->max_min_delay
);
8156 fprintf (output_file
, " ");
8157 output_min_issue_delay_vect_name (output_file
, automaton
);
8158 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
8159 /* Compress the vector */
8160 if (automaton
->max_min_delay
< 2)
8161 automaton
->min_issue_delay_table_compression_factor
= 8;
8162 else if (automaton
->max_min_delay
< 4)
8163 automaton
->min_issue_delay_table_compression_factor
= 4;
8164 else if (automaton
->max_min_delay
< 16)
8165 automaton
->min_issue_delay_table_compression_factor
= 2;
8167 automaton
->min_issue_delay_table_compression_factor
= 1;
8168 VLA_HWINT_CREATE (compressed_min_issue_delay_vect
, 1500,
8169 "compressed min issue delay vector");
8170 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect
,
8171 (VLA_HWINT_LENGTH (min_issue_delay_vect
)
8172 + automaton
->min_issue_delay_table_compression_factor
8174 / automaton
->min_issue_delay_table_compression_factor
);
8176 i
< (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect
);
8178 VLA_HWINT (compressed_min_issue_delay_vect
, i
) = 0;
8179 for (i
= 0; i
< (int) VLA_HWINT_LENGTH (min_issue_delay_vect
); i
++)
8180 VLA_HWINT (compressed_min_issue_delay_vect
,
8181 i
/ automaton
->min_issue_delay_table_compression_factor
)
8182 |= (VLA_HWINT (min_issue_delay_vect
, i
)
8183 << (8 - (i
% automaton
->min_issue_delay_table_compression_factor
8185 * (8 / automaton
->min_issue_delay_table_compression_factor
)));
8186 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect
),
8187 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect
));
8188 fprintf (output_file
, "};\n\n");
8189 VLA_PTR_DELETE (output_states_vect
);
8190 VLA_HWINT_DELETE (min_issue_delay_vect
);
8191 VLA_HWINT_DELETE (compressed_min_issue_delay_vect
);
8195 /* Number of states which contains transition only by advancing cpu
8197 static int locked_states_num
;
8200 /* Form and output vector representing the locked states of
8203 output_dead_lock_vect (automaton
)
8204 automaton_t automaton
;
8208 vla_hwint_t dead_lock_vect
;
8210 /* Create vect of pointers to states ordered by num of
8211 transitions from the state (state with the maximum num is the
8213 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8214 pass_states (automaton
, add_states_vect_el
);
8215 VLA_HWINT_CREATE (dead_lock_vect
, 1500, "is dead locked vector");
8216 VLA_HWINT_EXPAND (dead_lock_vect
, VLA_HWINT_LENGTH (output_states_vect
));
8217 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8218 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8221 arc
= first_out_arc (*state_ptr
);
8224 VLA_HWINT (dead_lock_vect
, (*state_ptr
)->order_state_num
)
8225 = (next_out_arc (arc
) == NULL
8226 && (arc
->insn
->insn_reserv_decl
8227 == DECL_INSN_RESERV (advance_cycle_insn_decl
)) ? 1 : 0);
8229 if (VLA_HWINT (dead_lock_vect
, (*state_ptr
)->order_state_num
))
8230 locked_states_num
++;
8233 fprintf (output_file
, "/* Vector for locked state flags. */\n");
8234 fprintf (output_file
, "static const ");
8235 output_range_type (output_file
, 0, 1);
8236 fprintf (output_file
, " ");
8237 output_dead_lock_vect_name (output_file
, automaton
);
8238 fprintf (output_file
, "[] = {\n");
8239 output_vect (VLA_HWINT_BEGIN (dead_lock_vect
),
8240 VLA_HWINT_LENGTH (dead_lock_vect
));
8241 fprintf (output_file
, "};\n\n");
8242 VLA_HWINT_DELETE (dead_lock_vect
);
8243 VLA_PTR_DELETE (output_states_vect
);
8246 /* Form and output vector representing reserved units of the states of
8249 output_reserved_units_table (automaton
)
8250 automaton_t automaton
;
8252 state_t
*curr_state_ptr
;
8253 vla_hwint_t reserved_units_table
;
8254 size_t state_byte_size
;
8257 /* Create vect of pointers to states. */
8258 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8259 pass_states (automaton
, add_states_vect_el
);
8260 /* Create vector. */
8261 VLA_HWINT_CREATE (reserved_units_table
, 1500, "reserved units vector");
8262 state_byte_size
= (description
->query_units_num
+ 7) / 8;
8263 VLA_HWINT_EXPAND (reserved_units_table
,
8264 VLA_HWINT_LENGTH (output_states_vect
) * state_byte_size
);
8266 i
< (int) (VLA_HWINT_LENGTH (output_states_vect
) * state_byte_size
);
8268 VLA_HWINT (reserved_units_table
, i
) = 0;
8269 for (curr_state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8270 curr_state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8273 for (i
= 0; i
< description
->units_num
; i
++)
8274 if (units_array
[i
]->query_p
8275 && first_cycle_unit_presence (*curr_state_ptr
, i
))
8276 VLA_HWINT (reserved_units_table
,
8277 (*curr_state_ptr
)->order_state_num
* state_byte_size
8278 + units_array
[i
]->query_num
/ 8)
8279 += (1 << (units_array
[i
]->query_num
% 8));
8281 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
8282 fprintf (output_file
, "static const ");
8283 output_range_type (output_file
, 0, 255);
8284 fprintf (output_file
, " ");
8285 output_reserved_units_table_name (output_file
, automaton
);
8286 fprintf (output_file
, "[] = {\n");
8287 output_vect (VLA_HWINT_BEGIN (reserved_units_table
),
8288 VLA_HWINT_LENGTH (reserved_units_table
));
8289 fprintf (output_file
, "};\n\n");
8290 VLA_HWINT_DELETE (reserved_units_table
);
8291 VLA_PTR_DELETE (output_states_vect
);
8294 /* The function outputs all tables representing DFA(s) used for fast
8295 pipeline hazards recognition. */
8299 automaton_t automaton
;
8302 locked_states_num
= 0;
8304 initiate_min_issue_delay_pass_states ();
8305 for (automaton
= description
->first_automaton
;
8307 automaton
= automaton
->next_automaton
)
8309 output_translate_vect (automaton
);
8310 output_trans_table (automaton
);
8311 fprintf (output_file
, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME
);
8312 output_state_alts_table (automaton
);
8313 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
8314 AUTOMATON_STATE_ALTS_MACRO_NAME
);
8315 output_min_issue_delay_table (automaton
);
8316 output_dead_lock_vect (automaton
);
8317 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
8318 output_reserved_units_table (automaton
);
8319 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
8320 CPU_UNITS_QUERY_MACRO_NAME
);
8322 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
8323 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8326 /* The function outputs definition and value of PHR interface variable
8327 `max_insn_queue_index'. Its value is not less than maximal queue
8328 length needed for the insn scheduler. */
8330 output_max_insn_queue_index_def ()
8332 int i
, max
, latency
;
8335 max
= description
->max_insn_reserv_cycles
;
8336 for (i
= 0; i
< description
->decls_num
; i
++)
8338 decl
= description
->decls
[i
];
8339 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8341 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
8345 else if (decl
->mode
== dm_bypass
)
8347 latency
= DECL_BYPASS (decl
)->latency
;
8352 for (i
= 0; (1 << i
) <= max
; i
++)
8356 fprintf (output_file
, "\nint max_insn_queue_index = %d;\n\n", (1 << i
) - 1);
8360 /* The function outputs switch cases for insn reseravtions using
8361 function *output_automata_list_code. */
8363 output_insn_code_cases (output_automata_list_code
)
8364 void (*output_automata_list_code
) PARAMS ((automata_list_el_t
));
8369 for (i
= 0; i
< description
->decls_num
; i
++)
8371 decl
= description
->decls
[i
];
8372 if (decl
->mode
== dm_insn_reserv
)
8373 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
8375 for (i
= 0; i
< description
->decls_num
; i
++)
8377 decl
= description
->decls
[i
];
8378 if (decl
->mode
== dm_insn_reserv
8379 && !DECL_INSN_RESERV (decl
)->processed_p
)
8381 for (j
= i
; j
< description
->decls_num
; j
++)
8383 decl2
= description
->decls
[j
];
8384 if (decl2
->mode
== dm_insn_reserv
8385 && (DECL_INSN_RESERV (decl2
)->important_automata_list
8386 == DECL_INSN_RESERV (decl
)->important_automata_list
))
8388 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
8389 fprintf (output_file
, " case %d: /* %s */\n",
8390 DECL_INSN_RESERV (decl2
)->insn_num
,
8391 DECL_INSN_RESERV (decl2
)->name
);
8394 (*output_automata_list_code
)
8395 (DECL_INSN_RESERV (decl
)->important_automata_list
);
8401 /* The function outputs a code for evaluation of a minimal delay of
8402 issue of insns which have reservations in given AUTOMATA_LIST. */
8404 output_automata_list_min_issue_delay_code (automata_list
)
8405 automata_list_el_t automata_list
;
8407 automata_list_el_t el
;
8408 automaton_t automaton
;
8410 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8412 automaton
= el
->automaton
;
8413 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8414 output_min_issue_delay_vect_name (output_file
, automaton
);
8415 fprintf (output_file
,
8416 (automaton
->min_issue_delay_table_compression_factor
!= 1
8418 output_translate_vect_name (output_file
, automaton
);
8419 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8420 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8421 output_chip_member_name (output_file
, automaton
);
8422 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
8423 if (automaton
->min_issue_delay_table_compression_factor
== 1)
8424 fprintf (output_file
, "];\n");
8427 fprintf (output_file
, ") / %d];\n",
8428 automaton
->min_issue_delay_table_compression_factor
);
8429 fprintf (output_file
, " %s = (%s >> (8 - (",
8430 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8431 output_translate_vect_name (output_file
, automaton
);
8433 (output_file
, " [%s] %% %d + 1) * %d)) & %d;\n",
8434 INTERNAL_INSN_CODE_NAME
,
8435 automaton
->min_issue_delay_table_compression_factor
,
8436 8 / automaton
->min_issue_delay_table_compression_factor
,
8437 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
8440 if (el
== automata_list
)
8441 fprintf (output_file
, " %s = %s;\n",
8442 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8445 fprintf (output_file
, " if (%s > %s)\n",
8446 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8447 fprintf (output_file
, " %s = %s;\n",
8448 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8451 fprintf (output_file
, " break;\n\n");
8454 /* Output function `internal_min_issue_delay'. */
8456 output_internal_min_issue_delay_func ()
8458 fprintf (output_file
, "static int %s PARAMS ((int, struct %s *));\n",
8459 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, CHIP_NAME
);
8460 fprintf (output_file
,
8461 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8462 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8463 CHIP_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
,
8464 CHIP_PARAMETER_NAME
);
8465 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8466 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8467 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8468 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
8469 fprintf (output_file
,
8470 "\n default:\n %s = -1;\n break;\n }\n",
8471 RESULT_VARIABLE_NAME
);
8472 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8473 fprintf (output_file
, "}\n\n");
8476 /* The function outputs a code changing state after issue of insns
8477 which have reservations in given AUTOMATA_LIST. */
8479 output_automata_list_transition_code (automata_list
)
8480 automata_list_el_t automata_list
;
8482 automata_list_el_t el
, next_el
;
8484 fprintf (output_file
, " {\n");
8485 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8486 for (el
= automata_list
;; el
= next_el
)
8488 next_el
= el
->next_automata_list_el
;
8489 if (next_el
== NULL
)
8491 fprintf (output_file
, " ");
8492 output_state_member_type (output_file
, el
->automaton
);
8493 fprintf (output_file
, " ");
8494 output_temp_chip_member_name (output_file
, el
->automaton
);
8495 fprintf (output_file
, ";\n");
8497 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8498 if (comb_vect_p (el
->automaton
->trans_table
))
8500 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8501 output_trans_base_vect_name (output_file
, el
->automaton
);
8502 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8503 output_chip_member_name (output_file
, el
->automaton
);
8504 fprintf (output_file
, "] + ");
8505 output_translate_vect_name (output_file
, el
->automaton
);
8506 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8507 fprintf (output_file
, " if (");
8508 output_trans_check_vect_name (output_file
, el
->automaton
);
8509 fprintf (output_file
, " [%s] != %s->",
8510 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8511 output_chip_member_name (output_file
, el
->automaton
);
8512 fprintf (output_file
, ")\n");
8513 fprintf (output_file
, " return %s (%s, %s);\n",
8514 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8515 CHIP_PARAMETER_NAME
);
8516 fprintf (output_file
, " else\n");
8517 fprintf (output_file
, " ");
8518 if (el
->next_automata_list_el
!= NULL
)
8519 output_temp_chip_member_name (output_file
, el
->automaton
);
8522 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8523 output_chip_member_name (output_file
, el
->automaton
);
8525 fprintf (output_file
, " = ");
8526 output_trans_comb_vect_name (output_file
, el
->automaton
);
8527 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8531 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8532 output_trans_full_vect_name (output_file
, el
->automaton
);
8533 fprintf (output_file
, " [");
8534 output_translate_vect_name (output_file
, el
->automaton
);
8535 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8536 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8537 output_chip_member_name (output_file
, el
->automaton
);
8538 fprintf (output_file
, " * %d];\n",
8539 el
->automaton
->insn_equiv_classes_num
);
8540 fprintf (output_file
, " if (%s >= %d)\n",
8541 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
8542 fprintf (output_file
, " return %s (%s, %s);\n",
8543 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8544 CHIP_PARAMETER_NAME
);
8545 fprintf (output_file
, " else\n ");
8546 if (el
->next_automata_list_el
!= NULL
)
8547 output_temp_chip_member_name (output_file
, el
->automaton
);
8550 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8551 output_chip_member_name (output_file
, el
->automaton
);
8553 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
8555 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8556 for (el
= automata_list
;; el
= next_el
)
8558 next_el
= el
->next_automata_list_el
;
8559 if (next_el
== NULL
)
8561 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
8562 output_chip_member_name (output_file
, el
->automaton
);
8563 fprintf (output_file
, " = ");
8564 output_temp_chip_member_name (output_file
, el
->automaton
);
8565 fprintf (output_file
, ";\n");
8567 fprintf (output_file
, " return -1;\n");
8568 fprintf (output_file
, " }\n");
8571 /* Output function `internal_state_transition'. */
8573 output_internal_trans_func ()
8575 fprintf (output_file
, "static int %s PARAMS ((int, struct %s *));\n",
8576 INTERNAL_TRANSITION_FUNC_NAME
, CHIP_NAME
);
8577 fprintf (output_file
,
8578 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8579 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8580 CHIP_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
,
8581 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8582 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
8583 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8584 output_insn_code_cases (output_automata_list_transition_code
);
8585 fprintf (output_file
, "\n default:\n return -1;\n }\n");
8586 fprintf (output_file
, "}\n\n");
8593 insn_code = dfa_insn_code (insn);
8594 if (insn_code > DFA__ADVANCE_CYCLE)
8598 insn_code = DFA__ADVANCE_CYCLE;
8600 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8601 code denotes CODE. */
8603 output_internal_insn_code_evaluation (insn_name
, insn_code_name
, code
)
8604 const char *insn_name
;
8605 const char *insn_code_name
;
8608 fprintf (output_file
, "\n if (%s != 0)\n {\n", insn_name
);
8609 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
8610 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
8611 fprintf (output_file
, " if (%s > %s)\n return %d;\n",
8612 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
8613 fprintf (output_file
, " }\n else\n %s = %s;\n\n",
8614 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
8618 /* The function outputs function `dfa_insn_code'. */
8620 output_dfa_insn_code_func ()
8622 fprintf (output_file
, "#ifdef __GNUC__\n__inline__\n#endif\n");
8623 fprintf (output_file
, "static int %s PARAMS ((rtx));\n",
8624 DFA_INSN_CODE_FUNC_NAME
);
8625 fprintf (output_file
, "static int\n%s (%s)\n\trtx %s;\n",
8626 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN_PARAMETER_NAME
);
8627 fprintf (output_file
, "{\n int %s;\n int %s;\n\n",
8628 INTERNAL_INSN_CODE_NAME
, TEMPORARY_VARIABLE_NAME
);
8629 fprintf (output_file
, " if (INSN_UID (%s) >= %s)\n {\n",
8630 INSN_PARAMETER_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8631 fprintf (output_file
, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
8632 TEMPORARY_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8633 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, INSN_PARAMETER_NAME
);
8634 fprintf (output_file
, " %s = xrealloc (%s, %s * sizeof (int));\n",
8635 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8636 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8637 fprintf (output_file
,
8638 " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
8639 TEMPORARY_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8640 TEMPORARY_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8641 TEMPORARY_VARIABLE_NAME
);
8642 fprintf (output_file
, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
8643 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8644 INSN_PARAMETER_NAME
);
8645 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8646 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8647 fprintf (output_file
, " %s [INSN_UID (%s)] = %s;\n",
8648 DFA_INSN_CODES_VARIABLE_NAME
, INSN_PARAMETER_NAME
,
8649 INTERNAL_INSN_CODE_NAME
);
8650 fprintf (output_file
, " }\n return %s;\n}\n\n",
8651 INTERNAL_INSN_CODE_NAME
);
8654 /* The function outputs PHR interface function `state_transition'. */
8656 output_trans_func ()
8658 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8659 TRANSITION_FUNC_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
,
8660 STATE_TYPE_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
);
8661 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8662 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8663 INTERNAL_INSN_CODE_NAME
, -1);
8664 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8665 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
8668 /* The function outputs a code for evaluation of alternative states
8669 number for insns which have reservations in given AUTOMATA_LIST. */
8671 output_automata_list_state_alts_code (automata_list
)
8672 automata_list_el_t automata_list
;
8674 automata_list_el_t el
;
8675 automaton_t automaton
;
8677 fprintf (output_file
, " {\n");
8678 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8679 if (comb_vect_p (el
->automaton
->state_alts_table
))
8681 fprintf (output_file
, " int %s;\n", TEMPORARY_VARIABLE_NAME
);
8684 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8686 automaton
= el
->automaton
;
8687 if (comb_vect_p (automaton
->state_alts_table
))
8689 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8690 output_state_alts_base_vect_name (output_file
, automaton
);
8691 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8692 output_chip_member_name (output_file
, automaton
);
8693 fprintf (output_file
, "] + ");
8694 output_translate_vect_name (output_file
, automaton
);
8695 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8696 fprintf (output_file
, " if (");
8697 output_state_alts_check_vect_name (output_file
, automaton
);
8698 fprintf (output_file
, " [%s] != %s->",
8699 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8700 output_chip_member_name (output_file
, automaton
);
8701 fprintf (output_file
, ")\n");
8702 fprintf (output_file
, " return 0;\n");
8703 fprintf (output_file
, " else\n");
8704 fprintf (output_file
,
8705 (el
== automata_list
8706 ? " %s = " : " %s += "),
8707 RESULT_VARIABLE_NAME
);
8708 output_state_alts_comb_vect_name (output_file
, automaton
);
8709 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8713 fprintf (output_file
,
8714 (el
== automata_list
8715 ? "\n %s = " : " %s += "),
8716 RESULT_VARIABLE_NAME
);
8717 output_state_alts_full_vect_name (output_file
, automaton
);
8718 fprintf (output_file
, " [");
8719 output_translate_vect_name (output_file
, automaton
);
8720 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8721 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8722 output_chip_member_name (output_file
, automaton
);
8723 fprintf (output_file
, " * %d];\n",
8724 automaton
->insn_equiv_classes_num
);
8727 fprintf (output_file
, " break;\n }\n\n");
8730 /* Output function `internal_state_alts'. */
8732 output_internal_state_alts_func ()
8734 fprintf (output_file
, "static int %s PARAMS ((int, struct %s *));\n",
8735 INTERNAL_STATE_ALTS_FUNC_NAME
, CHIP_NAME
);
8736 fprintf (output_file
,
8737 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8738 INTERNAL_STATE_ALTS_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8739 CHIP_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
,
8740 CHIP_PARAMETER_NAME
);
8741 fprintf (output_file
, "{\n int %s;\n", RESULT_VARIABLE_NAME
);
8742 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8743 output_insn_code_cases (output_automata_list_state_alts_code
);
8744 fprintf (output_file
,
8745 "\n default:\n %s = 0;\n break;\n }\n",
8746 RESULT_VARIABLE_NAME
);
8747 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8748 fprintf (output_file
, "}\n\n");
8751 /* The function outputs PHR interface function `state_alts'. */
8753 output_state_alts_func ()
8755 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8756 STATE_ALTS_FUNC_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
,
8757 STATE_TYPE_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
);
8758 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8759 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8760 INTERNAL_INSN_CODE_NAME
, 0);
8761 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8762 INTERNAL_STATE_ALTS_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
8765 /* Output function `min_issue_delay'. */
8767 output_min_issue_delay_func ()
8769 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8770 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
,
8771 STATE_TYPE_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
);
8772 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8773 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8774 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8775 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8776 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8777 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8778 fprintf (output_file
, " }\n else\n %s = %s;\n",
8779 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8780 fprintf (output_file
, "\n return %s (%s, %s);\n",
8781 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8783 fprintf (output_file
, "}\n\n");
8786 /* Output function `internal_dead_lock'. */
8788 output_internal_dead_lock_func ()
8790 automaton_t automaton
;
8792 fprintf (output_file
, "static int %s PARAMS ((struct %s *));\n",
8793 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
);
8794 fprintf (output_file
, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8795 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_PARAMETER_NAME
, CHIP_NAME
,
8796 CHIP_PARAMETER_NAME
);
8797 fprintf (output_file
, "{\n");
8798 for (automaton
= description
->first_automaton
;
8800 automaton
= automaton
->next_automaton
)
8802 fprintf (output_file
, " if (");
8803 output_dead_lock_vect_name (output_file
, automaton
);
8804 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8805 output_chip_member_name (output_file
, automaton
);
8806 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8808 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8811 /* The function outputs PHR interface function `state_dead_lock_p'. */
8813 output_dead_lock_func ()
8815 fprintf (output_file
, "int\n%s (%s)\n\t%s %s;\n",
8816 DEAD_LOCK_FUNC_NAME
, STATE_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8817 fprintf (output_file
, "{\n return %s (%s);\n}\n\n",
8818 INTERNAL_DEAD_LOCK_FUNC_NAME
, STATE_NAME
);
8821 /* Output function `internal_reset'. */
8823 output_internal_reset_func ()
8825 fprintf (output_file
, "static void %s PARAMS ((struct %s *));\n",
8826 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8827 fprintf (output_file
, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8828 INTERNAL_RESET_FUNC_NAME
, CHIP_PARAMETER_NAME
,
8829 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8830 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8831 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8834 /* The function outputs PHR interface function `state_size'. */
8838 fprintf (output_file
, "int\n%s ()\n", SIZE_FUNC_NAME
);
8839 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8842 /* The function outputs PHR interface function `state_reset'. */
8844 output_reset_func ()
8846 fprintf (output_file
, "void\n%s (%s)\n\t %s %s;\n",
8847 RESET_FUNC_NAME
, STATE_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8848 fprintf (output_file
, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8852 /* Output function `min_insn_conflict_delay'. */
8854 output_min_insn_conflict_delay_func ()
8856 fprintf (output_file
,
8857 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8858 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
,
8859 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
,
8860 STATE_TYPE_NAME
, STATE_NAME
,
8861 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8862 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s;\n",
8863 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8864 INTERNAL_INSN2_CODE_NAME
);
8865 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8866 INTERNAL_INSN_CODE_NAME
, 0);
8867 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8868 INTERNAL_INSN2_CODE_NAME
, 0);
8869 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8870 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8871 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8872 fprintf (output_file
, " if (%s (%s, &%s) > 0)\n abort ();\n",
8873 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8874 fprintf (output_file
, " return %s (%s, &%s);\n",
8875 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8877 fprintf (output_file
, "}\n\n");
8880 /* Output function `internal_insn_latency'. */
8882 output_internal_insn_latency_func ()
8885 struct bypass_decl
*bypass
;
8888 fprintf (output_file
, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8889 INTERNAL_INSN_LATENCY_FUNC_NAME
);
8890 fprintf (output_file
, "static int\n%s (%s, %s, %s, %s)",
8891 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8892 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8893 INSN2_PARAMETER_NAME
);
8894 fprintf (output_file
, "\n\tint %s;\n\tint %s;\n",
8895 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8896 fprintf (output_file
,
8897 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
8898 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8899 fprintf (output_file
, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8900 for (i
= 0; i
< description
->decls_num
; i
++)
8902 decl
= description
->decls
[i
];
8903 if (decl
->mode
== dm_insn_reserv
)
8905 fprintf (output_file
, " case %d:\n",
8906 DECL_INSN_RESERV (decl
)->insn_num
);
8907 if (DECL_INSN_RESERV (decl
)->bypass_list
== NULL
)
8908 fprintf (output_file
, " return (%s != %s ? %d : 0);\n",
8909 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8910 DECL_INSN_RESERV (decl
)->default_latency
);
8913 fprintf (output_file
, " switch (%s)\n {\n",
8914 INTERNAL_INSN2_CODE_NAME
);
8915 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8917 bypass
= bypass
->next
)
8919 fprintf (output_file
, " case %d:\n",
8920 bypass
->in_insn_reserv
->insn_num
);
8921 if (bypass
->bypass_guard_name
== NULL
)
8922 fprintf (output_file
, " return %d;\n",
8925 fprintf (output_file
,
8926 " return (%s (%s, %s) ? %d : %d);\n",
8927 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8928 INSN2_PARAMETER_NAME
, bypass
->latency
,
8929 DECL_INSN_RESERV (decl
)->default_latency
);
8931 fprintf (output_file
, " default:\n");
8932 fprintf (output_file
,
8933 " return (%s != %s ? %d : 0);\n }\n",
8934 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8935 DECL_INSN_RESERV (decl
)->default_latency
);
8940 fprintf (output_file
, " default:\n return 0;\n }\n}\n\n");
8943 /* The function outputs PHR interface function `insn_latency'. */
8945 output_insn_latency_func ()
8947 fprintf (output_file
, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
8948 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
,
8949 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8950 fprintf (output_file
, "{\n int %s, %s;\n",
8951 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8952 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8953 INTERNAL_INSN_CODE_NAME
, 0);
8954 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8955 INTERNAL_INSN2_CODE_NAME
, 0);
8956 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
8957 INTERNAL_INSN_LATENCY_FUNC_NAME
,
8958 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
8959 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8962 /* The function outputs PHR interface function `print_reservation'. */
8964 output_print_reservation_func ()
8969 fprintf (output_file
, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
8970 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
8971 INSN_PARAMETER_NAME
, FILE_PARAMETER_NAME
,
8972 INSN_PARAMETER_NAME
);
8973 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8974 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8975 fprintf (output_file
, " %s = %s (%s);\n",
8976 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8977 INSN_PARAMETER_NAME
);
8978 fprintf (output_file
, " if (%s > %s)\n",
8979 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8980 fprintf (output_file
, " {\n fprintf (%s, \"%s\");\n",
8981 FILE_PARAMETER_NAME
, NOTHING_NAME
);
8982 fprintf (output_file
, " return;\n }\n");
8983 fprintf (output_file
, " }\n else\n");
8984 fprintf (output_file
,
8985 " {\n fprintf (%s, \"%s\");\n return;\n }\n",
8986 FILE_PARAMETER_NAME
, NOTHING_NAME
);
8987 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8988 for (i
= 0; i
< description
->decls_num
; i
++)
8990 decl
= description
->decls
[i
];
8991 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8993 fprintf (output_file
,
8994 " case %d:\n", DECL_INSN_RESERV (decl
)->insn_num
);
8995 fprintf (output_file
,
8996 " fprintf (%s, \"%s\");\n break;\n",
8997 FILE_PARAMETER_NAME
,
8998 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
8999 finish_regexp_representation ();
9002 fprintf (output_file
, " default:\n fprintf (%s, \"%s\");\n }\n",
9003 FILE_PARAMETER_NAME
, NOTHING_NAME
);
9004 fprintf (output_file
, "}\n\n");
9007 /* The following function is used to sort unit declaration by their
9010 units_cmp (unit1
, unit2
)
9011 const void *unit1
, *unit2
;
9013 const unit_decl_t u1
= *(unit_decl_t
*) unit1
;
9014 const unit_decl_t u2
= *(unit_decl_t
*) unit2
;
9016 return strcmp (u1
->name
, u2
->name
);
9019 /* The following macro value is name of struct containing unit name
9021 #define NAME_CODE_STRUCT_NAME "name_code"
9023 /* The following macro value is name of table of struct name_code. */
9024 #define NAME_CODE_TABLE_NAME "name_code_table"
9026 /* The following macro values are member names for struct name_code. */
9027 #define NAME_MEMBER_NAME "name"
9028 #define CODE_MEMBER_NAME "code"
9030 /* The following macro values are local variable names for function
9031 `get_cpu_unit_code'. */
9032 #define CMP_VARIABLE_NAME "cmp"
9033 #define LOW_VARIABLE_NAME "l"
9034 #define MIDDLE_VARIABLE_NAME "m"
9035 #define HIGH_VARIABLE_NAME "h"
9037 /* The following function outputs function to obtain internal cpu unit
9038 code by the cpu unit name. */
9040 output_get_cpu_unit_code_func ()
9045 fprintf (output_file
, "int\n%s (%s)\n\tconst char *%s;\n",
9046 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
9047 CPU_UNIT_NAME_PARAMETER_NAME
);
9048 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
9049 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
9050 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
9051 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
9052 fprintf (output_file
, " static struct %s %s [] =\n {\n",
9053 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
9054 units
= (unit_decl_t
*) xmalloc (sizeof (unit_decl_t
)
9055 * description
->units_num
);
9056 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
9057 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
9058 for (i
= 0; i
< description
->units_num
; i
++)
9059 if (units
[i
]->query_p
)
9060 fprintf (output_file
, " {\"%s\", %d},\n",
9061 units
[i
]->name
, units
[i
]->query_num
);
9062 fprintf (output_file
, " };\n\n");
9063 fprintf (output_file
, " /* The following is binary search: */\n");
9064 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
9065 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
9066 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
9067 fprintf (output_file
, " while (%s <= %s)\n {\n",
9068 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
9069 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
9070 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
9071 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
9072 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
9073 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
9074 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
9075 fprintf (output_file
, " %s = %s - 1;\n",
9076 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
9077 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
9078 fprintf (output_file
, " %s = %s + 1;\n",
9079 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
9080 fprintf (output_file
, " else\n");
9081 fprintf (output_file
, " return %s [%s].%s;\n }\n",
9082 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
9083 fprintf (output_file
, " return -1;\n}\n\n");
9087 /* The following function outputs function to check reservation of cpu
9088 unit (its internal code will be passed as the function argument) in
9091 output_cpu_unit_reservation_p ()
9093 automaton_t automaton
;
9095 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
9096 CPU_UNIT_RESERVATION_P_FUNC_NAME
, STATE_NAME
,
9097 CPU_CODE_PARAMETER_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
9098 CPU_CODE_PARAMETER_NAME
);
9099 fprintf (output_file
, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
9100 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
9101 description
->query_units_num
);
9102 for (automaton
= description
->first_automaton
;
9104 automaton
= automaton
->next_automaton
)
9106 fprintf (output_file
, " if ((");
9107 output_reserved_units_table_name (output_file
, automaton
);
9108 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
9109 output_chip_member_name (output_file
, automaton
);
9110 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
9111 (description
->query_units_num
+ 7) / 8,
9112 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
9113 fprintf (output_file
, " return 1;\n");
9115 fprintf (output_file
, " return 0;\n}\n\n");
9118 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
9120 output_dfa_clean_insn_cache_func ()
9122 fprintf (output_file
,
9123 "void\n%s ()\n{\n int %s;\n\n",
9124 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
9125 fprintf (output_file
,
9126 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
9127 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
9128 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
9129 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
9132 /* The function outputs PHR interface function `dfa_start'. */
9134 output_dfa_start_func ()
9136 fprintf (output_file
,
9137 "void\n%s ()\n{\n %s = get_max_uid ();\n",
9138 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9139 fprintf (output_file
, " %s = (int *) xmalloc (%s * sizeof (int));\n",
9140 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9141 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
9144 /* The function outputs PHR interface function `dfa_finish'. */
9146 output_dfa_finish_func ()
9148 fprintf (output_file
, "void\n%s ()\n{\n free (%s);\n}\n\n",
9149 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
9154 /* The page contains code for output description file (readable
9155 representation of original description and generated DFA(s). */
9157 /* The function outputs string representation of IR reservation. */
9159 output_regexp (regexp
)
9162 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
9163 finish_regexp_representation ();
9166 /* Output names of units in LIST separated by comma. */
9168 output_unit_set_el_list (list
)
9173 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
9176 fprintf (output_description_file
, ", ");
9177 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
9181 /* Output patterns in LIST separated by comma. */
9183 output_pattern_set_el_list (list
)
9184 pattern_set_el_t list
;
9186 pattern_set_el_t el
;
9189 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
9192 fprintf (output_description_file
, ", ");
9193 for (i
= 0; i
< el
->units_num
; i
++)
9194 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
9195 el
->unit_decls
[i
]->name
);
9199 /* The function outputs string representation of IR define_reservation
9200 and define_insn_reservation. */
9202 output_description ()
9207 for (i
= 0; i
< description
->decls_num
; i
++)
9209 decl
= description
->decls
[i
];
9210 if (decl
->mode
== dm_unit
)
9212 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
9214 fprintf (output_description_file
, "unit %s exlusion_set: ",
9215 DECL_UNIT (decl
)->name
);
9216 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
9217 fprintf (output_description_file
, "\n");
9219 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
9221 fprintf (output_description_file
, "unit %s presence_set: ",
9222 DECL_UNIT (decl
)->name
);
9223 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
9224 fprintf (output_description_file
, "\n");
9226 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
9228 fprintf (output_description_file
, "unit %s final_presence_set: ",
9229 DECL_UNIT (decl
)->name
);
9230 output_pattern_set_el_list
9231 (DECL_UNIT (decl
)->final_presence_list
);
9232 fprintf (output_description_file
, "\n");
9234 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
9236 fprintf (output_description_file
, "unit %s absence_set: ",
9237 DECL_UNIT (decl
)->name
);
9238 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
9239 fprintf (output_description_file
, "\n");
9241 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
9243 fprintf (output_description_file
, "unit %s final_absence_set: ",
9244 DECL_UNIT (decl
)->name
);
9245 output_pattern_set_el_list
9246 (DECL_UNIT (decl
)->final_absence_list
);
9247 fprintf (output_description_file
, "\n");
9251 fprintf (output_description_file
, "\n");
9252 for (i
= 0; i
< description
->decls_num
; i
++)
9254 decl
= description
->decls
[i
];
9255 if (decl
->mode
== dm_reserv
)
9257 fprintf (output_description_file
, "reservation ");
9258 fprintf (output_description_file
, DECL_RESERV (decl
)->name
);
9259 fprintf (output_description_file
, ": ");
9260 output_regexp (DECL_RESERV (decl
)->regexp
);
9261 fprintf (output_description_file
, "\n");
9263 else if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9265 fprintf (output_description_file
, "insn reservation %s ",
9266 DECL_INSN_RESERV (decl
)->name
);
9267 print_rtl (output_description_file
,
9268 DECL_INSN_RESERV (decl
)->condexp
);
9269 fprintf (output_description_file
, ": ");
9270 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
9271 fprintf (output_description_file
, "\n");
9273 else if (decl
->mode
== dm_bypass
)
9274 fprintf (output_description_file
, "bypass %d %s %s\n",
9275 DECL_BYPASS (decl
)->latency
,
9276 DECL_BYPASS (decl
)->out_insn_name
,
9277 DECL_BYPASS (decl
)->in_insn_name
);
9279 fprintf (output_description_file
, "\n\f\n");
9282 /* The function outputs name of AUTOMATON. */
9284 output_automaton_name (f
, automaton
)
9286 automaton_t automaton
;
9288 if (automaton
->corresponding_automaton_decl
== NULL
)
9289 fprintf (f
, "#%d", automaton
->automaton_order_num
);
9291 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
9294 /* Maximal length of line for pretty printing into description
9296 #define MAX_LINE_LENGTH 70
9298 /* The function outputs units name belonging to AUTOMATON. */
9300 output_automaton_units (automaton
)
9301 automaton_t automaton
;
9305 int curr_line_length
;
9306 int there_is_an_automaton_unit
;
9309 fprintf (output_description_file
, "\n Coresponding units:\n");
9310 fprintf (output_description_file
, " ");
9311 curr_line_length
= 4;
9312 there_is_an_automaton_unit
= 0;
9313 for (i
= 0; i
< description
->decls_num
; i
++)
9315 decl
= description
->decls
[i
];
9316 if (decl
->mode
== dm_unit
9317 && (DECL_UNIT (decl
)->corresponding_automaton_num
9318 == automaton
->automaton_order_num
))
9320 there_is_an_automaton_unit
= 1;
9321 name
= DECL_UNIT (decl
)->name
;
9322 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
9324 curr_line_length
= strlen (name
) + 4;
9325 fprintf (output_description_file
, "\n ");
9329 curr_line_length
+= strlen (name
) + 1;
9330 fprintf (output_description_file
, " ");
9332 fprintf (output_description_file
, name
);
9335 if (!there_is_an_automaton_unit
)
9336 fprintf (output_description_file
, "<None>");
9337 fprintf (output_description_file
, "\n\n");
9340 /* The following variable is used for forming array of all possible cpu unit
9341 reservations described by the current DFA state. */
9342 static vla_ptr_t state_reservs
;
9344 /* The function forms `state_reservs' for STATE. */
9346 add_state_reservs (state
)
9349 alt_state_t curr_alt_state
;
9350 reserv_sets_t reservs
;
9352 if (state
->component_states
!= NULL
)
9353 for (curr_alt_state
= state
->component_states
;
9354 curr_alt_state
!= NULL
;
9355 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
9356 add_state_reservs (curr_alt_state
->state
);
9359 reservs
= state
->reservs
;
9360 VLA_PTR_ADD (state_reservs
, reservs
);
9364 /* The function outputs readable representation of all out arcs of
9367 output_state_arcs (state
)
9373 int curr_line_length
;
9375 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
9378 if (!ainsn
->first_insn_with_same_reservs
)
9380 fprintf (output_description_file
, " ");
9381 curr_line_length
= 7;
9382 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
9385 insn_name
= ainsn
->insn_reserv_decl
->name
;
9386 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
9388 if (ainsn
!= arc
->insn
)
9390 fprintf (output_description_file
, ",\n ");
9391 curr_line_length
= strlen (insn_name
) + 6;
9394 curr_line_length
+= strlen (insn_name
);
9398 curr_line_length
+= strlen (insn_name
);
9399 if (ainsn
!= arc
->insn
)
9401 curr_line_length
+= 2;
9402 fprintf (output_description_file
, ", ");
9405 fprintf (output_description_file
, insn_name
);
9406 ainsn
= ainsn
->next_same_reservs_insn
;
9408 while (ainsn
!= NULL
);
9409 fprintf (output_description_file
, " %d (%d)\n",
9410 arc
->to_state
->order_state_num
, arc
->state_alts
);
9412 fprintf (output_description_file
, "\n");
9415 /* The following function is used for sorting possible cpu unit
9416 reservation of a DFA state. */
9418 state_reservs_cmp (reservs_ptr_1
, reservs_ptr_2
)
9419 const void *reservs_ptr_1
;
9420 const void *reservs_ptr_2
;
9422 return reserv_sets_cmp (*(reserv_sets_t
*) reservs_ptr_1
,
9423 *(reserv_sets_t
*) reservs_ptr_2
);
9426 /* The following function is used for sorting possible cpu unit
9427 reservation of a DFA state. */
9429 remove_state_duplicate_reservs ()
9431 reserv_sets_t
*reservs_ptr
;
9432 reserv_sets_t
*last_formed_reservs_ptr
;
9434 last_formed_reservs_ptr
= NULL
;
9435 for (reservs_ptr
= VLA_PTR_BEGIN (state_reservs
);
9436 reservs_ptr
<= (reserv_sets_t
*) VLA_PTR_LAST (state_reservs
);
9438 if (last_formed_reservs_ptr
== NULL
)
9439 last_formed_reservs_ptr
= reservs_ptr
;
9440 else if (reserv_sets_cmp (*last_formed_reservs_ptr
, *reservs_ptr
) != 0)
9442 ++last_formed_reservs_ptr
;
9443 *last_formed_reservs_ptr
= *reservs_ptr
;
9445 VLA_PTR_SHORTEN (state_reservs
, reservs_ptr
- last_formed_reservs_ptr
- 1);
9448 /* The following function output readable representation of DFA(s)
9449 state used for fast recognition of pipeline hazards. State is
9450 described by possible (current and scheduled) cpu unit
9453 output_state (state
)
9456 reserv_sets_t
*reservs_ptr
;
9458 VLA_PTR_CREATE (state_reservs
, 150, "state reservations");
9459 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
9460 fprintf (output_description_file
,
9461 state
->new_cycle_p
? " (new cycle)\n" : "\n");
9462 add_state_reservs (state
);
9463 qsort (VLA_PTR_BEGIN (state_reservs
), VLA_PTR_LENGTH (state_reservs
),
9464 sizeof (reserv_sets_t
), state_reservs_cmp
);
9465 remove_state_duplicate_reservs ();
9466 for (reservs_ptr
= VLA_PTR_BEGIN (state_reservs
);
9467 reservs_ptr
<= (reserv_sets_t
*) VLA_PTR_LAST (state_reservs
);
9470 fprintf (output_description_file
, " ");
9471 output_reserv_sets (output_description_file
, *reservs_ptr
);
9472 fprintf (output_description_file
, "\n");
9474 fprintf (output_description_file
, "\n");
9475 output_state_arcs (state
);
9476 VLA_PTR_DELETE (state_reservs
);
9479 /* The following function output readable representation of
9480 DFAs used for fast recognition of pipeline hazards. */
9482 output_automaton_descriptions ()
9484 automaton_t automaton
;
9486 for (automaton
= description
->first_automaton
;
9488 automaton
= automaton
->next_automaton
)
9490 fprintf (output_description_file
, "\nAutomaton ");
9491 output_automaton_name (output_description_file
, automaton
);
9492 fprintf (output_description_file
, "\n");
9493 output_automaton_units (automaton
);
9494 pass_states (automaton
, output_state
);
9500 /* The page contains top level function for generation DFA(s) used for
9503 /* The function outputs statistics about work of different phases of
9506 output_statistics (f
)
9509 automaton_t automaton
;
9512 int transition_comb_vect_els
= 0;
9513 int transition_full_vect_els
= 0;
9514 int state_alts_comb_vect_els
= 0;
9515 int state_alts_full_vect_els
= 0;
9516 int min_issue_delay_vect_els
= 0;
9519 for (automaton
= description
->first_automaton
;
9521 automaton
= automaton
->next_automaton
)
9523 fprintf (f
, "\nAutomaton ");
9524 output_automaton_name (f
, automaton
);
9525 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
9526 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
9527 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
9528 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
9529 states_num
= automaton
->DFA_states_num
;
9530 if (!no_minimization_flag
)
9532 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9533 automaton
->minimal_DFA_states_num
,
9534 automaton
->minimal_DFA_arcs_num
);
9535 states_num
= automaton
->minimal_DFA_states_num
;
9537 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
9538 description
->insns_num
, automaton
->insn_equiv_classes_num
);
9541 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9542 (long) VLA_HWINT_LENGTH (automaton
->trans_table
->comb_vect
),
9543 (long) VLA_HWINT_LENGTH (automaton
->trans_table
->full_vect
),
9544 (comb_vect_p (automaton
->trans_table
)
9545 ? "use comb vect" : "use simple vect"));
9547 (f
, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9548 (long) VLA_HWINT_LENGTH (automaton
->state_alts_table
->comb_vect
),
9549 (long) VLA_HWINT_LENGTH (automaton
->state_alts_table
->full_vect
),
9550 (comb_vect_p (automaton
->state_alts_table
)
9551 ? "use comb vect" : "use simple vect"));
9553 (f
, "%5ld min delay table els, compression factor %d\n",
9554 (long) states_num
* automaton
->insn_equiv_classes_num
,
9555 automaton
->min_issue_delay_table_compression_factor
);
9556 transition_comb_vect_els
9557 += VLA_HWINT_LENGTH (automaton
->trans_table
->comb_vect
);
9558 transition_full_vect_els
9559 += VLA_HWINT_LENGTH (automaton
->trans_table
->full_vect
);
9560 state_alts_comb_vect_els
9561 += VLA_HWINT_LENGTH (automaton
->state_alts_table
->comb_vect
);
9562 state_alts_full_vect_els
9563 += VLA_HWINT_LENGTH (automaton
->state_alts_table
->full_vect
);
9564 min_issue_delay_vect_els
9565 += states_num
* automaton
->insn_equiv_classes_num
;
9569 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
9570 allocated_states_num
, allocated_arcs_num
);
9571 fprintf (f
, "%5d all allocated alternative states\n",
9572 allocated_alt_states_num
);
9573 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
9574 transition_comb_vect_els
, transition_full_vect_els
);
9576 (f
, "%5d all state alts comb vector els, %5d all state alts table els\n",
9577 state_alts_comb_vect_els
, state_alts_full_vect_els
);
9578 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
9579 fprintf (f
, "%5d locked states num\n", locked_states_num
);
9583 /* The function output times of work of different phases of DFA
9586 output_time_statistics (f
)
9589 fprintf (f
, "\n transformation: ");
9590 print_active_time (f
, transform_time
);
9591 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
9592 print_active_time (f
, NDFA_time
);
9595 fprintf (f
, ", NDFA -> DFA: ");
9596 print_active_time (f
, NDFA_to_DFA_time
);
9598 fprintf (f
, "\n DFA minimization: ");
9599 print_active_time (f
, minimize_time
);
9600 fprintf (f
, ", making insn equivalence: ");
9601 print_active_time (f
, equiv_time
);
9602 fprintf (f
, "\n all automaton generation: ");
9603 print_active_time (f
, automaton_generation_time
);
9604 fprintf (f
, ", output: ");
9605 print_active_time (f
, output_time
);
9609 /* The function generates DFA (deterministic finite state automaton)
9610 for fast recognition of pipeline hazards. No errors during
9611 checking must be fixed before this function call. */
9615 automata_num
= split_argument
;
9616 if (description
->units_num
< automata_num
)
9617 automata_num
= description
->units_num
;
9620 initiate_automata_lists ();
9621 initiate_pass_states ();
9622 initiate_excl_sets ();
9623 initiate_presence_absence_pattern_sets ();
9624 automaton_generation_time
= create_ticker ();
9626 ticker_off (&automaton_generation_time
);
9631 /* The following function creates insn attribute whose values are
9632 number alternatives in insn reservations. */
9634 make_insn_alts_attr ()
9640 condexp
= rtx_alloc (COND
);
9641 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9642 XEXP (condexp
, 1) = make_numeric_value (0);
9643 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9645 decl
= description
->decls
[i
];
9646 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9648 XVECEXP (condexp
, 0, 2 * insn_num
)
9649 = DECL_INSN_RESERV (decl
)->condexp
;
9650 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9651 = make_numeric_value
9652 (DECL_INSN_RESERV (decl
)->transformed_regexp
->mode
!= rm_oneof
9653 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl
)
9654 ->transformed_regexp
)->regexps_num
);
9658 if (description
->insns_num
!= insn_num
+ 1)
9660 make_internal_attr (attr_printf (sizeof ("*")
9661 + strlen (INSN_ALTS_FUNC_NAME
) + 1,
9662 "*%s", INSN_ALTS_FUNC_NAME
),
9668 /* The following function creates attribute which is order number of
9669 insn in pipeline hazard description translator. */
9671 make_internal_dfa_insn_code_attr ()
9677 condexp
= rtx_alloc (COND
);
9678 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9680 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl
)
9682 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9684 decl
= description
->decls
[i
];
9685 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9687 XVECEXP (condexp
, 0, 2 * insn_num
)
9688 = DECL_INSN_RESERV (decl
)->condexp
;
9689 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9690 = make_numeric_value (DECL_INSN_RESERV (decl
)->insn_num
);
9694 if (description
->insns_num
!= insn_num
+ 1)
9697 (attr_printf (sizeof ("*")
9698 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME
) + 1,
9699 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME
),
9705 /* The following function creates attribute which order number of insn
9706 in pipeline hazard description translator. */
9708 make_default_insn_latency_attr ()
9714 condexp
= rtx_alloc (COND
);
9715 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9716 XEXP (condexp
, 1) = make_numeric_value (0);
9717 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9719 decl
= description
->decls
[i
];
9720 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9722 XVECEXP (condexp
, 0, 2 * insn_num
)
9723 = DECL_INSN_RESERV (decl
)->condexp
;
9724 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9725 = make_numeric_value (DECL_INSN_RESERV (decl
)->default_latency
);
9729 if (description
->insns_num
!= insn_num
+ 1)
9731 make_internal_attr (attr_printf (sizeof ("*")
9732 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME
)
9733 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME
),
9739 /* The following function creates attribute which returns 1 if given
9740 output insn has bypassing and 0 otherwise. */
9745 int bypass_insns_num
= 0;
9749 for (i
= 0; i
< description
->decls_num
; i
++)
9751 decl
= description
->decls
[i
];
9752 if (decl
->mode
== dm_insn_reserv
9753 && DECL_INSN_RESERV (decl
)->condexp
!= NULL
9754 && DECL_INSN_RESERV (decl
)->bypass_list
!= NULL
)
9757 if (bypass_insns_num
== 0)
9758 result_rtx
= make_numeric_value (0);
9761 result_rtx
= rtx_alloc (COND
);
9762 XVEC (result_rtx
, 0) = rtvec_alloc (bypass_insns_num
* 2);
9763 XEXP (result_rtx
, 1) = make_numeric_value (0);
9765 for (i
= bypass_insn
= 0; i
< description
->decls_num
; i
++)
9767 decl
= description
->decls
[i
];
9768 if (decl
->mode
== dm_insn_reserv
9769 && DECL_INSN_RESERV (decl
)->condexp
!= NULL
9770 && DECL_INSN_RESERV (decl
)->bypass_list
!= NULL
)
9772 XVECEXP (result_rtx
, 0, 2 * bypass_insn
)
9773 = DECL_INSN_RESERV (decl
)->condexp
;
9774 XVECEXP (result_rtx
, 0, 2 * bypass_insn
+ 1)
9775 = make_numeric_value (1);
9780 make_internal_attr (attr_printf (sizeof ("*")
9781 + strlen (BYPASS_P_FUNC_NAME
) + 1,
9782 "*%s", BYPASS_P_FUNC_NAME
),
9788 /* This page mainly contains top level functions of pipeline hazards
9789 description translator. */
9791 /* The following macro value is suffix of name of description file of
9792 pipeline hazards description translator. */
9793 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9795 /* The function returns suffix of given file name. The returned
9796 string can not be changed. */
9798 file_name_suffix (file_name
)
9799 const char *file_name
;
9801 const char *last_period
;
9803 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
9804 if (*file_name
== '.')
9805 last_period
= file_name
;
9806 return (last_period
== NULL
? file_name
: last_period
);
9809 /* The function returns base name of given file name, i.e. pointer to
9810 first char after last `/' (or `\' for WIN32) in given file name,
9811 given file name itself if the directory name is absent. The
9812 returned string can not be changed. */
9814 base_file_name (file_name
)
9815 const char *file_name
;
9817 int directory_name_length
;
9819 directory_name_length
= strlen (file_name
);
9821 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
9822 && file_name
[directory_name_length
] != '\\')
9824 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
9826 directory_name_length
--;
9827 return file_name
+ directory_name_length
+ 1;
9830 /* The following is top level function to initialize the work of
9831 pipeline hazards description translator. */
9833 initiate_automaton_gen (argc
, argv
)
9837 const char *base_name
;
9841 split_argument
= 0; /* default value */
9842 no_minimization_flag
= 0;
9846 for (i
= 2; i
< argc
; i
++)
9847 if (strcmp (argv
[i
], NO_MINIMIZATION_OPTION
) == 0)
9848 no_minimization_flag
= 1;
9849 else if (strcmp (argv
[i
], TIME_OPTION
) == 0)
9851 else if (strcmp (argv
[i
], V_OPTION
) == 0)
9853 else if (strcmp (argv
[i
], W_OPTION
) == 0)
9855 else if (strcmp (argv
[i
], NDFA_OPTION
) == 0)
9857 else if (strcmp (argv
[i
], "-split") == 0)
9860 fatal ("-split has no argument.");
9861 fatal ("option `-split' has not been implemented yet\n");
9862 /* split_argument = atoi (argument_vect [i + 1]); */
9864 VLA_PTR_CREATE (decls
, 150, "decls");
9865 /* Initialize IR storage. */
9866 obstack_init (&irp
);
9867 initiate_automaton_decl_table ();
9868 initiate_insn_decl_table ();
9869 initiate_decl_table ();
9870 output_file
= stdout
;
9871 output_description_file
= NULL
;
9872 base_name
= base_file_name (argv
[1]);
9873 obstack_grow (&irp
, base_name
,
9874 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
9875 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
9876 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
9877 obstack_1grow (&irp
, '\0');
9878 output_description_file_name
= obstack_base (&irp
);
9879 obstack_finish (&irp
);
9882 /* The following function checks existence at least one arc marked by
9885 check_automata_insn_issues ()
9887 automaton_t automaton
;
9888 ainsn_t ainsn
, reserv_ainsn
;
9890 for (automaton
= description
->first_automaton
;
9892 automaton
= automaton
->next_automaton
)
9894 for (ainsn
= automaton
->ainsn_list
;
9896 ainsn
= ainsn
->next_ainsn
)
9897 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
)
9899 for (reserv_ainsn
= ainsn
;
9900 reserv_ainsn
!= NULL
;
9901 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9902 if (automaton
->corresponding_automaton_decl
!= NULL
)
9905 error ("Automaton `%s': Insn `%s' will never be issued",
9906 automaton
->corresponding_automaton_decl
->name
,
9907 reserv_ainsn
->insn_reserv_decl
->name
);
9910 ("Automaton `%s': Insn `%s' will never be issued",
9911 automaton
->corresponding_automaton_decl
->name
,
9912 reserv_ainsn
->insn_reserv_decl
->name
);
9917 error ("Insn `%s' will never be issued",
9918 reserv_ainsn
->insn_reserv_decl
->name
);
9920 warning ("Insn `%s' will never be issued",
9921 reserv_ainsn
->insn_reserv_decl
->name
);
9927 /* The following vla is used for storing pointers to all achieved
9929 static vla_ptr_t automaton_states
;
9931 /* This function is called by function pass_states to add an achieved
9934 add_automaton_state (state
)
9937 VLA_PTR_ADD (automaton_states
, state
);
9940 /* The following function forms list of important automata (whose
9941 states may be changed after the insn issue) for each insn. */
9943 form_important_insn_automata_lists ()
9945 automaton_t automaton
;
9952 VLA_PTR_CREATE (automaton_states
, 1500,
9953 "automaton states for forming important insn automata sets");
9954 /* Mark important ainsns. */
9955 for (automaton
= description
->first_automaton
;
9957 automaton
= automaton
->next_automaton
)
9959 VLA_PTR_NULLIFY (automaton_states
);
9960 pass_states (automaton
, add_automaton_state
);
9961 for (state_ptr
= VLA_PTR_BEGIN (automaton_states
);
9962 state_ptr
<= (state_t
*) VLA_PTR_LAST (automaton_states
);
9965 for (arc
= first_out_arc (*state_ptr
);
9967 arc
= next_out_arc (arc
))
9968 if (arc
->to_state
!= *state_ptr
)
9970 if (!arc
->insn
->first_insn_with_same_reservs
)
9972 for (ainsn
= arc
->insn
;
9974 ainsn
= ainsn
->next_same_reservs_insn
)
9975 ainsn
->important_p
= TRUE
;
9979 VLA_PTR_DELETE (automaton_states
);
9980 /* Create automata sets for the insns. */
9981 for (i
= 0; i
< description
->decls_num
; i
++)
9983 decl
= description
->decls
[i
];
9984 if (decl
->mode
== dm_insn_reserv
)
9986 automata_list_start ();
9987 for (automaton
= description
->first_automaton
;
9989 automaton
= automaton
->next_automaton
)
9990 for (ainsn
= automaton
->ainsn_list
;
9992 ainsn
= ainsn
->next_ainsn
)
9993 if (ainsn
->important_p
9994 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
9996 automata_list_add (automaton
);
9999 DECL_INSN_RESERV (decl
)->important_automata_list
10000 = automata_list_finish ();
10006 /* The following is top level function to generate automat(a,on) for
10007 fast recognition of pipeline hazards. */
10013 description
= create_node (sizeof (struct description
)
10014 /* One entry for cycle advancing insn. */
10015 + sizeof (decl_t
) * VLA_PTR_LENGTH (decls
));
10016 description
->decls_num
= VLA_PTR_LENGTH (decls
);
10017 description
->query_units_num
= 0;
10018 for (i
= 0; i
< description
->decls_num
; i
++)
10020 description
->decls
[i
] = VLA_PTR (decls
, i
);
10021 if (description
->decls
[i
]->mode
== dm_unit
10022 && DECL_UNIT (description
->decls
[i
])->query_p
)
10023 DECL_UNIT (description
->decls
[i
])->query_num
10024 = description
->query_units_num
++;
10026 all_time
= create_ticker ();
10027 check_time
= create_ticker ();
10028 fprintf (stderr
, "Check description...");
10030 check_all_description ();
10031 fprintf (stderr
, "done\n");
10032 ticker_off (&check_time
);
10033 generation_time
= create_ticker ();
10036 transform_insn_regexps ();
10037 check_unit_distributions_to_automata ();
10042 check_automata_insn_issues ();
10046 form_important_insn_automata_lists ();
10047 fprintf (stderr
, "Generation of attributes...");
10049 make_internal_dfa_insn_code_attr ();
10050 make_insn_alts_attr ();
10051 make_default_insn_latency_attr ();
10052 make_bypass_attr ();
10053 fprintf (stderr
, "done\n");
10055 ticker_off (&generation_time
);
10056 ticker_off (&all_time
);
10057 fprintf (stderr
, "All other genattrtab stuff...");
10061 /* The following is top level function to output PHR and to finish
10062 work with pipeline description translator. */
10066 fprintf (stderr
, "done\n");
10068 fatal ("Errors in DFA description");
10069 ticker_on (&all_time
);
10070 output_time
= create_ticker ();
10071 fprintf (stderr
, "Forming and outputing automata tables...");
10073 output_dfa_max_issue_rate ();
10075 fprintf (stderr
, "done\n");
10076 fprintf (stderr
, "Output functions to work with automata...");
10078 output_chip_definitions ();
10079 output_max_insn_queue_index_def ();
10080 output_internal_min_issue_delay_func ();
10081 output_internal_trans_func ();
10082 /* Cache of insn dfa codes: */
10083 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
10084 fprintf (output_file
, "\nstatic int %s;\n\n",
10085 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
10086 output_dfa_insn_code_func ();
10087 output_trans_func ();
10088 fprintf (output_file
, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME
);
10089 output_internal_state_alts_func ();
10090 output_state_alts_func ();
10091 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
10092 AUTOMATON_STATE_ALTS_MACRO_NAME
);
10093 output_min_issue_delay_func ();
10094 output_internal_dead_lock_func ();
10095 output_dead_lock_func ();
10096 output_size_func ();
10097 output_internal_reset_func ();
10098 output_reset_func ();
10099 output_min_insn_conflict_delay_func ();
10100 output_internal_insn_latency_func ();
10101 output_insn_latency_func ();
10102 output_print_reservation_func ();
10103 /* Output function get_cpu_unit_code. */
10104 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
10105 output_get_cpu_unit_code_func ();
10106 output_cpu_unit_reservation_p ();
10107 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
10108 CPU_UNITS_QUERY_MACRO_NAME
);
10109 output_dfa_clean_insn_cache_func ();
10110 output_dfa_start_func ();
10111 output_dfa_finish_func ();
10112 fprintf (stderr
, "done\n");
10115 output_description_file
= fopen (output_description_file_name
, "w");
10116 if (output_description_file
== NULL
)
10118 perror (output_description_file_name
);
10119 exit (FATAL_EXIT_CODE
);
10121 fprintf (stderr
, "Output automata description...");
10123 output_description ();
10124 output_automaton_descriptions ();
10125 fprintf (stderr
, "done\n");
10126 output_statistics (output_description_file
);
10128 output_statistics (stderr
);
10129 ticker_off (&output_time
);
10130 output_time_statistics (stderr
);
10133 finish_automata_lists ();
10136 fprintf (stderr
, "Summary:\n");
10137 fprintf (stderr
, " check time ");
10138 print_active_time (stderr
, check_time
);
10139 fprintf (stderr
, ", generation time ");
10140 print_active_time (stderr
, generation_time
);
10141 fprintf (stderr
, ", all time ");
10142 print_active_time (stderr
, all_time
);
10143 fprintf (stderr
, "\n");
10145 /* Finish all work. */
10146 if (output_description_file
!= NULL
)
10148 fflush (output_description_file
);
10149 if (ferror (stdout
) != 0)
10150 fatal ("Error in writing DFA description file %s",
10151 output_description_file_name
);
10152 fclose (output_description_file
);
10154 finish_automaton_decl_table ();
10155 finish_insn_decl_table ();
10156 finish_decl_table ();
10157 obstack_free (&irp
, NULL
);
10158 if (have_error
&& output_description_file
!= NULL
)
10159 remove (output_description_file_name
);