1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003 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 deterministically and
43 non-deterministically.
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 deterministic 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 following 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 parentheses 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 changed. */
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
++)
5279 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
5281 seq
= REGEXP_ALLOF (regexp
)->regexps
[i
];
5282 if (max_seq_length
< REGEXP_SEQUENCE (seq
)->regexps_num
)
5283 max_seq_length
= REGEXP_SEQUENCE (seq
)->regexps_num
;
5285 else if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
!= rm_unit
5286 && REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
!= rm_nothing
)
5292 if (max_seq_length
!= 0)
5294 if (max_seq_length
== 1 || REGEXP_ALLOF (regexp
)->regexps_num
<= 1)
5296 result
= create_node (sizeof (struct regexp
)
5297 + sizeof (regexp_t
) * (max_seq_length
- 1));
5298 result
->mode
= rm_sequence
;
5299 result
->pos
= regexp
->pos
;
5300 REGEXP_SEQUENCE (result
)->regexps_num
= max_seq_length
;
5301 for (i
= 0; i
< max_seq_length
; i
++)
5304 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
5305 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
5306 && (i
< (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5307 ->regexps
[j
])->regexps_num
)))
5310 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)->regexps
[j
])
5315 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5317 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5320 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
5323 if (allof_length
== 1)
5324 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof_op
;
5327 allof
= create_node (sizeof (struct regexp
)
5329 * (allof_length
- 1));
5330 allof
->mode
= rm_allof
;
5331 allof
->pos
= regexp
->pos
;
5332 REGEXP_ALLOF (allof
)->regexps_num
= allof_length
;
5333 REGEXP_SEQUENCE (result
)->regexps
[i
] = allof
;
5335 for (j
= 0; j
< REGEXP_ALLOF (regexp
)->regexps_num
; j
++)
5336 if (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
== rm_sequence
5338 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5339 ->regexps
[j
])->regexps_num
)))
5341 allof_op
= (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp
)
5344 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
5349 && (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5351 || (REGEXP_ALLOF (regexp
)->regexps
[j
]->mode
5354 allof_op
= REGEXP_ALLOF (regexp
)->regexps
[j
];
5355 REGEXP_ALLOF (allof
)->regexps
[allof_length
]
5361 regexp_transformed_p
= 1;
5368 /* The function traverses IR of reservation and applies transformations
5369 implemented by FUNC. */
5371 regexp_transform_func (regexp
, func
)
5373 regexp_t (*func
) PARAMS ((regexp_t regexp
));
5377 if (regexp
->mode
== rm_sequence
)
5378 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5379 REGEXP_SEQUENCE (regexp
)->regexps
[i
]
5380 = regexp_transform_func (REGEXP_SEQUENCE (regexp
)->regexps
[i
], func
);
5381 else if (regexp
->mode
== rm_allof
)
5382 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5383 REGEXP_ALLOF (regexp
)->regexps
[i
]
5384 = regexp_transform_func (REGEXP_ALLOF (regexp
)->regexps
[i
], func
);
5385 else if (regexp
->mode
== rm_oneof
)
5386 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
5387 REGEXP_ONEOF (regexp
)->regexps
[i
]
5388 = regexp_transform_func (REGEXP_ONEOF (regexp
)->regexps
[i
], func
);
5389 else if (regexp
->mode
== rm_repeat
)
5390 REGEXP_REPEAT (regexp
)->regexp
5391 = regexp_transform_func (REGEXP_REPEAT (regexp
)->regexp
, func
);
5392 else if (regexp
->mode
!= rm_nothing
&& regexp
->mode
!= rm_unit
)
5394 return (*func
) (regexp
);
5397 /* The function applies all transformations for IR representation of
5398 reservation REGEXP. */
5400 transform_regexp (regexp
)
5403 regexp
= regexp_transform_func (regexp
, transform_1
);
5406 regexp_transformed_p
= 0;
5407 regexp
= regexp_transform_func (regexp
, transform_2
);
5408 regexp
= regexp_transform_func (regexp
, transform_3
);
5410 while (regexp_transformed_p
);
5414 /* The function applies all transformations for reservations of all
5415 insn declarations. */
5417 transform_insn_regexps ()
5422 transform_time
= create_ticker ();
5423 add_advance_cycle_insn_decl ();
5424 fprintf (stderr
, "Reservation transformation...");
5426 for (i
= 0; i
< description
->decls_num
; i
++)
5428 decl
= description
->decls
[i
];
5429 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
5430 DECL_INSN_RESERV (decl
)->transformed_regexp
5431 = transform_regexp (copy_insn_regexp
5432 (DECL_INSN_RESERV (decl
)->regexp
));
5434 fprintf (stderr
, "done\n");
5435 ticker_off (&transform_time
);
5441 /* The following variable value is TRUE if the first annotated message
5442 about units to automata distribution has been output. */
5443 static int annotation_message_reported_p
;
5445 /* The function processes all alternative reservations on CYCLE in
5446 given REGEXP of insn reservation with INSN_RESERV_NAME to check the
5447 UNIT (or another unit from the same automaton) is not reserved on
5448 the all alternatives. If it is true, the function outputs message
5449 about the rule violation. */
5451 check_unit_distribution_in_reserv (insn_reserv_name
, unit
, regexp
, cycle
)
5452 const char *insn_reserv_name
;
5458 regexp_t seq
, allof
;
5459 unit_decl_t unit_decl
;
5461 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5463 unit_decl
= REGEXP_UNIT (unit
)->unit_decl
;
5464 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5466 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5467 if (seq
->mode
== rm_sequence
)
5469 if (cycle
>= REGEXP_SEQUENCE (seq
)->regexps_num
)
5471 allof
= REGEXP_SEQUENCE (seq
)->regexps
[cycle
];
5472 if (allof
->mode
== rm_allof
)
5474 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5475 if (REGEXP_ALLOF (allof
)->regexps
[k
]->mode
== rm_unit
5476 && (REGEXP_UNIT (REGEXP_ALLOF (allof
)->regexps
[k
])
5477 ->unit_decl
->automaton_decl
5478 == unit_decl
->automaton_decl
))
5480 if (k
>= REGEXP_ALLOF (allof
)->regexps_num
)
5483 else if (allof
->mode
== rm_unit
5484 && (REGEXP_UNIT (allof
)->unit_decl
->automaton_decl
5485 != unit_decl
->automaton_decl
))
5488 else if (cycle
!= 0)
5490 else if (seq
->mode
== rm_allof
)
5492 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5493 if (REGEXP_ALLOF (seq
)->regexps
[k
]->mode
== rm_unit
5494 && (REGEXP_UNIT (REGEXP_ALLOF (seq
)->regexps
[k
])
5495 ->unit_decl
->automaton_decl
== unit_decl
->automaton_decl
))
5497 if (k
>= REGEXP_ALLOF (seq
)->regexps_num
)
5500 else if (seq
->mode
== rm_unit
5501 && (REGEXP_UNIT (seq
)->unit_decl
->automaton_decl
5502 != unit_decl
->automaton_decl
))
5507 if (!annotation_message_reported_p
)
5509 fprintf (stderr
, "\n");
5510 error ("The following units do not satisfy units-automata distribution rule");
5511 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5512 annotation_message_reported_p
= TRUE
;
5514 error ("Unit %s, reserv. %s, cycle %d",
5515 unit_decl
->name
, insn_reserv_name
, cycle
);
5519 /* The function processes given REGEXP to find units with the wrong
5522 check_regexp_units_distribution (insn_reserv_name
, regexp
)
5523 const char *insn_reserv_name
;
5527 regexp_t seq
, allof
, unit
;
5529 if (regexp
== NULL
|| regexp
->mode
!= rm_oneof
)
5531 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5533 seq
= REGEXP_ONEOF (regexp
)->regexps
[i
];
5534 if (seq
->mode
== rm_sequence
)
5535 for (j
= 0; j
< REGEXP_SEQUENCE (seq
)->regexps_num
; j
++)
5537 allof
= REGEXP_SEQUENCE (seq
)->regexps
[j
];
5538 if (allof
->mode
== rm_allof
)
5539 for (k
= 0; k
< REGEXP_ALLOF (allof
)->regexps_num
; k
++)
5541 unit
= REGEXP_ALLOF (allof
)->regexps
[k
];
5542 if (unit
->mode
== rm_unit
)
5543 check_unit_distribution_in_reserv (insn_reserv_name
, unit
,
5545 else if (unit
->mode
!= rm_nothing
)
5548 else if (allof
->mode
== rm_unit
)
5549 check_unit_distribution_in_reserv (insn_reserv_name
, allof
,
5551 else if (allof
->mode
!= rm_nothing
)
5554 else if (seq
->mode
== rm_allof
)
5555 for (k
= 0; k
< REGEXP_ALLOF (seq
)->regexps_num
; k
++)
5557 unit
= REGEXP_ALLOF (seq
)->regexps
[k
];
5558 if (unit
->mode
== rm_unit
)
5559 check_unit_distribution_in_reserv (insn_reserv_name
, unit
,
5561 else if (unit
->mode
!= rm_nothing
)
5564 else if (seq
->mode
== rm_unit
)
5565 check_unit_distribution_in_reserv (insn_reserv_name
, seq
, regexp
, 0);
5566 else if (seq
->mode
!= rm_nothing
)
5571 /* The function finds units which violates units to automata
5572 distribution rule. If the units exist, report about them. */
5574 check_unit_distributions_to_automata ()
5579 fprintf (stderr
, "Check unit distributions to automata...");
5580 annotation_message_reported_p
= FALSE
;
5581 for (i
= 0; i
< description
->decls_num
; i
++)
5583 decl
= description
->decls
[i
];
5584 if (decl
->mode
== dm_insn_reserv
)
5585 check_regexp_units_distribution
5586 (DECL_INSN_RESERV (decl
)->name
,
5587 DECL_INSN_RESERV (decl
)->transformed_regexp
);
5589 fprintf (stderr
, "done\n");
5594 /* The page contains code for building alt_states (see comments for
5595 IR) describing all possible insns reservations of an automaton. */
5597 /* Current state being formed for which the current alt_state
5599 static state_t state_being_formed
;
5601 /* Current alt_state being formed. */
5602 static alt_state_t alt_state_being_formed
;
5604 /* This recursive function processes `,' and units in reservation
5605 REGEXP for forming alt_states of AUTOMATON. It is believed that
5606 CURR_CYCLE is start cycle of all reservation REGEXP. */
5608 process_seq_for_forming_states (regexp
, automaton
, curr_cycle
)
5610 automaton_t automaton
;
5617 else if (regexp
->mode
== rm_unit
)
5619 if (REGEXP_UNIT (regexp
)->unit_decl
->corresponding_automaton_num
5620 == automaton
->automaton_order_num
)
5621 set_state_reserv (state_being_formed
, curr_cycle
,
5622 REGEXP_UNIT (regexp
)->unit_decl
->unit_num
);
5625 else if (regexp
->mode
== rm_sequence
)
5627 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
5629 = process_seq_for_forming_states
5630 (REGEXP_SEQUENCE (regexp
)->regexps
[i
], automaton
, curr_cycle
) + 1;
5633 else if (regexp
->mode
== rm_allof
)
5635 int finish_cycle
= 0;
5638 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
5640 cycle
= process_seq_for_forming_states (REGEXP_ALLOF (regexp
)
5642 automaton
, curr_cycle
);
5643 if (finish_cycle
< cycle
)
5644 finish_cycle
= cycle
;
5646 return finish_cycle
;
5650 if (regexp
->mode
!= rm_nothing
)
5656 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5657 inserts alt_state into the table. */
5659 finish_forming_alt_state (alt_state
, automaton
)
5660 alt_state_t alt_state
;
5661 automaton_t automaton ATTRIBUTE_UNUSED
;
5663 state_t state_in_table
;
5664 state_t corresponding_state
;
5666 corresponding_state
= alt_state
->state
;
5667 state_in_table
= insert_state (corresponding_state
);
5668 if (state_in_table
!= corresponding_state
)
5670 free_state (corresponding_state
);
5671 alt_state
->state
= state_in_table
;
5675 /* The following variable value is current automaton insn for whose
5676 reservation the alt states are created. */
5677 static ainsn_t curr_ainsn
;
5679 /* This recursive function processes `|' in reservation REGEXP for
5680 forming alt_states of AUTOMATON. List of the alt states should
5681 have the same order as in the description. */
5683 process_alts_for_forming_states (regexp
, automaton
, inside_oneof_p
)
5685 automaton_t automaton
;
5690 if (regexp
->mode
!= rm_oneof
)
5692 alt_state_being_formed
= get_free_alt_state ();
5693 state_being_formed
= get_free_state (1, automaton
);
5694 alt_state_being_formed
->state
= state_being_formed
;
5695 /* We inserts in reverse order but we process alternatives also
5696 in reverse order. So we have the same order of alternative
5697 as in the description. */
5698 alt_state_being_formed
->next_alt_state
= curr_ainsn
->alt_states
;
5699 curr_ainsn
->alt_states
= alt_state_being_formed
;
5700 (void) process_seq_for_forming_states (regexp
, automaton
, 0);
5701 finish_forming_alt_state (alt_state_being_formed
, automaton
);
5707 /* We processes it in reverse order to get list with the same
5708 order as in the description. See also the previous
5710 for (i
= REGEXP_ONEOF (regexp
)->regexps_num
- 1; i
>= 0; i
--)
5711 process_alts_for_forming_states (REGEXP_ONEOF (regexp
)->regexps
[i
],
5716 /* Create nodes alt_state for all AUTOMATON insns. */
5718 create_alt_states (automaton
)
5719 automaton_t automaton
;
5721 struct insn_reserv_decl
*reserv_decl
;
5723 for (curr_ainsn
= automaton
->ainsn_list
;
5725 curr_ainsn
= curr_ainsn
->next_ainsn
)
5727 reserv_decl
= curr_ainsn
->insn_reserv_decl
;
5728 if (reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5730 curr_ainsn
->alt_states
= NULL
;
5731 process_alts_for_forming_states (reserv_decl
->transformed_regexp
,
5733 curr_ainsn
->sorted_alt_states
5734 = uniq_sort_alt_states (curr_ainsn
->alt_states
);
5741 /* The page contains major code for building DFA(s) for fast pipeline
5742 hazards recognition. */
5744 /* The function forms list of ainsns of AUTOMATON with the same
5747 form_ainsn_with_same_reservs (automaton
)
5748 automaton_t automaton
;
5752 vla_ptr_t first_insns
;
5753 vla_ptr_t last_insns
;
5755 VLA_PTR_CREATE (first_insns
, 150, "first insns with the same reservs");
5756 VLA_PTR_CREATE (last_insns
, 150, "last insns with the same reservs");
5757 for (curr_ainsn
= automaton
->ainsn_list
;
5759 curr_ainsn
= curr_ainsn
->next_ainsn
)
5760 if (curr_ainsn
->insn_reserv_decl
5761 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
5763 curr_ainsn
->next_same_reservs_insn
= NULL
;
5764 curr_ainsn
->first_insn_with_same_reservs
= 1;
5768 for (i
= 0; i
< VLA_PTR_LENGTH (first_insns
); i
++)
5770 (curr_ainsn
->sorted_alt_states
,
5771 ((ainsn_t
) VLA_PTR (first_insns
, i
))->sorted_alt_states
))
5773 curr_ainsn
->next_same_reservs_insn
= NULL
;
5774 if (i
< VLA_PTR_LENGTH (first_insns
))
5776 curr_ainsn
->first_insn_with_same_reservs
= 0;
5777 ((ainsn_t
) VLA_PTR (last_insns
, i
))->next_same_reservs_insn
5779 VLA_PTR (last_insns
, i
) = curr_ainsn
;
5783 VLA_PTR_ADD (first_insns
, curr_ainsn
);
5784 VLA_PTR_ADD (last_insns
, curr_ainsn
);
5785 curr_ainsn
->first_insn_with_same_reservs
= 1;
5788 VLA_PTR_DELETE (first_insns
);
5789 VLA_PTR_DELETE (last_insns
);
5792 /* Forming unit reservations which can affect creating the automaton
5793 states achieved from a given state. It permits to build smaller
5794 automata in many cases. We would have the same automata after
5795 the minimization without such optimization, but the automaton
5796 right after the building could be huge. So in other words, usage
5797 of reservs_matter means some minimization during building the
5799 static reserv_sets_t
5800 form_reservs_matter (automaton
)
5801 automaton_t automaton
;
5804 reserv_sets_t reservs_matter
= alloc_empty_reserv_sets();
5806 for (cycle
= 0; cycle
< max_cycles_num
; cycle
++)
5807 for (unit
= 0; unit
< description
->units_num
; unit
++)
5808 if (units_array
[unit
]->automaton_decl
5809 == automaton
->corresponding_automaton_decl
5810 && (cycle
>= units_array
[unit
]->min_occ_cycle_num
5811 /* We can not remove queried unit from reservations. */
5812 || units_array
[unit
]->query_p
5813 /* We can not remove units which are used
5814 `exclusion_set', `presence_set',
5815 `final_presence_set', `absence_set', and
5816 `final_absence_set'. */
5817 || units_array
[unit
]->in_set_p
))
5818 set_unit_reserv (reservs_matter
, cycle
, unit
);
5819 return reservs_matter
;
5822 /* The following function creates all states of nondeterministic (if
5823 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5825 make_automaton (automaton
)
5826 automaton_t automaton
;
5829 struct insn_reserv_decl
*insn_reserv_decl
;
5830 alt_state_t alt_state
;
5832 state_t start_state
;
5834 ainsn_t advance_cycle_ainsn
;
5836 vla_ptr_t state_stack
;
5838 reserv_sets_t reservs_matter
= form_reservs_matter (automaton
);
5840 VLA_PTR_CREATE (state_stack
, 150, "state stack");
5841 /* Create the start state (empty state). */
5842 start_state
= insert_state (get_free_state (1, automaton
));
5843 automaton
->start_state
= start_state
;
5844 start_state
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5845 VLA_PTR_ADD (state_stack
, start_state
);
5847 while (VLA_PTR_LENGTH (state_stack
) != 0)
5849 state
= VLA_PTR (state_stack
, VLA_PTR_LENGTH (state_stack
) - 1);
5850 VLA_PTR_SHORTEN (state_stack
, 1);
5851 advance_cycle_ainsn
= NULL
;
5852 for (ainsn
= automaton
->ainsn_list
;
5854 ainsn
= ainsn
->next_ainsn
)
5855 if (ainsn
->first_insn_with_same_reservs
)
5857 insn_reserv_decl
= ainsn
->insn_reserv_decl
;
5858 if (insn_reserv_decl
!= DECL_INSN_RESERV (advance_cycle_insn_decl
))
5860 /* We process alt_states in the same order as they are
5861 present in the description. */
5863 for (alt_state
= ainsn
->alt_states
;
5865 alt_state
= alt_state
->next_alt_state
)
5867 state2
= alt_state
->state
;
5868 if (!intersected_state_reservs_p (state
, state2
))
5870 state2
= states_union (state
, state2
, reservs_matter
);
5871 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5873 state2
->it_was_placed_in_stack_for_NDFA_forming
5875 VLA_PTR_ADD (state_stack
, state2
);
5877 if (states_n
% 100 == 0)
5878 fprintf (stderr
, "*");
5880 added_arc
= add_arc (state
, state2
, ainsn
, 1);
5885 if (!ndfa_flag
&& added_arc
!= NULL
)
5887 added_arc
->state_alts
= 0;
5888 for (alt_state
= ainsn
->alt_states
;
5890 alt_state
= alt_state
->next_alt_state
)
5892 state2
= alt_state
->state
;
5893 if (!intersected_state_reservs_p (state
, state2
))
5894 added_arc
->state_alts
++;
5899 advance_cycle_ainsn
= ainsn
;
5901 /* Add transition to advance cycle. */
5902 state2
= state_shift (state
, reservs_matter
);
5903 if (!state2
->it_was_placed_in_stack_for_NDFA_forming
)
5905 state2
->it_was_placed_in_stack_for_NDFA_forming
= 1;
5906 VLA_PTR_ADD (state_stack
, state2
);
5908 if (states_n
% 100 == 0)
5909 fprintf (stderr
, "*");
5911 if (advance_cycle_ainsn
== NULL
)
5913 add_arc (state
, state2
, advance_cycle_ainsn
, 1);
5915 VLA_PTR_DELETE (state_stack
);
5918 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5920 form_arcs_marked_by_insn (state
)
5927 for (i
= 0; i
< description
->decls_num
; i
++)
5929 decl
= description
->decls
[i
];
5930 if (decl
->mode
== dm_insn_reserv
)
5931 DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
= NULL
;
5933 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
5935 if (arc
->insn
== NULL
)
5937 arc
->next_arc_marked_by_insn
5938 = arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
;
5939 arc
->insn
->insn_reserv_decl
->arcs_marked_by_insn
= arc
;
5943 /* The function creates composed state (see comments for IR) from
5944 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5945 same insn. If the composed state is not in STATE_STACK yet, it is
5946 pushed into STATE_STACK. */
5948 create_composed_state (original_state
, arcs_marked_by_insn
, state_stack
)
5949 state_t original_state
;
5950 arc_t arcs_marked_by_insn
;
5951 vla_ptr_t
*state_stack
;
5954 alt_state_t alt_state
, curr_alt_state
;
5955 alt_state_t new_alt_state
;
5958 state_t state_in_table
;
5960 alt_state_t canonical_alt_states_list
;
5962 int new_state_p
= 0;
5964 if (arcs_marked_by_insn
== NULL
)
5966 if (arcs_marked_by_insn
->next_arc_marked_by_insn
== NULL
)
5967 state
= arcs_marked_by_insn
->to_state
;
5972 /* Create composed state. */
5973 state
= get_free_state (0, arcs_marked_by_insn
->to_state
->automaton
);
5974 curr_alt_state
= NULL
;
5975 for (curr_arc
= arcs_marked_by_insn
;
5977 curr_arc
= curr_arc
->next_arc_marked_by_insn
)
5978 if (curr_arc
->to_state
->component_states
== NULL
)
5980 new_alt_state
= get_free_alt_state ();
5981 new_alt_state
->next_alt_state
= curr_alt_state
;
5982 new_alt_state
->state
= curr_arc
->to_state
;
5983 curr_alt_state
= new_alt_state
;
5986 for (alt_state
= curr_arc
->to_state
->component_states
;
5988 alt_state
= alt_state
->next_sorted_alt_state
)
5990 new_alt_state
= get_free_alt_state ();
5991 new_alt_state
->next_alt_state
= curr_alt_state
;
5992 new_alt_state
->state
= alt_state
->state
;
5993 if (alt_state
->state
->component_states
!= NULL
)
5995 curr_alt_state
= new_alt_state
;
5997 /* There are not identical sets in the alt state list. */
5998 canonical_alt_states_list
= uniq_sort_alt_states (curr_alt_state
);
5999 if (canonical_alt_states_list
->next_sorted_alt_state
== NULL
)
6002 state
= canonical_alt_states_list
->state
;
6003 free_state (temp_state
);
6007 state
->component_states
= canonical_alt_states_list
;
6008 state_in_table
= insert_state (state
);
6009 if (state_in_table
!= state
)
6011 if (!state_in_table
->it_was_placed_in_stack_for_DFA_forming
)
6014 state
= state_in_table
;
6018 if (state
->it_was_placed_in_stack_for_DFA_forming
)
6021 for (curr_alt_state
= state
->component_states
;
6022 curr_alt_state
!= NULL
;
6023 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
6024 for (curr_arc
= first_out_arc (curr_alt_state
->state
);
6026 curr_arc
= next_out_arc (curr_arc
))
6027 add_arc (state
, curr_arc
->to_state
, curr_arc
->insn
, 1);
6029 arcs_marked_by_insn
->to_state
= state
;
6030 for (alts_number
= 0,
6031 curr_arc
= arcs_marked_by_insn
->next_arc_marked_by_insn
;
6033 curr_arc
= next_arc
)
6035 next_arc
= curr_arc
->next_arc_marked_by_insn
;
6036 remove_arc (original_state
, curr_arc
);
6039 arcs_marked_by_insn
->state_alts
= alts_number
;
6042 if (!state
->it_was_placed_in_stack_for_DFA_forming
)
6044 state
->it_was_placed_in_stack_for_DFA_forming
= 1;
6045 VLA_PTR_ADD (*state_stack
, state
);
6050 /* The function transforms nondeterministic AUTOMATON into
6053 NDFA_to_DFA (automaton
)
6054 automaton_t automaton
;
6056 state_t start_state
;
6059 vla_ptr_t state_stack
;
6063 VLA_PTR_CREATE (state_stack
, 150, "state stack");
6064 /* Create the start state (empty state). */
6065 start_state
= automaton
->start_state
;
6066 start_state
->it_was_placed_in_stack_for_DFA_forming
= 1;
6067 VLA_PTR_ADD (state_stack
, start_state
);
6069 while (VLA_PTR_LENGTH (state_stack
) != 0)
6071 state
= VLA_PTR (state_stack
, VLA_PTR_LENGTH (state_stack
) - 1);
6072 VLA_PTR_SHORTEN (state_stack
, 1);
6073 form_arcs_marked_by_insn (state
);
6074 for (i
= 0; i
< description
->decls_num
; i
++)
6076 decl
= description
->decls
[i
];
6077 if (decl
->mode
== dm_insn_reserv
6078 && create_composed_state
6079 (state
, DECL_INSN_RESERV (decl
)->arcs_marked_by_insn
,
6083 if (states_n
% 100 == 0)
6084 fprintf (stderr
, "*");
6088 VLA_PTR_DELETE (state_stack
);
6091 /* The following variable value is current number (1, 2, ...) of passing
6093 static int curr_state_graph_pass_num
;
6095 /* This recursive function passes all states achieved from START_STATE
6096 and applies APPLIED_FUNC to them. */
6098 pass_state_graph (start_state
, applied_func
)
6099 state_t start_state
;
6100 void (*applied_func
) PARAMS ((state_t state
));
6104 if (start_state
->pass_num
== curr_state_graph_pass_num
)
6106 start_state
->pass_num
= curr_state_graph_pass_num
;
6107 (*applied_func
) (start_state
);
6108 for (arc
= first_out_arc (start_state
);
6110 arc
= next_out_arc (arc
))
6111 pass_state_graph (arc
->to_state
, applied_func
);
6114 /* This recursive function passes all states of AUTOMATON and applies
6115 APPLIED_FUNC to them. */
6117 pass_states (automaton
, applied_func
)
6118 automaton_t automaton
;
6119 void (*applied_func
) PARAMS ((state_t state
));
6121 curr_state_graph_pass_num
++;
6122 pass_state_graph (automaton
->start_state
, applied_func
);
6125 /* The function initializes code for passing of all states. */
6127 initiate_pass_states ()
6129 curr_state_graph_pass_num
= 0;
6132 /* The following vla is used for storing pointers to all achieved
6134 static vla_ptr_t all_achieved_states
;
6136 /* This function is called by function pass_states to add an achieved
6139 add_achieved_state (state
)
6142 VLA_PTR_ADD (all_achieved_states
, state
);
6145 /* The function sets up equivalence numbers of insns which mark all
6146 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
6147 nonzero value) or by equiv_class_num_2 of the destination state.
6148 The function returns number of out arcs of STATE. */
6150 set_out_arc_insns_equiv_num (state
, odd_iteration_flag
)
6152 int odd_iteration_flag
;
6154 int state_out_arcs_num
;
6157 state_out_arcs_num
= 0;
6158 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6160 if (arc
->insn
->insn_reserv_decl
->equiv_class_num
!= 0
6161 || arc
->insn
->insn_reserv_decl
->state_alts
!= 0)
6163 state_out_arcs_num
++;
6164 arc
->insn
->insn_reserv_decl
->equiv_class_num
6165 = (odd_iteration_flag
6166 ? arc
->to_state
->equiv_class_num_1
6167 : arc
->to_state
->equiv_class_num_2
);
6168 arc
->insn
->insn_reserv_decl
->state_alts
= arc
->state_alts
;
6169 if (arc
->insn
->insn_reserv_decl
->equiv_class_num
== 0
6170 || arc
->insn
->insn_reserv_decl
->state_alts
<= 0)
6173 return state_out_arcs_num
;
6176 /* The function clears equivalence numbers and alt_states in all insns
6177 which mark all out arcs of STATE. */
6179 clear_arc_insns_equiv_num (state
)
6184 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6186 arc
->insn
->insn_reserv_decl
->equiv_class_num
= 0;
6187 arc
->insn
->insn_reserv_decl
->state_alts
= 0;
6191 /* The function copies pointers to equivalent states from vla FROM
6194 copy_equiv_class (to
, from
)
6196 const vla_ptr_t
*from
;
6200 VLA_PTR_NULLIFY (*to
);
6201 for (class_ptr
= VLA_PTR_BEGIN (*from
);
6202 class_ptr
<= (state_t
*) VLA_PTR_LAST (*from
);
6204 VLA_PTR_ADD (*to
, *class_ptr
);
6207 /* The following function returns TRUE if STATE reserves the unit with
6208 UNIT_NUM on the first cycle. */
6210 first_cycle_unit_presence (state
, unit_num
)
6216 if (state
->component_states
== NULL
)
6217 presence_p
= test_unit_reserv (state
->reservs
, 0, unit_num
);
6220 = test_unit_reserv (state
->component_states
->state
->reservs
,
6225 /* The function returns nonzero value if STATE is not equivalent to
6226 ANOTHER_STATE from the same current partition on equivalence
6227 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
6228 output arcs. Iteration of making equivalence partition is defined
6229 by ODD_ITERATION_FLAG. */
6231 state_is_differed (state
, another_state
, another_state_out_arcs_num
,
6233 state_t state
, another_state
;
6234 int another_state_out_arcs_num
;
6235 int odd_iteration_flag
;
6238 int state_out_arcs_num
;
6239 int i
, presence1_p
, presence2_p
;
6241 state_out_arcs_num
= 0;
6242 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6244 state_out_arcs_num
++;
6245 if ((odd_iteration_flag
6246 ? arc
->to_state
->equiv_class_num_1
6247 : arc
->to_state
->equiv_class_num_2
)
6248 != arc
->insn
->insn_reserv_decl
->equiv_class_num
6249 || (arc
->insn
->insn_reserv_decl
->state_alts
!= arc
->state_alts
))
6252 if (state_out_arcs_num
!= another_state_out_arcs_num
)
6254 /* Now we are looking at the states with the point of view of query
6256 for (i
= 0; i
< description
->units_num
; i
++)
6257 if (units_array
[i
]->query_p
)
6259 presence1_p
= first_cycle_unit_presence (state
, i
);
6260 presence2_p
= first_cycle_unit_presence (another_state
, i
);
6261 if ((presence1_p
&& !presence2_p
) || (!presence1_p
&& presence2_p
))
6267 /* The function makes initial partition of STATES on equivalent
6270 init_equiv_class (states
, states_num
)
6275 state_t result_equiv_class
;
6277 result_equiv_class
= NULL
;
6278 for (state_ptr
= states
; state_ptr
< states
+ states_num
; state_ptr
++)
6280 (*state_ptr
)->equiv_class_num_1
= 1;
6281 (*state_ptr
)->next_equiv_class_state
= result_equiv_class
;
6282 result_equiv_class
= *state_ptr
;
6284 return result_equiv_class
;
6287 /* The function processes equivalence class given by its pointer
6288 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
6289 are not equivalent states, the function partitions the class
6290 removing nonequivalent states and placing them in
6291 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6292 assigns it to the state equivalence number. If the class has been
6293 partitioned, the function returns nonzero value. */
6295 partition_equiv_class (equiv_class_ptr
, odd_iteration_flag
,
6296 next_iteration_classes
, new_equiv_class_num_ptr
)
6297 state_t
*equiv_class_ptr
;
6298 int odd_iteration_flag
;
6299 vla_ptr_t
*next_iteration_classes
;
6300 int *new_equiv_class_num_ptr
;
6302 state_t new_equiv_class
;
6304 state_t first_state
;
6311 if (*equiv_class_ptr
== NULL
)
6313 for (first_state
= *equiv_class_ptr
;
6314 first_state
!= NULL
;
6315 first_state
= new_equiv_class
)
6317 new_equiv_class
= NULL
;
6318 if (first_state
->next_equiv_class_state
!= NULL
)
6320 /* There are more one states in the class equivalence. */
6321 out_arcs_num
= set_out_arc_insns_equiv_num (first_state
,
6322 odd_iteration_flag
);
6323 for (prev_state
= first_state
,
6324 curr_state
= first_state
->next_equiv_class_state
;
6326 curr_state
= next_state
)
6328 next_state
= curr_state
->next_equiv_class_state
;
6329 if (state_is_differed (curr_state
, first_state
, out_arcs_num
,
6330 odd_iteration_flag
))
6332 /* Remove curr state from the class equivalence. */
6333 prev_state
->next_equiv_class_state
= next_state
;
6334 /* Add curr state to the new class equivalence. */
6335 curr_state
->next_equiv_class_state
= new_equiv_class
;
6336 if (new_equiv_class
== NULL
)
6337 (*new_equiv_class_num_ptr
)++;
6338 if (odd_iteration_flag
)
6339 curr_state
->equiv_class_num_2
= *new_equiv_class_num_ptr
;
6341 curr_state
->equiv_class_num_1
= *new_equiv_class_num_ptr
;
6342 new_equiv_class
= curr_state
;
6346 prev_state
= curr_state
;
6348 clear_arc_insns_equiv_num (first_state
);
6350 if (new_equiv_class
!= NULL
)
6351 VLA_PTR_ADD (*next_iteration_classes
, new_equiv_class
);
6356 /* The function finds equivalent states of AUTOMATON. */
6358 evaluate_equiv_classes (automaton
, equiv_classes
)
6359 automaton_t automaton
;
6360 vla_ptr_t
*equiv_classes
;
6362 state_t new_equiv_class
;
6363 int new_equiv_class_num
;
6364 int odd_iteration_flag
;
6366 vla_ptr_t next_iteration_classes
;
6367 state_t
*equiv_class_ptr
;
6370 VLA_PTR_CREATE (all_achieved_states
, 1500, "all achieved states");
6371 pass_states (automaton
, add_achieved_state
);
6372 new_equiv_class
= init_equiv_class (VLA_PTR_BEGIN (all_achieved_states
),
6373 VLA_PTR_LENGTH (all_achieved_states
));
6374 odd_iteration_flag
= 0;
6375 new_equiv_class_num
= 1;
6376 VLA_PTR_CREATE (next_iteration_classes
, 150, "next iteration classes");
6377 VLA_PTR_ADD (next_iteration_classes
, new_equiv_class
);
6380 odd_iteration_flag
= !odd_iteration_flag
;
6382 copy_equiv_class (equiv_classes
, &next_iteration_classes
);
6383 /* Transfer equiv numbers for the next iteration. */
6384 for (state_ptr
= VLA_PTR_BEGIN (all_achieved_states
);
6385 state_ptr
<= (state_t
*) VLA_PTR_LAST (all_achieved_states
);
6387 if (odd_iteration_flag
)
6388 (*state_ptr
)->equiv_class_num_2
= (*state_ptr
)->equiv_class_num_1
;
6390 (*state_ptr
)->equiv_class_num_1
= (*state_ptr
)->equiv_class_num_2
;
6391 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6392 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6394 if (partition_equiv_class (equiv_class_ptr
, odd_iteration_flag
,
6395 &next_iteration_classes
,
6396 &new_equiv_class_num
))
6399 while (!finish_flag
);
6400 VLA_PTR_DELETE (next_iteration_classes
);
6401 VLA_PTR_DELETE (all_achieved_states
);
6404 /* The function merges equivalent states of AUTOMATON. */
6406 merge_states (automaton
, equiv_classes
)
6407 automaton_t automaton
;
6408 vla_ptr_t
*equiv_classes
;
6410 state_t
*equiv_class_ptr
;
6413 state_t first_class_state
;
6414 alt_state_t alt_states
;
6415 alt_state_t alt_state
, new_alt_state
;
6419 /* Create states corresponding to equivalence classes containing two
6421 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6422 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6424 if ((*equiv_class_ptr
)->next_equiv_class_state
!= NULL
)
6426 /* There are more one states in the class equivalence. */
6427 /* Create new compound state. */
6428 new_state
= get_free_state (0, automaton
);
6430 first_class_state
= *equiv_class_ptr
;
6431 for (curr_state
= first_class_state
;
6433 curr_state
= curr_state
->next_equiv_class_state
)
6435 curr_state
->equiv_class_state
= new_state
;
6436 if (curr_state
->component_states
== NULL
)
6438 new_alt_state
= get_free_alt_state ();
6439 new_alt_state
->state
= curr_state
;
6440 new_alt_state
->next_alt_state
= alt_states
;
6441 alt_states
= new_alt_state
;
6444 for (alt_state
= curr_state
->component_states
;
6446 alt_state
= alt_state
->next_sorted_alt_state
)
6448 new_alt_state
= get_free_alt_state ();
6449 new_alt_state
->state
= alt_state
->state
;
6450 new_alt_state
->next_alt_state
= alt_states
;
6451 alt_states
= new_alt_state
;
6454 /* Its is important that alt states were sorted before and
6455 after merging to have the same quering results. */
6456 new_state
->component_states
= uniq_sort_alt_states (alt_states
);
6459 (*equiv_class_ptr
)->equiv_class_state
= *equiv_class_ptr
;
6460 for (equiv_class_ptr
= VLA_PTR_BEGIN (*equiv_classes
);
6461 equiv_class_ptr
<= (state_t
*) VLA_PTR_LAST (*equiv_classes
);
6463 if ((*equiv_class_ptr
)->next_equiv_class_state
!= NULL
)
6465 first_class_state
= *equiv_class_ptr
;
6466 /* Create new arcs output from the state corresponding to
6468 for (curr_arc
= first_out_arc (first_class_state
);
6470 curr_arc
= next_out_arc (curr_arc
))
6471 add_arc (first_class_state
->equiv_class_state
,
6472 curr_arc
->to_state
->equiv_class_state
,
6473 curr_arc
->insn
, curr_arc
->state_alts
);
6474 /* Delete output arcs from states of given class equivalence. */
6475 for (curr_state
= first_class_state
;
6477 curr_state
= curr_state
->next_equiv_class_state
)
6479 if (automaton
->start_state
== curr_state
)
6480 automaton
->start_state
= curr_state
->equiv_class_state
;
6481 /* Delete the state and its output arcs. */
6482 for (curr_arc
= first_out_arc (curr_state
);
6484 curr_arc
= next_arc
)
6486 next_arc
= next_out_arc (curr_arc
);
6487 free_arc (curr_arc
);
6493 /* Change `to_state' of arcs output from the state of given
6494 equivalence class. */
6495 for (curr_arc
= first_out_arc (*equiv_class_ptr
);
6497 curr_arc
= next_out_arc (curr_arc
))
6498 curr_arc
->to_state
= curr_arc
->to_state
->equiv_class_state
;
6502 /* The function sets up new_cycle_p for states if there is arc to the
6503 state marked by advance_cycle_insn_decl. */
6505 set_new_cycle_flags (state
)
6510 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6511 if (arc
->insn
->insn_reserv_decl
6512 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
6513 arc
->to_state
->new_cycle_p
= 1;
6516 /* The top level function for minimization of deterministic
6519 minimize_DFA (automaton
)
6520 automaton_t automaton
;
6522 vla_ptr_t equiv_classes
;
6524 VLA_PTR_CREATE (equiv_classes
, 1500, "equivalence classes");
6525 evaluate_equiv_classes (automaton
, &equiv_classes
);
6526 merge_states (automaton
, &equiv_classes
);
6527 pass_states (automaton
, set_new_cycle_flags
);
6528 VLA_PTR_DELETE (equiv_classes
);
6531 /* Values of two variables are counted number of states and arcs in an
6533 static int curr_counted_states_num
;
6534 static int curr_counted_arcs_num
;
6536 /* The function is called by function `pass_states' to count states
6537 and arcs of an automaton. */
6539 incr_states_and_arcs_nums (state
)
6544 curr_counted_states_num
++;
6545 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6546 curr_counted_arcs_num
++;
6549 /* The function counts states and arcs of AUTOMATON. */
6551 count_states_and_arcs (automaton
, states_num
, arcs_num
)
6552 automaton_t automaton
;
6556 curr_counted_states_num
= 0;
6557 curr_counted_arcs_num
= 0;
6558 pass_states (automaton
, incr_states_and_arcs_nums
);
6559 *states_num
= curr_counted_states_num
;
6560 *arcs_num
= curr_counted_arcs_num
;
6563 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6564 recognition after checking and simplifying IR of the
6567 build_automaton (automaton
)
6568 automaton_t automaton
;
6573 ticker_on (&NDFA_time
);
6574 if (automaton
->corresponding_automaton_decl
== NULL
)
6575 fprintf (stderr
, "Create anonymous automaton (1 star is 100 new states):");
6577 fprintf (stderr
, "Create automaton `%s' (1 star is 100 new states):",
6578 automaton
->corresponding_automaton_decl
->name
);
6579 make_automaton (automaton
);
6580 fprintf (stderr
, " done\n");
6581 ticker_off (&NDFA_time
);
6582 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6583 automaton
->NDFA_states_num
= states_num
;
6584 automaton
->NDFA_arcs_num
= arcs_num
;
6585 ticker_on (&NDFA_to_DFA_time
);
6586 if (automaton
->corresponding_automaton_decl
== NULL
)
6587 fprintf (stderr
, "Make anonymous DFA (1 star is 100 new states):");
6589 fprintf (stderr
, "Make DFA `%s' (1 star is 100 new states):",
6590 automaton
->corresponding_automaton_decl
->name
);
6591 NDFA_to_DFA (automaton
);
6592 fprintf (stderr
, " done\n");
6593 ticker_off (&NDFA_to_DFA_time
);
6594 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6595 automaton
->DFA_states_num
= states_num
;
6596 automaton
->DFA_arcs_num
= arcs_num
;
6597 if (!no_minimization_flag
)
6599 ticker_on (&minimize_time
);
6600 if (automaton
->corresponding_automaton_decl
== NULL
)
6601 fprintf (stderr
, "Minimize anonymous DFA...");
6603 fprintf (stderr
, "Minimize DFA `%s'...",
6604 automaton
->corresponding_automaton_decl
->name
);
6605 minimize_DFA (automaton
);
6606 fprintf (stderr
, "done\n");
6607 ticker_off (&minimize_time
);
6608 count_states_and_arcs (automaton
, &states_num
, &arcs_num
);
6609 automaton
->minimal_DFA_states_num
= states_num
;
6610 automaton
->minimal_DFA_arcs_num
= arcs_num
;
6616 /* The page contains code for enumeration of all states of an automaton. */
6618 /* Variable used for enumeration of all states of an automaton. Its
6619 value is current number of automaton states. */
6620 static int curr_state_order_num
;
6622 /* The function is called by function `pass_states' for enumerating
6625 set_order_state_num (state
)
6628 state
->order_state_num
= curr_state_order_num
;
6629 curr_state_order_num
++;
6632 /* The function enumerates all states of AUTOMATON. */
6634 enumerate_states (automaton
)
6635 automaton_t automaton
;
6637 curr_state_order_num
= 0;
6638 pass_states (automaton
, set_order_state_num
);
6639 automaton
->achieved_states_num
= curr_state_order_num
;
6644 /* The page contains code for finding equivalent automaton insns
6647 /* The function inserts AINSN into cyclic list
6648 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6650 insert_ainsn_into_equiv_class (ainsn
, cyclic_equiv_class_insn_list
)
6652 ainsn_t cyclic_equiv_class_insn_list
;
6654 if (cyclic_equiv_class_insn_list
== NULL
)
6655 ainsn
->next_equiv_class_insn
= ainsn
;
6658 ainsn
->next_equiv_class_insn
6659 = cyclic_equiv_class_insn_list
->next_equiv_class_insn
;
6660 cyclic_equiv_class_insn_list
->next_equiv_class_insn
= ainsn
;
6665 /* The function deletes equiv_class_insn into cyclic list of
6666 equivalent ainsns. */
6668 delete_ainsn_from_equiv_class (equiv_class_insn
)
6669 ainsn_t equiv_class_insn
;
6671 ainsn_t curr_equiv_class_insn
;
6672 ainsn_t prev_equiv_class_insn
;
6674 prev_equiv_class_insn
= equiv_class_insn
;
6675 for (curr_equiv_class_insn
= equiv_class_insn
->next_equiv_class_insn
;
6676 curr_equiv_class_insn
!= equiv_class_insn
;
6677 curr_equiv_class_insn
= curr_equiv_class_insn
->next_equiv_class_insn
)
6678 prev_equiv_class_insn
= curr_equiv_class_insn
;
6679 if (prev_equiv_class_insn
!= equiv_class_insn
)
6680 prev_equiv_class_insn
->next_equiv_class_insn
6681 = equiv_class_insn
->next_equiv_class_insn
;
6684 /* The function processes AINSN of a state in order to find equivalent
6685 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6688 process_insn_equiv_class (ainsn
, insn_arcs_array
)
6690 arc_t
*insn_arcs_array
;
6694 ainsn_t cyclic_insn_list
;
6697 if (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
] == NULL
)
6700 /* New class of ainsns which are not equivalent to given ainsn. */
6701 cyclic_insn_list
= NULL
;
6704 next_insn
= curr_insn
->next_equiv_class_insn
;
6705 arc
= insn_arcs_array
[curr_insn
->insn_reserv_decl
->insn_num
];
6707 || (insn_arcs_array
[ainsn
->insn_reserv_decl
->insn_num
]->to_state
6710 delete_ainsn_from_equiv_class (curr_insn
);
6711 cyclic_insn_list
= insert_ainsn_into_equiv_class (curr_insn
,
6714 curr_insn
= next_insn
;
6716 while (curr_insn
!= ainsn
);
6719 /* The function processes STATE in order to find equivalent ainsns. */
6721 process_state_for_insn_equiv_partition (state
)
6725 arc_t
*insn_arcs_array
;
6727 vla_ptr_t insn_arcs_vect
;
6729 VLA_PTR_CREATE (insn_arcs_vect
, 500, "insn arcs vector");
6730 VLA_PTR_EXPAND (insn_arcs_vect
, description
->insns_num
);
6731 insn_arcs_array
= VLA_PTR_BEGIN (insn_arcs_vect
);
6732 /* Process insns of the arcs. */
6733 for (i
= 0; i
< description
->insns_num
; i
++)
6734 insn_arcs_array
[i
] = NULL
;
6735 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6736 insn_arcs_array
[arc
->insn
->insn_reserv_decl
->insn_num
] = arc
;
6737 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
6738 process_insn_equiv_class (arc
->insn
, insn_arcs_array
);
6739 VLA_PTR_DELETE (insn_arcs_vect
);
6742 /* The function searches for equivalent ainsns of AUTOMATON. */
6744 set_insn_equiv_classes (automaton
)
6745 automaton_t automaton
;
6750 ainsn_t cyclic_insn_list
;
6751 ainsn_t insn_with_same_reservs
;
6752 int equiv_classes_num
;
6754 /* All insns are included in one equivalence class. */
6755 cyclic_insn_list
= NULL
;
6756 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6757 if (ainsn
->first_insn_with_same_reservs
)
6758 cyclic_insn_list
= insert_ainsn_into_equiv_class (ainsn
,
6760 /* Process insns in order to make equivalence partition. */
6761 pass_states (automaton
, process_state_for_insn_equiv_partition
);
6762 /* Enumerate equiv classes. */
6763 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6764 /* Set undefined value. */
6765 ainsn
->insn_equiv_class_num
= -1;
6766 equiv_classes_num
= 0;
6767 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
6768 if (ainsn
->insn_equiv_class_num
< 0)
6771 if (!first_insn
->first_insn_with_same_reservs
)
6773 first_insn
->first_ainsn_with_given_equialence_num
= 1;
6774 curr_insn
= first_insn
;
6777 for (insn_with_same_reservs
= curr_insn
;
6778 insn_with_same_reservs
!= NULL
;
6779 insn_with_same_reservs
6780 = insn_with_same_reservs
->next_same_reservs_insn
)
6781 insn_with_same_reservs
->insn_equiv_class_num
= equiv_classes_num
;
6782 curr_insn
= curr_insn
->next_equiv_class_insn
;
6784 while (curr_insn
!= first_insn
);
6785 equiv_classes_num
++;
6787 automaton
->insn_equiv_classes_num
= equiv_classes_num
;
6792 /* This page contains code for creating DFA(s) and calls functions
6796 /* The following value is used to prevent floating point overflow for
6797 estimating an automaton bound. The value should be less DBL_MAX on
6798 the host machine. We use here approximate minimum of maximal
6799 double floating point value required by ANSI C standard. It
6800 will work for non ANSI sun compiler too. */
6802 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6804 /* The function estimate size of the single DFA used by PHR (pipeline
6805 hazards recognizer). */
6807 estimate_one_automaton_bound ()
6810 double one_automaton_estimation_bound
;
6814 one_automaton_estimation_bound
= 1.0;
6815 for (i
= 0; i
< description
->decls_num
; i
++)
6817 decl
= description
->decls
[i
];
6818 if (decl
->mode
== dm_unit
)
6820 root_value
= exp (log (DECL_UNIT (decl
)->max_occ_cycle_num
6821 - DECL_UNIT (decl
)->min_occ_cycle_num
+ 1.0)
6823 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND
/ root_value
6824 > one_automaton_estimation_bound
)
6825 one_automaton_estimation_bound
*= root_value
;
6828 return one_automaton_estimation_bound
;
6831 /* The function compares unit declarations according to their maximal
6832 cycle in reservations. */
6834 compare_max_occ_cycle_nums (unit_decl_1
, unit_decl_2
)
6835 const void *unit_decl_1
;
6836 const void *unit_decl_2
;
6838 if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6839 < (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6841 else if ((DECL_UNIT (*(decl_t
*) unit_decl_1
)->max_occ_cycle_num
)
6842 == (DECL_UNIT (*(decl_t
*) unit_decl_2
)->max_occ_cycle_num
))
6848 /* The function makes heuristic assigning automata to units. Actually
6849 efficacy of the algorithm has been checked yet??? */
6851 units_to_automata_heuristic_distr ()
6853 double estimation_bound
;
6855 decl_t
*unit_decl_ptr
;
6859 vla_ptr_t unit_decls
;
6862 if (description
->units_num
== 0)
6864 estimation_bound
= estimate_one_automaton_bound ();
6865 VLA_PTR_CREATE (unit_decls
, 150, "unit decls");
6866 for (i
= 0; i
< description
->decls_num
; i
++)
6868 decl
= description
->decls
[i
];
6869 if (decl
->mode
== dm_unit
)
6870 VLA_PTR_ADD (unit_decls
, decl
);
6872 qsort (VLA_PTR_BEGIN (unit_decls
), VLA_PTR_LENGTH (unit_decls
),
6873 sizeof (decl_t
), compare_max_occ_cycle_nums
);
6875 unit_decl_ptr
= VLA_PTR_BEGIN (unit_decls
);
6876 bound_value
= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6877 DECL_UNIT (*unit_decl_ptr
)->corresponding_automaton_num
= automaton_num
;
6878 for (unit_decl_ptr
++;
6879 unit_decl_ptr
<= (decl_t
*) VLA_PTR_LAST (unit_decls
);
6883 = ((decl_t
*) VLA_PTR_LAST (unit_decls
) - unit_decl_ptr
+ 1);
6884 if (automata_num
- automaton_num
- 1 > rest_units_num
)
6886 if (automaton_num
< automata_num
- 1
6887 && ((automata_num
- automaton_num
- 1 == rest_units_num
)
6890 / (DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
)))))
6892 bound_value
= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6896 bound_value
*= DECL_UNIT (*unit_decl_ptr
)->max_occ_cycle_num
;
6897 DECL_UNIT (*unit_decl_ptr
)->corresponding_automaton_num
= automaton_num
;
6899 if (automaton_num
!= automata_num
- 1)
6901 VLA_PTR_DELETE (unit_decls
);
6904 /* The functions creates automaton insns for each automata. Automaton
6905 insn is simply insn for given automaton which makes reservation
6906 only of units of the automaton. */
6911 ainsn_t first_ainsn
;
6918 for (i
= 0; i
< description
->decls_num
; i
++)
6920 decl
= description
->decls
[i
];
6921 if (decl
->mode
== dm_insn_reserv
)
6923 curr_ainsn
= create_node (sizeof (struct ainsn
));
6924 curr_ainsn
->insn_reserv_decl
= DECL_INSN_RESERV (decl
);
6925 curr_ainsn
->important_p
= FALSE
;
6926 curr_ainsn
->next_ainsn
= NULL
;
6927 if (prev_ainsn
== NULL
)
6928 first_ainsn
= curr_ainsn
;
6930 prev_ainsn
->next_ainsn
= curr_ainsn
;
6931 prev_ainsn
= curr_ainsn
;
6937 /* The function assigns automata to units according to constructions
6938 `define_automaton' in the description. */
6940 units_to_automata_distr ()
6945 for (i
= 0; i
< description
->decls_num
; i
++)
6947 decl
= description
->decls
[i
];
6948 if (decl
->mode
== dm_unit
)
6950 if (DECL_UNIT (decl
)->automaton_decl
== NULL
6951 || (DECL_UNIT (decl
)->automaton_decl
->corresponding_automaton
6953 /* Distribute to the first automaton. */
6954 DECL_UNIT (decl
)->corresponding_automaton_num
= 0;
6956 DECL_UNIT (decl
)->corresponding_automaton_num
6957 = (DECL_UNIT (decl
)->automaton_decl
6958 ->corresponding_automaton
->automaton_order_num
);
6963 /* The function creates DFA(s) for fast pipeline hazards recognition
6964 after checking and simplifying IR of the description. */
6968 automaton_t curr_automaton
;
6969 automaton_t prev_automaton
;
6971 int curr_automaton_num
;
6974 if (automata_num
!= 0)
6976 units_to_automata_heuristic_distr ();
6977 for (prev_automaton
= NULL
, curr_automaton_num
= 0;
6978 curr_automaton_num
< automata_num
;
6979 curr_automaton_num
++, prev_automaton
= curr_automaton
)
6981 curr_automaton
= create_node (sizeof (struct automaton
));
6982 curr_automaton
->ainsn_list
= create_ainsns ();
6983 curr_automaton
->corresponding_automaton_decl
= NULL
;
6984 curr_automaton
->next_automaton
= NULL
;
6985 curr_automaton
->automaton_order_num
= curr_automaton_num
;
6986 if (prev_automaton
== NULL
)
6987 description
->first_automaton
= curr_automaton
;
6989 prev_automaton
->next_automaton
= curr_automaton
;
6994 curr_automaton_num
= 0;
6995 prev_automaton
= NULL
;
6996 for (i
= 0; i
< description
->decls_num
; i
++)
6998 decl
= description
->decls
[i
];
6999 if (decl
->mode
== dm_automaton
7000 && DECL_AUTOMATON (decl
)->automaton_is_used
)
7002 curr_automaton
= create_node (sizeof (struct automaton
));
7003 curr_automaton
->ainsn_list
= create_ainsns ();
7004 curr_automaton
->corresponding_automaton_decl
7005 = DECL_AUTOMATON (decl
);
7006 curr_automaton
->next_automaton
= NULL
;
7007 DECL_AUTOMATON (decl
)->corresponding_automaton
= curr_automaton
;
7008 curr_automaton
->automaton_order_num
= curr_automaton_num
;
7009 if (prev_automaton
== NULL
)
7010 description
->first_automaton
= curr_automaton
;
7012 prev_automaton
->next_automaton
= curr_automaton
;
7013 curr_automaton_num
++;
7014 prev_automaton
= curr_automaton
;
7017 if (curr_automaton_num
== 0)
7019 curr_automaton
= create_node (sizeof (struct automaton
));
7020 curr_automaton
->ainsn_list
= create_ainsns ();
7021 curr_automaton
->corresponding_automaton_decl
= NULL
;
7022 curr_automaton
->next_automaton
= NULL
;
7023 description
->first_automaton
= curr_automaton
;
7025 units_to_automata_distr ();
7027 NDFA_time
= create_ticker ();
7028 ticker_off (&NDFA_time
);
7029 NDFA_to_DFA_time
= create_ticker ();
7030 ticker_off (&NDFA_to_DFA_time
);
7031 minimize_time
= create_ticker ();
7032 ticker_off (&minimize_time
);
7033 equiv_time
= create_ticker ();
7034 ticker_off (&equiv_time
);
7035 for (curr_automaton
= description
->first_automaton
;
7036 curr_automaton
!= NULL
;
7037 curr_automaton
= curr_automaton
->next_automaton
)
7039 if (curr_automaton
->corresponding_automaton_decl
== NULL
)
7040 fprintf (stderr
, "Prepare anonymous automaton creation ... ");
7042 fprintf (stderr
, "Prepare automaton `%s' creation...",
7043 curr_automaton
->corresponding_automaton_decl
->name
);
7044 create_alt_states (curr_automaton
);
7045 form_ainsn_with_same_reservs (curr_automaton
);
7046 fprintf (stderr
, "done\n");
7047 build_automaton (curr_automaton
);
7048 enumerate_states (curr_automaton
);
7049 ticker_on (&equiv_time
);
7050 set_insn_equiv_classes (curr_automaton
);
7051 ticker_off (&equiv_time
);
7057 /* This page contains code for forming string representation of
7058 regexp. The representation is formed on IR obstack. So you should
7059 not work with IR obstack between regexp_representation and
7060 finish_regexp_representation calls. */
7062 /* This recursive function forms string representation of regexp
7063 (without tailing '\0'). */
7065 form_regexp (regexp
)
7070 if (regexp
->mode
== rm_unit
|| regexp
->mode
== rm_reserv
)
7072 const char *name
= (regexp
->mode
== rm_unit
7073 ? REGEXP_UNIT (regexp
)->name
7074 : REGEXP_RESERV (regexp
)->name
);
7076 obstack_grow (&irp
, name
, strlen (name
));
7078 else if (regexp
->mode
== rm_sequence
)
7079 for (i
= 0; i
< REGEXP_SEQUENCE (regexp
)->regexps_num
; i
++)
7082 obstack_1grow (&irp
, ',');
7083 form_regexp (REGEXP_SEQUENCE (regexp
)->regexps
[i
]);
7085 else if (regexp
->mode
== rm_allof
)
7087 obstack_1grow (&irp
, '(');
7088 for (i
= 0; i
< REGEXP_ALLOF (regexp
)->regexps_num
; i
++)
7091 obstack_1grow (&irp
, '+');
7092 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
7093 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
7094 obstack_1grow (&irp
, '(');
7095 form_regexp (REGEXP_ALLOF (regexp
)->regexps
[i
]);
7096 if (REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_sequence
7097 || REGEXP_ALLOF (regexp
)->regexps
[i
]->mode
== rm_oneof
)
7098 obstack_1grow (&irp
, ')');
7100 obstack_1grow (&irp
, ')');
7102 else if (regexp
->mode
== rm_oneof
)
7103 for (i
= 0; i
< REGEXP_ONEOF (regexp
)->regexps_num
; i
++)
7106 obstack_1grow (&irp
, '|');
7107 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
7108 obstack_1grow (&irp
, '(');
7109 form_regexp (REGEXP_ONEOF (regexp
)->regexps
[i
]);
7110 if (REGEXP_ONEOF (regexp
)->regexps
[i
]->mode
== rm_sequence
)
7111 obstack_1grow (&irp
, ')');
7113 else if (regexp
->mode
== rm_repeat
)
7117 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
7118 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
7119 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
7120 obstack_1grow (&irp
, '(');
7121 form_regexp (REGEXP_REPEAT (regexp
)->regexp
);
7122 if (REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_sequence
7123 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_allof
7124 || REGEXP_REPEAT (regexp
)->regexp
->mode
== rm_oneof
)
7125 obstack_1grow (&irp
, ')');
7126 sprintf (digits
, "*%d", REGEXP_REPEAT (regexp
)->repeat_num
);
7127 obstack_grow (&irp
, digits
, strlen (digits
));
7129 else if (regexp
->mode
== rm_nothing
)
7130 obstack_grow (&irp
, NOTHING_NAME
, strlen (NOTHING_NAME
));
7135 /* The function returns string representation of REGEXP on IR
7138 regexp_representation (regexp
)
7141 form_regexp (regexp
);
7142 obstack_1grow (&irp
, '\0');
7143 return obstack_base (&irp
);
7146 /* The function frees memory allocated for last formed string
7147 representation of regexp. */
7149 finish_regexp_representation ()
7151 int length
= obstack_object_size (&irp
);
7153 obstack_blank_fast (&irp
, -length
);
7158 /* This page contains code for output PHR (pipeline hazards recognizer). */
7160 /* The function outputs minimal C type which is sufficient for
7161 representation numbers in range min_range_value and
7162 max_range_value. Because host machine and build machine may be
7163 different, we use here minimal values required by ANSI C standard
7164 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
7168 output_range_type (f
, min_range_value
, max_range_value
)
7170 long int min_range_value
;
7171 long int max_range_value
;
7173 if (min_range_value
>= 0 && max_range_value
<= 255)
7174 fprintf (f
, "unsigned char");
7175 else if (min_range_value
>= -127 && max_range_value
<= 127)
7176 fprintf (f
, "signed char");
7177 else if (min_range_value
>= 0 && max_range_value
<= 65535)
7178 fprintf (f
, "unsigned short");
7179 else if (min_range_value
>= -32767 && max_range_value
<= 32767)
7180 fprintf (f
, "short");
7185 /* The following macro value is used as value of member
7186 `longest_path_length' of state when we are processing path and the
7187 state on the path. */
7189 #define ON_THE_PATH -2
7191 /* The following recursive function searches for the length of the
7192 longest path starting from STATE which does not contain cycles and
7193 `cycle advance' arcs. */
7196 longest_path_length (state
)
7202 if (state
->longest_path_length
== ON_THE_PATH
)
7203 /* We don't expect the path cycle here. Our graph may contain
7204 only cycles with one state on the path not containing `cycle
7205 advance' arcs -- see comment below. */
7207 else if (state
->longest_path_length
!= UNDEFINED_LONGEST_PATH_LENGTH
)
7208 /* We already visited the state. */
7209 return state
->longest_path_length
;
7212 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7213 /* Ignore cycles containing one state and `cycle advance' arcs. */
7214 if (arc
->to_state
!= state
7215 && (arc
->insn
->insn_reserv_decl
7216 != DECL_INSN_RESERV (advance_cycle_insn_decl
)))
7218 length
= longest_path_length (arc
->to_state
);
7219 if (length
> result
)
7222 state
->longest_path_length
= result
+ 1;
7226 /* The following variable value is value of the corresponding global
7227 variable in the automaton based pipeline interface. */
7229 static int max_dfa_issue_rate
;
7231 /* The following function processes the longest path length staring
7232 from STATE to find MAX_DFA_ISSUE_RATE. */
7235 process_state_longest_path_length (state
)
7240 value
= longest_path_length (state
);
7241 if (value
> max_dfa_issue_rate
)
7242 max_dfa_issue_rate
= value
;
7245 /* The following macro value is name of the corresponding global
7246 variable in the automaton based pipeline interface. */
7248 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
7250 /* The following function calculates value of the corresponding
7251 global variable and outputs its declaration. */
7254 output_dfa_max_issue_rate ()
7256 automaton_t automaton
;
7258 if (UNDEFINED_LONGEST_PATH_LENGTH
== ON_THE_PATH
|| ON_THE_PATH
>= 0)
7260 max_dfa_issue_rate
= 0;
7261 for (automaton
= description
->first_automaton
;
7263 automaton
= automaton
->next_automaton
)
7264 pass_states (automaton
, process_state_longest_path_length
);
7265 fprintf (output_file
, "\nint %s = %d;\n",
7266 MAX_DFA_ISSUE_RATE_VAR_NAME
, max_dfa_issue_rate
);
7269 /* The function outputs all initialization values of VECT with length
7272 output_vect (vect
, vect_length
)
7279 if (vect_length
== 0)
7280 fprintf (output_file
,
7281 "0 /* This is dummy el because the vect is empty */");
7286 fprintf (output_file
, "%5ld", (long) *vect
);
7288 if (els_on_line
== 10)
7291 fprintf (output_file
, ",\n");
7293 else if (vect_length
!= 0)
7294 fprintf (output_file
, ", ");
7298 while (vect_length
!= 0);
7302 /* The following is name of the structure which represents DFA(s) for
7304 #define CHIP_NAME "DFA_chip"
7306 /* The following is name of member which represents state of a DFA for
7309 output_chip_member_name (f
, automaton
)
7311 automaton_t automaton
;
7313 if (automaton
->corresponding_automaton_decl
== NULL
)
7314 fprintf (f
, "automaton_state_%d", automaton
->automaton_order_num
);
7316 fprintf (f
, "%s_automaton_state",
7317 automaton
->corresponding_automaton_decl
->name
);
7320 /* The following is name of temporary variable which stores state of a
7323 output_temp_chip_member_name (f
, automaton
)
7325 automaton_t automaton
;
7328 output_chip_member_name (f
, automaton
);
7331 /* This is name of macro value which is code of pseudo_insn
7332 representing advancing cpu cycle. Its value is used as internal
7333 code unknown insn. */
7334 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7336 /* Output name of translate vector for given automaton. */
7338 output_translate_vect_name (f
, automaton
)
7340 automaton_t automaton
;
7342 if (automaton
->corresponding_automaton_decl
== NULL
)
7343 fprintf (f
, "translate_%d", automaton
->automaton_order_num
);
7345 fprintf (f
, "%s_translate", automaton
->corresponding_automaton_decl
->name
);
7348 /* Output name for simple transition table representation. */
7350 output_trans_full_vect_name (f
, automaton
)
7352 automaton_t automaton
;
7354 if (automaton
->corresponding_automaton_decl
== NULL
)
7355 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7357 fprintf (f
, "%s_transitions",
7358 automaton
->corresponding_automaton_decl
->name
);
7361 /* Output name of comb vector of the transition table for given
7364 output_trans_comb_vect_name (f
, automaton
)
7366 automaton_t automaton
;
7368 if (automaton
->corresponding_automaton_decl
== NULL
)
7369 fprintf (f
, "transitions_%d", automaton
->automaton_order_num
);
7371 fprintf (f
, "%s_transitions",
7372 automaton
->corresponding_automaton_decl
->name
);
7375 /* Output name of check vector of the transition table for given
7378 output_trans_check_vect_name (f
, automaton
)
7380 automaton_t automaton
;
7382 if (automaton
->corresponding_automaton_decl
== NULL
)
7383 fprintf (f
, "check_%d", automaton
->automaton_order_num
);
7385 fprintf (f
, "%s_check", automaton
->corresponding_automaton_decl
->name
);
7388 /* Output name of base vector of the transition table for given
7391 output_trans_base_vect_name (f
, automaton
)
7393 automaton_t automaton
;
7395 if (automaton
->corresponding_automaton_decl
== NULL
)
7396 fprintf (f
, "base_%d", automaton
->automaton_order_num
);
7398 fprintf (f
, "%s_base", automaton
->corresponding_automaton_decl
->name
);
7401 /* Output name for simple alternatives number representation. */
7403 output_state_alts_full_vect_name (f
, automaton
)
7405 automaton_t automaton
;
7407 if (automaton
->corresponding_automaton_decl
== NULL
)
7408 fprintf (f
, "state_alts_%d", automaton
->automaton_order_num
);
7410 fprintf (f
, "%s_state_alts",
7411 automaton
->corresponding_automaton_decl
->name
);
7414 /* Output name of comb vector of the alternatives number table for given
7417 output_state_alts_comb_vect_name (f
, automaton
)
7419 automaton_t automaton
;
7421 if (automaton
->corresponding_automaton_decl
== NULL
)
7422 fprintf (f
, "state_alts_%d", automaton
->automaton_order_num
);
7424 fprintf (f
, "%s_state_alts",
7425 automaton
->corresponding_automaton_decl
->name
);
7428 /* Output name of check vector of the alternatives number table for given
7431 output_state_alts_check_vect_name (f
, automaton
)
7433 automaton_t automaton
;
7435 if (automaton
->corresponding_automaton_decl
== NULL
)
7436 fprintf (f
, "check_state_alts_%d", automaton
->automaton_order_num
);
7438 fprintf (f
, "%s_check_state_alts",
7439 automaton
->corresponding_automaton_decl
->name
);
7442 /* Output name of base vector of the alternatives number table for given
7445 output_state_alts_base_vect_name (f
, automaton
)
7447 automaton_t automaton
;
7449 if (automaton
->corresponding_automaton_decl
== NULL
)
7450 fprintf (f
, "base_state_alts_%d", automaton
->automaton_order_num
);
7452 fprintf (f
, "%s_base_state_alts",
7453 automaton
->corresponding_automaton_decl
->name
);
7456 /* Output name of simple min issue delay table representation. */
7458 output_min_issue_delay_vect_name (f
, automaton
)
7460 automaton_t automaton
;
7462 if (automaton
->corresponding_automaton_decl
== NULL
)
7463 fprintf (f
, "min_issue_delay_%d", automaton
->automaton_order_num
);
7465 fprintf (f
, "%s_min_issue_delay",
7466 automaton
->corresponding_automaton_decl
->name
);
7469 /* Output name of deadlock vector for given automaton. */
7471 output_dead_lock_vect_name (f
, automaton
)
7473 automaton_t automaton
;
7475 if (automaton
->corresponding_automaton_decl
== NULL
)
7476 fprintf (f
, "dead_lock_%d", automaton
->automaton_order_num
);
7478 fprintf (f
, "%s_dead_lock", automaton
->corresponding_automaton_decl
->name
);
7481 /* Output name of reserved units table for AUTOMATON into file F. */
7483 output_reserved_units_table_name (f
, automaton
)
7485 automaton_t automaton
;
7487 if (automaton
->corresponding_automaton_decl
== NULL
)
7488 fprintf (f
, "reserved_units_%d", automaton
->automaton_order_num
);
7490 fprintf (f
, "%s_reserved_units",
7491 automaton
->corresponding_automaton_decl
->name
);
7494 /* Name of the PHR interface macro. */
7495 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7497 /* Name of the PHR interface macro. */
7498 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7500 /* Names of an internal functions: */
7501 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7503 /* This is external type of DFA(s) state. */
7504 #define STATE_TYPE_NAME "state_t"
7506 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7508 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7510 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7512 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7514 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7516 /* Name of cache of insn dfa codes. */
7517 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7519 /* Name of length of cache of insn dfa codes. */
7520 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7522 /* Names of the PHR interface functions: */
7523 #define SIZE_FUNC_NAME "state_size"
7525 #define TRANSITION_FUNC_NAME "state_transition"
7527 #define STATE_ALTS_FUNC_NAME "state_alts"
7529 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7531 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7533 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7535 #define RESET_FUNC_NAME "state_reset"
7537 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7539 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7541 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7543 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7545 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7547 #define DFA_START_FUNC_NAME "dfa_start"
7549 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7551 /* Names of parameters of the PHR interface functions. */
7552 #define STATE_NAME "state"
7554 #define INSN_PARAMETER_NAME "insn"
7556 #define INSN2_PARAMETER_NAME "insn2"
7558 #define CHIP_PARAMETER_NAME "chip"
7560 #define FILE_PARAMETER_NAME "f"
7562 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7564 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7566 /* Names of the variables whose values are internal insn code of rtx
7568 #define INTERNAL_INSN_CODE_NAME "insn_code"
7570 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7572 /* Names of temporary variables in some functions. */
7573 #define TEMPORARY_VARIABLE_NAME "temp"
7575 #define I_VARIABLE_NAME "i"
7577 /* Name of result variable in some functions. */
7578 #define RESULT_VARIABLE_NAME "res"
7580 /* Name of function (attribute) to translate insn into internal insn
7582 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7584 /* Name of function (attribute) to translate insn into internal insn
7585 code with caching. */
7586 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7588 /* Name of function (attribute) to translate insn into internal insn
7590 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7592 /* Name of function (attribute) to translate insn into internal insn
7594 #define BYPASS_P_FUNC_NAME "bypass_p"
7596 /* Output C type which is used for representation of codes of states
7599 output_state_member_type (f
, automaton
)
7601 automaton_t automaton
;
7603 output_range_type (f
, 0, automaton
->achieved_states_num
);
7606 /* Output definition of the structure representing current DFA(s)
7609 output_chip_definitions ()
7611 automaton_t automaton
;
7613 fprintf (output_file
, "struct %s\n{\n", CHIP_NAME
);
7614 for (automaton
= description
->first_automaton
;
7616 automaton
= automaton
->next_automaton
)
7618 fprintf (output_file
, " ");
7619 output_state_member_type (output_file
, automaton
);
7620 fprintf (output_file
, " ");
7621 output_chip_member_name (output_file
, automaton
);
7622 fprintf (output_file
, ";\n");
7624 fprintf (output_file
, "};\n\n");
7626 fprintf (output_file
, "static struct %s %s;\n\n", CHIP_NAME
, CHIP_NAME
);
7631 /* The function outputs translate vector of internal insn code into
7632 insn equivalence class number. The equivalence class number is
7633 used to access to table and vectors representing DFA(s). */
7635 output_translate_vect (automaton
)
7636 automaton_t automaton
;
7640 vla_hwint_t translate_vect
;
7642 VLA_HWINT_CREATE (translate_vect
, 250, "translate vector");
7643 VLA_HWINT_EXPAND (translate_vect
, description
->insns_num
);
7644 for (insn_value
= 0; insn_value
<= description
->insns_num
; insn_value
++)
7645 /* Undefined value */
7646 VLA_HWINT (translate_vect
, insn_value
) = automaton
->insn_equiv_classes_num
;
7647 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
7648 VLA_HWINT (translate_vect
, ainsn
->insn_reserv_decl
->insn_num
)
7649 = ainsn
->insn_equiv_class_num
;
7650 fprintf (output_file
,
7651 "/* Vector translating external insn codes to internal ones.*/\n");
7652 fprintf (output_file
, "static const ");
7653 output_range_type (output_file
, 0, automaton
->insn_equiv_classes_num
);
7654 fprintf (output_file
, " ");
7655 output_translate_vect_name (output_file
, automaton
);
7656 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7657 output_vect (VLA_HWINT_BEGIN (translate_vect
),
7658 VLA_HWINT_LENGTH (translate_vect
));
7659 fprintf (output_file
, "};\n\n");
7660 VLA_HWINT_DELETE (translate_vect
);
7663 /* The value in a table state x ainsn -> something which represents
7665 static int undefined_vect_el_value
;
7667 /* The following function returns nonzero value if the best
7668 representation of the table is comb vector. */
7671 state_ainsn_table_t tab
;
7673 return (2 * VLA_HWINT_LENGTH (tab
->full_vect
)
7674 > 5 * VLA_HWINT_LENGTH (tab
->comb_vect
));
7677 /* The following function creates new table for AUTOMATON. */
7678 static state_ainsn_table_t
7679 create_state_ainsn_table (automaton
)
7680 automaton_t automaton
;
7682 state_ainsn_table_t tab
;
7683 int full_vect_length
;
7686 tab
= create_node (sizeof (struct state_ainsn_table
));
7687 tab
->automaton
= automaton
;
7688 VLA_HWINT_CREATE (tab
->comb_vect
, 10000, "comb vector");
7689 VLA_HWINT_CREATE (tab
->check_vect
, 10000, "check vector");
7690 VLA_HWINT_CREATE (tab
->base_vect
, 1000, "base vector");
7691 VLA_HWINT_EXPAND (tab
->base_vect
, automaton
->achieved_states_num
);
7692 VLA_HWINT_CREATE (tab
->full_vect
, 10000, "full vector");
7693 full_vect_length
= (automaton
->insn_equiv_classes_num
7694 * automaton
->achieved_states_num
);
7695 VLA_HWINT_EXPAND (tab
->full_vect
, full_vect_length
);
7696 for (i
= 0; i
< full_vect_length
; i
++)
7697 VLA_HWINT (tab
->full_vect
, i
) = undefined_vect_el_value
;
7698 tab
->min_base_vect_el_value
= 0;
7699 tab
->max_base_vect_el_value
= 0;
7700 tab
->min_comb_vect_el_value
= 0;
7701 tab
->max_comb_vect_el_value
= 0;
7705 /* The following function outputs the best C representation of the
7706 table TAB of given TABLE_NAME. */
7708 output_state_ainsn_table (tab
, table_name
, output_full_vect_name_func
,
7709 output_comb_vect_name_func
,
7710 output_check_vect_name_func
,
7711 output_base_vect_name_func
)
7712 state_ainsn_table_t tab
;
7714 void (*output_full_vect_name_func
) PARAMS ((FILE *, automaton_t
));
7715 void (*output_comb_vect_name_func
) PARAMS ((FILE *, automaton_t
));
7716 void (*output_check_vect_name_func
) PARAMS ((FILE *, automaton_t
));
7717 void (*output_base_vect_name_func
) PARAMS ((FILE *, automaton_t
));
7719 if (!comb_vect_p (tab
))
7721 fprintf (output_file
, "/* Vector for %s. */\n", table_name
);
7722 fprintf (output_file
, "static const ");
7723 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7724 tab
->max_comb_vect_el_value
);
7725 fprintf (output_file
, " ");
7726 (*output_full_vect_name_func
) (output_file
, tab
->automaton
);
7727 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7728 output_vect (VLA_HWINT_BEGIN (tab
->full_vect
),
7729 VLA_HWINT_LENGTH (tab
->full_vect
));
7730 fprintf (output_file
, "};\n\n");
7734 fprintf (output_file
, "/* Comb vector for %s. */\n", table_name
);
7735 fprintf (output_file
, "static const ");
7736 output_range_type (output_file
, tab
->min_comb_vect_el_value
,
7737 tab
->max_comb_vect_el_value
);
7738 fprintf (output_file
, " ");
7739 (*output_comb_vect_name_func
) (output_file
, tab
->automaton
);
7740 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
7741 output_vect (VLA_HWINT_BEGIN (tab
->comb_vect
),
7742 VLA_HWINT_LENGTH (tab
->comb_vect
));
7743 fprintf (output_file
, "};\n\n");
7744 fprintf (output_file
, "/* Check vector for %s. */\n", table_name
);
7745 fprintf (output_file
, "static const ");
7746 output_range_type (output_file
, 0, tab
->automaton
->achieved_states_num
);
7747 fprintf (output_file
, " ");
7748 (*output_check_vect_name_func
) (output_file
, tab
->automaton
);
7749 fprintf (output_file
, "[] = {\n");
7750 output_vect (VLA_HWINT_BEGIN (tab
->check_vect
),
7751 VLA_HWINT_LENGTH (tab
->check_vect
));
7752 fprintf (output_file
, "};\n\n");
7753 fprintf (output_file
, "/* Base vector for %s. */\n", table_name
);
7754 fprintf (output_file
, "static const ");
7755 output_range_type (output_file
, tab
->min_base_vect_el_value
,
7756 tab
->max_base_vect_el_value
);
7757 fprintf (output_file
, " ");
7758 (*output_base_vect_name_func
) (output_file
, tab
->automaton
);
7759 fprintf (output_file
, "[] = {\n");
7760 output_vect (VLA_HWINT_BEGIN (tab
->base_vect
),
7761 VLA_HWINT_LENGTH (tab
->base_vect
));
7762 fprintf (output_file
, "};\n\n");
7766 /* The following function adds vector with length VECT_LENGTH and
7767 elements pointed by VECT to table TAB as its line with number
7770 add_vect (tab
, vect_num
, vect
, vect_length
)
7771 state_ainsn_table_t tab
;
7776 int real_vect_length
;
7777 vect_el_t
*comb_vect_start
;
7778 vect_el_t
*check_vect_start
;
7779 int comb_vect_index
;
7780 int comb_vect_els_num
;
7782 int first_unempty_vect_index
;
7783 int additional_els_num
;
7788 if (vect_length
== 0)
7790 real_vect_length
= tab
->automaton
->insn_equiv_classes_num
;
7791 if (vect
[vect_length
- 1] == undefined_vect_el_value
)
7793 /* Form full vector in the table: */
7794 for (i
= 0; i
< vect_length
; i
++)
7795 VLA_HWINT (tab
->full_vect
,
7796 i
+ tab
->automaton
->insn_equiv_classes_num
* vect_num
)
7798 /* Form comb vector in the table: */
7799 if (VLA_HWINT_LENGTH (tab
->comb_vect
) != VLA_HWINT_LENGTH (tab
->check_vect
))
7801 comb_vect_start
= VLA_HWINT_BEGIN (tab
->comb_vect
);
7802 comb_vect_els_num
= VLA_HWINT_LENGTH (tab
->comb_vect
);
7803 for (first_unempty_vect_index
= 0;
7804 first_unempty_vect_index
< vect_length
;
7805 first_unempty_vect_index
++)
7806 if (vect
[first_unempty_vect_index
] != undefined_vect_el_value
)
7808 /* Search for the place in comb vect for the inserted vect. */
7809 for (comb_vect_index
= 0;
7810 comb_vect_index
< comb_vect_els_num
;
7813 for (vect_index
= first_unempty_vect_index
;
7814 vect_index
< vect_length
7815 && vect_index
+ comb_vect_index
< comb_vect_els_num
;
7817 if (vect
[vect_index
] != undefined_vect_el_value
7818 && (comb_vect_start
[vect_index
+ comb_vect_index
]
7819 != undefined_vect_el_value
))
7821 if (vect_index
>= vect_length
7822 || vect_index
+ comb_vect_index
>= comb_vect_els_num
)
7825 /* Slot was found. */
7826 additional_els_num
= comb_vect_index
+ real_vect_length
- comb_vect_els_num
;
7827 if (additional_els_num
< 0)
7828 additional_els_num
= 0;
7829 /* Expand comb and check vectors. */
7830 vect_el
= undefined_vect_el_value
;
7831 no_state_value
= tab
->automaton
->achieved_states_num
;
7832 while (additional_els_num
> 0)
7834 VLA_HWINT_ADD (tab
->comb_vect
, vect_el
);
7835 VLA_HWINT_ADD (tab
->check_vect
, no_state_value
);
7836 additional_els_num
--;
7838 comb_vect_start
= VLA_HWINT_BEGIN (tab
->comb_vect
);
7839 check_vect_start
= VLA_HWINT_BEGIN (tab
->check_vect
);
7840 if (VLA_HWINT_LENGTH (tab
->comb_vect
)
7841 < (size_t) (comb_vect_index
+ real_vect_length
))
7843 /* Fill comb and check vectors. */
7844 for (vect_index
= 0; vect_index
< vect_length
; vect_index
++)
7845 if (vect
[vect_index
] != undefined_vect_el_value
)
7847 if (comb_vect_start
[comb_vect_index
+ vect_index
]
7848 != undefined_vect_el_value
)
7850 comb_vect_start
[comb_vect_index
+ vect_index
] = vect
[vect_index
];
7851 if (vect
[vect_index
] < 0)
7853 if (tab
->max_comb_vect_el_value
< vect
[vect_index
])
7854 tab
->max_comb_vect_el_value
= vect
[vect_index
];
7855 if (tab
->min_comb_vect_el_value
> vect
[vect_index
])
7856 tab
->min_comb_vect_el_value
= vect
[vect_index
];
7857 check_vect_start
[comb_vect_index
+ vect_index
] = vect_num
;
7859 if (tab
->max_base_vect_el_value
< comb_vect_index
)
7860 tab
->max_base_vect_el_value
= comb_vect_index
;
7861 if (tab
->min_base_vect_el_value
> comb_vect_index
)
7862 tab
->min_base_vect_el_value
= comb_vect_index
;
7863 VLA_HWINT (tab
->base_vect
, vect_num
) = comb_vect_index
;
7866 /* Return number of out arcs of STATE. */
7868 out_state_arcs_num (state
)
7875 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
7877 if (arc
->insn
== NULL
)
7879 if (arc
->insn
->first_ainsn_with_given_equialence_num
)
7885 /* Compare number of possible transitions from the states. */
7887 compare_transition_els_num (state_ptr_1
, state_ptr_2
)
7888 const void *state_ptr_1
;
7889 const void *state_ptr_2
;
7891 int transition_els_num_1
;
7892 int transition_els_num_2
;
7894 transition_els_num_1
= out_state_arcs_num (*(state_t
*) state_ptr_1
);
7895 transition_els_num_2
= out_state_arcs_num (*(state_t
*) state_ptr_2
);
7896 if (transition_els_num_1
< transition_els_num_2
)
7898 else if (transition_els_num_1
== transition_els_num_2
)
7904 /* The function adds element EL_VALUE to vector VECT for a table state
7907 add_vect_el (vect
, ainsn
, el_value
)
7912 int equiv_class_num
;
7917 equiv_class_num
= ainsn
->insn_equiv_class_num
;
7918 for (vect_index
= VLA_HWINT_LENGTH (*vect
);
7919 vect_index
<= equiv_class_num
;
7921 VLA_HWINT_ADD (*vect
, undefined_vect_el_value
);
7922 VLA_HWINT (*vect
, equiv_class_num
) = el_value
;
7925 /* This is for forming vector of states of an automaton. */
7926 static vla_ptr_t output_states_vect
;
7928 /* The function is called by function pass_states. The function adds
7929 STATE to `output_states_vect'. */
7931 add_states_vect_el (state
)
7934 VLA_PTR_ADD (output_states_vect
, state
);
7937 /* Form and output vectors (comb, check, base or full vector)
7938 representing transition table of AUTOMATON. */
7940 output_trans_table (automaton
)
7941 automaton_t automaton
;
7945 vla_hwint_t transition_vect
;
7947 undefined_vect_el_value
= automaton
->achieved_states_num
;
7948 automaton
->trans_table
= create_state_ainsn_table (automaton
);
7949 /* Create vect of pointers to states ordered by num of transitions
7950 from the state (state with the maximum num is the first). */
7951 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
7952 pass_states (automaton
, add_states_vect_el
);
7953 qsort (VLA_PTR_BEGIN (output_states_vect
),
7954 VLA_PTR_LENGTH (output_states_vect
),
7955 sizeof (state_t
), compare_transition_els_num
);
7956 VLA_HWINT_CREATE (transition_vect
, 500, "transition vector");
7957 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
7958 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
7961 VLA_HWINT_NULLIFY (transition_vect
);
7962 for (arc
= first_out_arc (*state_ptr
);
7964 arc
= next_out_arc (arc
))
7966 if (arc
->insn
== NULL
)
7968 if (arc
->insn
->first_ainsn_with_given_equialence_num
)
7969 add_vect_el (&transition_vect
, arc
->insn
,
7970 arc
->to_state
->order_state_num
);
7972 add_vect (automaton
->trans_table
, (*state_ptr
)->order_state_num
,
7973 VLA_HWINT_BEGIN (transition_vect
),
7974 VLA_HWINT_LENGTH (transition_vect
));
7976 output_state_ainsn_table
7977 (automaton
->trans_table
, (char *) "state transitions",
7978 output_trans_full_vect_name
, output_trans_comb_vect_name
,
7979 output_trans_check_vect_name
, output_trans_base_vect_name
);
7980 VLA_PTR_DELETE (output_states_vect
);
7981 VLA_HWINT_DELETE (transition_vect
);
7984 /* Form and output vectors (comb, check, base or simple vect)
7985 representing alts number table of AUTOMATON. The table is state x
7986 ainsn -> number of possible alternative reservations by the
7989 output_state_alts_table (automaton
)
7990 automaton_t automaton
;
7994 vla_hwint_t state_alts_vect
;
7996 undefined_vect_el_value
= 0; /* no alts when transition is not possible */
7997 automaton
->state_alts_table
= create_state_ainsn_table (automaton
);
7998 /* Create vect of pointers to states ordered by num of transitions
7999 from the state (state with the maximum num is the first). */
8000 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8001 pass_states (automaton
, add_states_vect_el
);
8002 qsort (VLA_PTR_BEGIN (output_states_vect
),
8003 VLA_PTR_LENGTH (output_states_vect
),
8004 sizeof (state_t
), compare_transition_els_num
);
8005 /* Create base, comb, and check vectors. */
8006 VLA_HWINT_CREATE (state_alts_vect
, 500, "state alts vector");
8007 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8008 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8011 VLA_HWINT_NULLIFY (state_alts_vect
);
8012 for (arc
= first_out_arc (*state_ptr
);
8014 arc
= next_out_arc (arc
))
8016 if (arc
->insn
== NULL
)
8018 if (arc
->insn
->first_ainsn_with_given_equialence_num
)
8019 add_vect_el (&state_alts_vect
, arc
->insn
, arc
->state_alts
);
8021 add_vect (automaton
->state_alts_table
, (*state_ptr
)->order_state_num
,
8022 VLA_HWINT_BEGIN (state_alts_vect
),
8023 VLA_HWINT_LENGTH (state_alts_vect
));
8025 output_state_ainsn_table
8026 (automaton
->state_alts_table
, (char *) "state insn alternatives",
8027 output_state_alts_full_vect_name
, output_state_alts_comb_vect_name
,
8028 output_state_alts_check_vect_name
, output_state_alts_base_vect_name
);
8029 VLA_PTR_DELETE (output_states_vect
);
8030 VLA_HWINT_DELETE (state_alts_vect
);
8033 /* The current number of passing states to find minimal issue delay
8034 value for an ainsn and state. */
8035 static int curr_state_pass_num
;
8037 /* This recursive function passes states to find minimal issue delay
8038 value for AINSN. The state being visited is STATE. The function
8039 returns minimal issue delay value for AINSN in STATE or -1 if we
8040 enter into a loop. */
8042 min_issue_delay_pass_states (state
, ainsn
)
8047 int min_insn_issue_delay
, insn_issue_delay
;
8049 if (state
->state_pass_num
== curr_state_pass_num
8050 || state
->min_insn_issue_delay
!= -1)
8051 /* We've entered into a loop or already have the correct value for
8052 given state and ainsn. */
8053 return state
->min_insn_issue_delay
;
8054 state
->state_pass_num
= curr_state_pass_num
;
8055 min_insn_issue_delay
= -1;
8056 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
8057 if (arc
->insn
== ainsn
)
8059 min_insn_issue_delay
= 0;
8064 insn_issue_delay
= min_issue_delay_pass_states (arc
->to_state
, ainsn
);
8065 if (insn_issue_delay
!= -1)
8067 if (arc
->insn
->insn_reserv_decl
8068 == DECL_INSN_RESERV (advance_cycle_insn_decl
))
8070 if (min_insn_issue_delay
== -1
8071 || min_insn_issue_delay
> insn_issue_delay
)
8073 min_insn_issue_delay
= insn_issue_delay
;
8074 if (insn_issue_delay
== 0)
8079 return min_insn_issue_delay
;
8082 /* The function searches minimal issue delay value for AINSN in STATE.
8083 The function can return negative value if we can not issue AINSN. We
8084 will report about it later. */
8086 min_issue_delay (state
, ainsn
)
8090 curr_state_pass_num
++;
8091 state
->min_insn_issue_delay
= min_issue_delay_pass_states (state
, ainsn
);
8092 return state
->min_insn_issue_delay
;
8095 /* The function initiates code for finding minimal issue delay values.
8096 It should be called only once. */
8098 initiate_min_issue_delay_pass_states ()
8100 curr_state_pass_num
= 0;
8103 /* Form and output vectors representing minimal issue delay table of
8104 AUTOMATON. The table is state x ainsn -> minimal issue delay of
8107 output_min_issue_delay_table (automaton
)
8108 automaton_t automaton
;
8110 vla_hwint_t min_issue_delay_vect
;
8111 vla_hwint_t compressed_min_issue_delay_vect
;
8112 vect_el_t min_delay
;
8117 /* Create vect of pointers to states ordered by num of transitions
8118 from the state (state with the maximum num is the first). */
8119 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8120 pass_states (automaton
, add_states_vect_el
);
8121 VLA_HWINT_CREATE (min_issue_delay_vect
, 1500, "min issue delay vector");
8122 VLA_HWINT_EXPAND (min_issue_delay_vect
,
8123 VLA_HWINT_LENGTH (output_states_vect
)
8124 * automaton
->insn_equiv_classes_num
);
8126 i
< ((int) VLA_HWINT_LENGTH (output_states_vect
)
8127 * automaton
->insn_equiv_classes_num
);
8129 VLA_HWINT (min_issue_delay_vect
, i
) = 0;
8130 automaton
->max_min_delay
= 0;
8131 for (ainsn
= automaton
->ainsn_list
; ainsn
!= NULL
; ainsn
= ainsn
->next_ainsn
)
8132 if (ainsn
->first_ainsn_with_given_equialence_num
)
8134 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8135 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8137 (*state_ptr
)->min_insn_issue_delay
= -1;
8138 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8139 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8142 min_delay
= min_issue_delay (*state_ptr
, ainsn
);
8143 if (automaton
->max_min_delay
< min_delay
)
8144 automaton
->max_min_delay
= min_delay
;
8145 VLA_HWINT (min_issue_delay_vect
,
8146 (*state_ptr
)->order_state_num
8147 * automaton
->insn_equiv_classes_num
8148 + ainsn
->insn_equiv_class_num
) = min_delay
;
8151 fprintf (output_file
, "/* Vector of min issue delay of insns. */\n");
8152 fprintf (output_file
, "static const ");
8153 output_range_type (output_file
, 0, automaton
->max_min_delay
);
8154 fprintf (output_file
, " ");
8155 output_min_issue_delay_vect_name (output_file
, automaton
);
8156 fprintf (output_file
, "[] ATTRIBUTE_UNUSED = {\n");
8157 /* Compress the vector */
8158 if (automaton
->max_min_delay
< 2)
8159 automaton
->min_issue_delay_table_compression_factor
= 8;
8160 else if (automaton
->max_min_delay
< 4)
8161 automaton
->min_issue_delay_table_compression_factor
= 4;
8162 else if (automaton
->max_min_delay
< 16)
8163 automaton
->min_issue_delay_table_compression_factor
= 2;
8165 automaton
->min_issue_delay_table_compression_factor
= 1;
8166 VLA_HWINT_CREATE (compressed_min_issue_delay_vect
, 1500,
8167 "compressed min issue delay vector");
8168 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect
,
8169 (VLA_HWINT_LENGTH (min_issue_delay_vect
)
8170 + automaton
->min_issue_delay_table_compression_factor
8172 / automaton
->min_issue_delay_table_compression_factor
);
8174 i
< (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect
);
8176 VLA_HWINT (compressed_min_issue_delay_vect
, i
) = 0;
8177 for (i
= 0; i
< (int) VLA_HWINT_LENGTH (min_issue_delay_vect
); i
++)
8178 VLA_HWINT (compressed_min_issue_delay_vect
,
8179 i
/ automaton
->min_issue_delay_table_compression_factor
)
8180 |= (VLA_HWINT (min_issue_delay_vect
, i
)
8181 << (8 - (i
% automaton
->min_issue_delay_table_compression_factor
8183 * (8 / automaton
->min_issue_delay_table_compression_factor
)));
8184 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect
),
8185 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect
));
8186 fprintf (output_file
, "};\n\n");
8187 VLA_PTR_DELETE (output_states_vect
);
8188 VLA_HWINT_DELETE (min_issue_delay_vect
);
8189 VLA_HWINT_DELETE (compressed_min_issue_delay_vect
);
8193 /* Number of states which contains transition only by advancing cpu
8195 static int locked_states_num
;
8198 /* Form and output vector representing the locked states of
8201 output_dead_lock_vect (automaton
)
8202 automaton_t automaton
;
8206 vla_hwint_t dead_lock_vect
;
8208 /* Create vect of pointers to states ordered by num of
8209 transitions from the state (state with the maximum num is the
8211 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8212 pass_states (automaton
, add_states_vect_el
);
8213 VLA_HWINT_CREATE (dead_lock_vect
, 1500, "is dead locked vector");
8214 VLA_HWINT_EXPAND (dead_lock_vect
, VLA_HWINT_LENGTH (output_states_vect
));
8215 for (state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8216 state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8219 arc
= first_out_arc (*state_ptr
);
8222 VLA_HWINT (dead_lock_vect
, (*state_ptr
)->order_state_num
)
8223 = (next_out_arc (arc
) == NULL
8224 && (arc
->insn
->insn_reserv_decl
8225 == DECL_INSN_RESERV (advance_cycle_insn_decl
)) ? 1 : 0);
8227 if (VLA_HWINT (dead_lock_vect
, (*state_ptr
)->order_state_num
))
8228 locked_states_num
++;
8231 fprintf (output_file
, "/* Vector for locked state flags. */\n");
8232 fprintf (output_file
, "static const ");
8233 output_range_type (output_file
, 0, 1);
8234 fprintf (output_file
, " ");
8235 output_dead_lock_vect_name (output_file
, automaton
);
8236 fprintf (output_file
, "[] = {\n");
8237 output_vect (VLA_HWINT_BEGIN (dead_lock_vect
),
8238 VLA_HWINT_LENGTH (dead_lock_vect
));
8239 fprintf (output_file
, "};\n\n");
8240 VLA_HWINT_DELETE (dead_lock_vect
);
8241 VLA_PTR_DELETE (output_states_vect
);
8244 /* Form and output vector representing reserved units of the states of
8247 output_reserved_units_table (automaton
)
8248 automaton_t automaton
;
8250 state_t
*curr_state_ptr
;
8251 vla_hwint_t reserved_units_table
;
8252 size_t state_byte_size
;
8255 /* Create vect of pointers to states. */
8256 VLA_PTR_CREATE (output_states_vect
, 1500, "output states vector");
8257 pass_states (automaton
, add_states_vect_el
);
8258 /* Create vector. */
8259 VLA_HWINT_CREATE (reserved_units_table
, 1500, "reserved units vector");
8260 state_byte_size
= (description
->query_units_num
+ 7) / 8;
8261 VLA_HWINT_EXPAND (reserved_units_table
,
8262 VLA_HWINT_LENGTH (output_states_vect
) * state_byte_size
);
8264 i
< (int) (VLA_HWINT_LENGTH (output_states_vect
) * state_byte_size
);
8266 VLA_HWINT (reserved_units_table
, i
) = 0;
8267 for (curr_state_ptr
= VLA_PTR_BEGIN (output_states_vect
);
8268 curr_state_ptr
<= (state_t
*) VLA_PTR_LAST (output_states_vect
);
8271 for (i
= 0; i
< description
->units_num
; i
++)
8272 if (units_array
[i
]->query_p
8273 && first_cycle_unit_presence (*curr_state_ptr
, i
))
8274 VLA_HWINT (reserved_units_table
,
8275 (*curr_state_ptr
)->order_state_num
* state_byte_size
8276 + units_array
[i
]->query_num
/ 8)
8277 += (1 << (units_array
[i
]->query_num
% 8));
8279 fprintf (output_file
, "/* Vector for reserved units of states. */\n");
8280 fprintf (output_file
, "static const ");
8281 output_range_type (output_file
, 0, 255);
8282 fprintf (output_file
, " ");
8283 output_reserved_units_table_name (output_file
, automaton
);
8284 fprintf (output_file
, "[] = {\n");
8285 output_vect (VLA_HWINT_BEGIN (reserved_units_table
),
8286 VLA_HWINT_LENGTH (reserved_units_table
));
8287 fprintf (output_file
, "};\n\n");
8288 VLA_HWINT_DELETE (reserved_units_table
);
8289 VLA_PTR_DELETE (output_states_vect
);
8292 /* The function outputs all tables representing DFA(s) used for fast
8293 pipeline hazards recognition. */
8297 automaton_t automaton
;
8300 locked_states_num
= 0;
8302 initiate_min_issue_delay_pass_states ();
8303 for (automaton
= description
->first_automaton
;
8305 automaton
= automaton
->next_automaton
)
8307 output_translate_vect (automaton
);
8308 output_trans_table (automaton
);
8309 fprintf (output_file
, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME
);
8310 output_state_alts_table (automaton
);
8311 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
8312 AUTOMATON_STATE_ALTS_MACRO_NAME
);
8313 output_min_issue_delay_table (automaton
);
8314 output_dead_lock_vect (automaton
);
8315 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
8316 output_reserved_units_table (automaton
);
8317 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
8318 CPU_UNITS_QUERY_MACRO_NAME
);
8320 fprintf (output_file
, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME
,
8321 DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
);
8324 /* The function outputs definition and value of PHR interface variable
8325 `max_insn_queue_index'. Its value is not less than maximal queue
8326 length needed for the insn scheduler. */
8328 output_max_insn_queue_index_def ()
8330 int i
, max
, latency
;
8333 max
= description
->max_insn_reserv_cycles
;
8334 for (i
= 0; i
< description
->decls_num
; i
++)
8336 decl
= description
->decls
[i
];
8337 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
8339 latency
= DECL_INSN_RESERV (decl
)->default_latency
;
8343 else if (decl
->mode
== dm_bypass
)
8345 latency
= DECL_BYPASS (decl
)->latency
;
8350 for (i
= 0; (1 << i
) <= max
; i
++)
8354 fprintf (output_file
, "\nint max_insn_queue_index = %d;\n\n", (1 << i
) - 1);
8358 /* The function outputs switch cases for insn reservations using
8359 function *output_automata_list_code. */
8361 output_insn_code_cases (output_automata_list_code
)
8362 void (*output_automata_list_code
) PARAMS ((automata_list_el_t
));
8367 for (i
= 0; i
< description
->decls_num
; i
++)
8369 decl
= description
->decls
[i
];
8370 if (decl
->mode
== dm_insn_reserv
)
8371 DECL_INSN_RESERV (decl
)->processed_p
= FALSE
;
8373 for (i
= 0; i
< description
->decls_num
; i
++)
8375 decl
= description
->decls
[i
];
8376 if (decl
->mode
== dm_insn_reserv
8377 && !DECL_INSN_RESERV (decl
)->processed_p
)
8379 for (j
= i
; j
< description
->decls_num
; j
++)
8381 decl2
= description
->decls
[j
];
8382 if (decl2
->mode
== dm_insn_reserv
8383 && (DECL_INSN_RESERV (decl2
)->important_automata_list
8384 == DECL_INSN_RESERV (decl
)->important_automata_list
))
8386 DECL_INSN_RESERV (decl2
)->processed_p
= TRUE
;
8387 fprintf (output_file
, " case %d: /* %s */\n",
8388 DECL_INSN_RESERV (decl2
)->insn_num
,
8389 DECL_INSN_RESERV (decl2
)->name
);
8392 (*output_automata_list_code
)
8393 (DECL_INSN_RESERV (decl
)->important_automata_list
);
8399 /* The function outputs a code for evaluation of a minimal delay of
8400 issue of insns which have reservations in given AUTOMATA_LIST. */
8402 output_automata_list_min_issue_delay_code (automata_list
)
8403 automata_list_el_t automata_list
;
8405 automata_list_el_t el
;
8406 automaton_t automaton
;
8408 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8410 automaton
= el
->automaton
;
8411 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8412 output_min_issue_delay_vect_name (output_file
, automaton
);
8413 fprintf (output_file
,
8414 (automaton
->min_issue_delay_table_compression_factor
!= 1
8416 output_translate_vect_name (output_file
, automaton
);
8417 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8418 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8419 output_chip_member_name (output_file
, automaton
);
8420 fprintf (output_file
, " * %d", automaton
->insn_equiv_classes_num
);
8421 if (automaton
->min_issue_delay_table_compression_factor
== 1)
8422 fprintf (output_file
, "];\n");
8425 fprintf (output_file
, ") / %d];\n",
8426 automaton
->min_issue_delay_table_compression_factor
);
8427 fprintf (output_file
, " %s = (%s >> (8 - (",
8428 TEMPORARY_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8429 output_translate_vect_name (output_file
, automaton
);
8431 (output_file
, " [%s] %% %d + 1) * %d)) & %d;\n",
8432 INTERNAL_INSN_CODE_NAME
,
8433 automaton
->min_issue_delay_table_compression_factor
,
8434 8 / automaton
->min_issue_delay_table_compression_factor
,
8435 (1 << (8 / automaton
->min_issue_delay_table_compression_factor
))
8438 if (el
== automata_list
)
8439 fprintf (output_file
, " %s = %s;\n",
8440 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8443 fprintf (output_file
, " if (%s > %s)\n",
8444 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8445 fprintf (output_file
, " %s = %s;\n",
8446 RESULT_VARIABLE_NAME
, TEMPORARY_VARIABLE_NAME
);
8449 fprintf (output_file
, " break;\n\n");
8452 /* Output function `internal_min_issue_delay'. */
8454 output_internal_min_issue_delay_func ()
8456 fprintf (output_file
, "static int %s PARAMS ((int, struct %s *));\n",
8457 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, CHIP_NAME
);
8458 fprintf (output_file
,
8459 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8460 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8461 CHIP_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
,
8462 CHIP_PARAMETER_NAME
);
8463 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8464 TEMPORARY_VARIABLE_NAME
, RESULT_VARIABLE_NAME
);
8465 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8466 output_insn_code_cases (output_automata_list_min_issue_delay_code
);
8467 fprintf (output_file
,
8468 "\n default:\n %s = -1;\n break;\n }\n",
8469 RESULT_VARIABLE_NAME
);
8470 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8471 fprintf (output_file
, "}\n\n");
8474 /* The function outputs a code changing state after issue of insns
8475 which have reservations in given AUTOMATA_LIST. */
8477 output_automata_list_transition_code (automata_list
)
8478 automata_list_el_t automata_list
;
8480 automata_list_el_t el
, next_el
;
8482 fprintf (output_file
, " {\n");
8483 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8484 for (el
= automata_list
;; el
= next_el
)
8486 next_el
= el
->next_automata_list_el
;
8487 if (next_el
== NULL
)
8489 fprintf (output_file
, " ");
8490 output_state_member_type (output_file
, el
->automaton
);
8491 fprintf (output_file
, " ");
8492 output_temp_chip_member_name (output_file
, el
->automaton
);
8493 fprintf (output_file
, ";\n");
8495 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8496 if (comb_vect_p (el
->automaton
->trans_table
))
8498 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8499 output_trans_base_vect_name (output_file
, el
->automaton
);
8500 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8501 output_chip_member_name (output_file
, el
->automaton
);
8502 fprintf (output_file
, "] + ");
8503 output_translate_vect_name (output_file
, el
->automaton
);
8504 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8505 fprintf (output_file
, " if (");
8506 output_trans_check_vect_name (output_file
, el
->automaton
);
8507 fprintf (output_file
, " [%s] != %s->",
8508 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8509 output_chip_member_name (output_file
, el
->automaton
);
8510 fprintf (output_file
, ")\n");
8511 fprintf (output_file
, " return %s (%s, %s);\n",
8512 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8513 CHIP_PARAMETER_NAME
);
8514 fprintf (output_file
, " else\n");
8515 fprintf (output_file
, " ");
8516 if (el
->next_automata_list_el
!= NULL
)
8517 output_temp_chip_member_name (output_file
, el
->automaton
);
8520 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8521 output_chip_member_name (output_file
, el
->automaton
);
8523 fprintf (output_file
, " = ");
8524 output_trans_comb_vect_name (output_file
, el
->automaton
);
8525 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8529 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8530 output_trans_full_vect_name (output_file
, el
->automaton
);
8531 fprintf (output_file
, " [");
8532 output_translate_vect_name (output_file
, el
->automaton
);
8533 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8534 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8535 output_chip_member_name (output_file
, el
->automaton
);
8536 fprintf (output_file
, " * %d];\n",
8537 el
->automaton
->insn_equiv_classes_num
);
8538 fprintf (output_file
, " if (%s >= %d)\n",
8539 TEMPORARY_VARIABLE_NAME
, el
->automaton
->achieved_states_num
);
8540 fprintf (output_file
, " return %s (%s, %s);\n",
8541 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8542 CHIP_PARAMETER_NAME
);
8543 fprintf (output_file
, " else\n ");
8544 if (el
->next_automata_list_el
!= NULL
)
8545 output_temp_chip_member_name (output_file
, el
->automaton
);
8548 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8549 output_chip_member_name (output_file
, el
->automaton
);
8551 fprintf (output_file
, " = %s;\n", TEMPORARY_VARIABLE_NAME
);
8553 if (automata_list
!= NULL
&& automata_list
->next_automata_list_el
!= NULL
)
8554 for (el
= automata_list
;; el
= next_el
)
8556 next_el
= el
->next_automata_list_el
;
8557 if (next_el
== NULL
)
8559 fprintf (output_file
, " %s->", CHIP_PARAMETER_NAME
);
8560 output_chip_member_name (output_file
, el
->automaton
);
8561 fprintf (output_file
, " = ");
8562 output_temp_chip_member_name (output_file
, el
->automaton
);
8563 fprintf (output_file
, ";\n");
8565 fprintf (output_file
, " return -1;\n");
8566 fprintf (output_file
, " }\n");
8569 /* Output function `internal_state_transition'. */
8571 output_internal_trans_func ()
8573 fprintf (output_file
, "static int %s PARAMS ((int, struct %s *));\n",
8574 INTERNAL_TRANSITION_FUNC_NAME
, CHIP_NAME
);
8575 fprintf (output_file
,
8576 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8577 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8578 CHIP_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
,
8579 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8580 fprintf (output_file
, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME
);
8581 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8582 output_insn_code_cases (output_automata_list_transition_code
);
8583 fprintf (output_file
, "\n default:\n return -1;\n }\n");
8584 fprintf (output_file
, "}\n\n");
8591 insn_code = dfa_insn_code (insn);
8592 if (insn_code > DFA__ADVANCE_CYCLE)
8596 insn_code = DFA__ADVANCE_CYCLE;
8598 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8599 code denotes CODE. */
8601 output_internal_insn_code_evaluation (insn_name
, insn_code_name
, code
)
8602 const char *insn_name
;
8603 const char *insn_code_name
;
8606 fprintf (output_file
, "\n if (%s != 0)\n {\n", insn_name
);
8607 fprintf (output_file
, " %s = %s (%s);\n", insn_code_name
,
8608 DFA_INSN_CODE_FUNC_NAME
, insn_name
);
8609 fprintf (output_file
, " if (%s > %s)\n return %d;\n",
8610 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
, code
);
8611 fprintf (output_file
, " }\n else\n %s = %s;\n\n",
8612 insn_code_name
, ADVANCE_CYCLE_VALUE_NAME
);
8616 /* This function outputs `dfa_insn_code' and its helper function
8617 `dfa_insn_code_enlarge'. */
8619 output_dfa_insn_code_func ()
8621 /* Emacs c-mode gets really confused if there's a { or } in column 0
8622 inside a string, so don't do that. */
8623 fprintf (output_file
, "\
8624 static void dfa_insn_code_enlarge PARAMS ((int));\n\
8626 dfa_insn_code_enlarge (uid)\n\
8630 %s = xrealloc (%s,\n\
8631 %s * sizeof(int));\n\
8632 for (; i < %s; i++)\n\
8633 %s[i] = -1;\n}\n\n",
8634 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8635 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8636 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
,
8637 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8638 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
,
8639 DFA_INSN_CODES_VARIABLE_NAME
);
8640 fprintf (output_file
, "\
8641 static inline int %s PARAMS ((rtx));\n\
8642 static inline int\n%s (%s)\n\
8644 int uid = INSN_UID (%s);\n\
8646 DFA_INSN_CODE_FUNC_NAME
, DFA_INSN_CODE_FUNC_NAME
,
8647 INSN_PARAMETER_NAME
, INSN_PARAMETER_NAME
,
8648 INSN_PARAMETER_NAME
,
8649 INTERNAL_INSN_CODE_NAME
);
8651 fprintf (output_file
,
8652 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8653 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
8654 fprintf (output_file
, " %s = %s[uid];\n",
8655 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
8656 fprintf (output_file
, "\
8662 INTERNAL_INSN_CODE_NAME
,
8663 INTERNAL_INSN_CODE_NAME
,
8664 INTERNAL_DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
,
8665 DFA_INSN_CODES_VARIABLE_NAME
, INTERNAL_INSN_CODE_NAME
);
8666 fprintf (output_file
, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME
);
8669 /* The function outputs PHR interface function `state_transition'. */
8671 output_trans_func ()
8673 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8674 TRANSITION_FUNC_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
,
8675 STATE_TYPE_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
);
8676 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8677 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8678 INTERNAL_INSN_CODE_NAME
, -1);
8679 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8680 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
8683 /* The function outputs a code for evaluation of alternative states
8684 number for insns which have reservations in given AUTOMATA_LIST. */
8686 output_automata_list_state_alts_code (automata_list
)
8687 automata_list_el_t automata_list
;
8689 automata_list_el_t el
;
8690 automaton_t automaton
;
8692 fprintf (output_file
, " {\n");
8693 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8694 if (comb_vect_p (el
->automaton
->state_alts_table
))
8696 fprintf (output_file
, " int %s;\n", TEMPORARY_VARIABLE_NAME
);
8699 for (el
= automata_list
; el
!= NULL
; el
= el
->next_automata_list_el
)
8701 automaton
= el
->automaton
;
8702 if (comb_vect_p (automaton
->state_alts_table
))
8704 fprintf (output_file
, "\n %s = ", TEMPORARY_VARIABLE_NAME
);
8705 output_state_alts_base_vect_name (output_file
, automaton
);
8706 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8707 output_chip_member_name (output_file
, automaton
);
8708 fprintf (output_file
, "] + ");
8709 output_translate_vect_name (output_file
, automaton
);
8710 fprintf (output_file
, " [%s];\n", INTERNAL_INSN_CODE_NAME
);
8711 fprintf (output_file
, " if (");
8712 output_state_alts_check_vect_name (output_file
, automaton
);
8713 fprintf (output_file
, " [%s] != %s->",
8714 TEMPORARY_VARIABLE_NAME
, CHIP_PARAMETER_NAME
);
8715 output_chip_member_name (output_file
, automaton
);
8716 fprintf (output_file
, ")\n");
8717 fprintf (output_file
, " return 0;\n");
8718 fprintf (output_file
, " else\n");
8719 fprintf (output_file
,
8720 (el
== automata_list
8721 ? " %s = " : " %s += "),
8722 RESULT_VARIABLE_NAME
);
8723 output_state_alts_comb_vect_name (output_file
, automaton
);
8724 fprintf (output_file
, " [%s];\n", TEMPORARY_VARIABLE_NAME
);
8728 fprintf (output_file
,
8729 (el
== automata_list
8730 ? "\n %s = " : " %s += "),
8731 RESULT_VARIABLE_NAME
);
8732 output_state_alts_full_vect_name (output_file
, automaton
);
8733 fprintf (output_file
, " [");
8734 output_translate_vect_name (output_file
, automaton
);
8735 fprintf (output_file
, " [%s] + ", INTERNAL_INSN_CODE_NAME
);
8736 fprintf (output_file
, "%s->", CHIP_PARAMETER_NAME
);
8737 output_chip_member_name (output_file
, automaton
);
8738 fprintf (output_file
, " * %d];\n",
8739 automaton
->insn_equiv_classes_num
);
8742 fprintf (output_file
, " break;\n }\n\n");
8745 /* Output function `internal_state_alts'. */
8747 output_internal_state_alts_func ()
8749 fprintf (output_file
, "static int %s PARAMS ((int, struct %s *));\n",
8750 INTERNAL_STATE_ALTS_FUNC_NAME
, CHIP_NAME
);
8751 fprintf (output_file
,
8752 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8753 INTERNAL_STATE_ALTS_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8754 CHIP_PARAMETER_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
,
8755 CHIP_PARAMETER_NAME
);
8756 fprintf (output_file
, "{\n int %s;\n", RESULT_VARIABLE_NAME
);
8757 fprintf (output_file
, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8758 output_insn_code_cases (output_automata_list_state_alts_code
);
8759 fprintf (output_file
,
8760 "\n default:\n %s = 0;\n break;\n }\n",
8761 RESULT_VARIABLE_NAME
);
8762 fprintf (output_file
, " return %s;\n", RESULT_VARIABLE_NAME
);
8763 fprintf (output_file
, "}\n\n");
8766 /* The function outputs PHR interface function `state_alts'. */
8768 output_state_alts_func ()
8770 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8771 STATE_ALTS_FUNC_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
,
8772 STATE_TYPE_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
);
8773 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8774 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8775 INTERNAL_INSN_CODE_NAME
, 0);
8776 fprintf (output_file
, " return %s (%s, %s);\n}\n\n",
8777 INTERNAL_STATE_ALTS_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, STATE_NAME
);
8780 /* Output function `min_issue_delay'. */
8782 output_min_issue_delay_func ()
8784 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8785 MIN_ISSUE_DELAY_FUNC_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
,
8786 STATE_TYPE_NAME
, STATE_NAME
, INSN_PARAMETER_NAME
);
8787 fprintf (output_file
, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME
);
8788 fprintf (output_file
, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME
);
8789 fprintf (output_file
, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME
,
8790 DFA_INSN_CODE_FUNC_NAME
, INSN_PARAMETER_NAME
);
8791 fprintf (output_file
, " if (%s > %s)\n return 0;\n",
8792 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8793 fprintf (output_file
, " }\n else\n %s = %s;\n",
8794 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8795 fprintf (output_file
, "\n return %s (%s, %s);\n",
8796 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8798 fprintf (output_file
, "}\n\n");
8801 /* Output function `internal_dead_lock'. */
8803 output_internal_dead_lock_func ()
8805 automaton_t automaton
;
8807 fprintf (output_file
, "static int %s PARAMS ((struct %s *));\n",
8808 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_NAME
);
8809 fprintf (output_file
, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8810 INTERNAL_DEAD_LOCK_FUNC_NAME
, CHIP_PARAMETER_NAME
, CHIP_NAME
,
8811 CHIP_PARAMETER_NAME
);
8812 fprintf (output_file
, "{\n");
8813 for (automaton
= description
->first_automaton
;
8815 automaton
= automaton
->next_automaton
)
8817 fprintf (output_file
, " if (");
8818 output_dead_lock_vect_name (output_file
, automaton
);
8819 fprintf (output_file
, " [%s->", CHIP_PARAMETER_NAME
);
8820 output_chip_member_name (output_file
, automaton
);
8821 fprintf (output_file
, "])\n return 1/* TRUE */;\n");
8823 fprintf (output_file
, " return 0/* FALSE */;\n}\n\n");
8826 /* The function outputs PHR interface function `state_dead_lock_p'. */
8828 output_dead_lock_func ()
8830 fprintf (output_file
, "int\n%s (%s)\n\t%s %s;\n",
8831 DEAD_LOCK_FUNC_NAME
, STATE_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8832 fprintf (output_file
, "{\n return %s (%s);\n}\n\n",
8833 INTERNAL_DEAD_LOCK_FUNC_NAME
, STATE_NAME
);
8836 /* Output function `internal_reset'. */
8838 output_internal_reset_func ()
8840 fprintf (output_file
, "static void %s PARAMS ((struct %s *));\n",
8841 INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8842 fprintf (output_file
, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8843 INTERNAL_RESET_FUNC_NAME
, CHIP_PARAMETER_NAME
,
8844 CHIP_NAME
, CHIP_PARAMETER_NAME
);
8845 fprintf (output_file
, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8846 CHIP_PARAMETER_NAME
, CHIP_NAME
);
8849 /* The function outputs PHR interface function `state_size'. */
8853 fprintf (output_file
, "int\n%s ()\n", SIZE_FUNC_NAME
);
8854 fprintf (output_file
, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME
);
8857 /* The function outputs PHR interface function `state_reset'. */
8859 output_reset_func ()
8861 fprintf (output_file
, "void\n%s (%s)\n\t %s %s;\n",
8862 RESET_FUNC_NAME
, STATE_NAME
, STATE_TYPE_NAME
, STATE_NAME
);
8863 fprintf (output_file
, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME
,
8867 /* Output function `min_insn_conflict_delay'. */
8869 output_min_insn_conflict_delay_func ()
8871 fprintf (output_file
,
8872 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8873 MIN_INSN_CONFLICT_DELAY_FUNC_NAME
,
8874 STATE_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
,
8875 STATE_TYPE_NAME
, STATE_NAME
,
8876 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8877 fprintf (output_file
, "{\n struct %s %s;\n int %s, %s;\n",
8878 CHIP_NAME
, CHIP_NAME
, INTERNAL_INSN_CODE_NAME
,
8879 INTERNAL_INSN2_CODE_NAME
);
8880 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
8881 INTERNAL_INSN_CODE_NAME
, 0);
8882 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
8883 INTERNAL_INSN2_CODE_NAME
, 0);
8884 fprintf (output_file
, " memcpy (&%s, %s, sizeof (%s));\n",
8885 CHIP_NAME
, STATE_NAME
, CHIP_NAME
);
8886 fprintf (output_file
, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME
, CHIP_NAME
);
8887 fprintf (output_file
, " if (%s (%s, &%s) > 0)\n abort ();\n",
8888 INTERNAL_TRANSITION_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
, CHIP_NAME
);
8889 fprintf (output_file
, " return %s (%s, &%s);\n",
8890 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME
, INTERNAL_INSN2_CODE_NAME
,
8892 fprintf (output_file
, "}\n\n");
8895 /* Output function `internal_insn_latency'. */
8897 output_internal_insn_latency_func ()
8900 struct bypass_decl
*bypass
;
8902 const char *tabletype
= "unsigned char";
8904 /* Find the smallest integer type that can hold all the default
8906 for (i
= 0; i
< description
->decls_num
; i
++)
8907 if (description
->decls
[i
]->mode
== dm_insn_reserv
)
8909 decl
= description
->decls
[i
];
8910 if (DECL_INSN_RESERV (decl
)->default_latency
> UCHAR_MAX
8911 && tabletype
[0] != 'i') /* don't shrink it */
8912 tabletype
= "unsigned short";
8913 if (DECL_INSN_RESERV (decl
)->default_latency
> USHRT_MAX
)
8917 fprintf (output_file
, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8918 INTERNAL_INSN_LATENCY_FUNC_NAME
);
8919 fprintf (output_file
, "static int\n%s (%s, %s, %s, %s)",
8920 INTERNAL_INSN_LATENCY_FUNC_NAME
, INTERNAL_INSN_CODE_NAME
,
8921 INTERNAL_INSN2_CODE_NAME
, INSN_PARAMETER_NAME
,
8922 INSN2_PARAMETER_NAME
);
8923 fprintf (output_file
,
8924 "\n\tint %s ATTRIBUTE_UNUSED;\n\tint %s ATTRIBUTE_UNUSED;\n",
8925 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
8926 fprintf (output_file
,
8927 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n{\n",
8928 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
8930 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
8932 fputs (" return 0;\n}\n\n", output_file
);
8936 fprintf (output_file
, " static const %s default_latencies[] =\n {",
8939 for (i
= 0, j
= 0, col
= 7; i
< description
->decls_num
; i
++)
8940 if (description
->decls
[i
]->mode
== dm_insn_reserv
8941 && description
->decls
[i
] != advance_cycle_insn_decl
)
8943 if ((col
= (col
+1) % 8) == 0)
8944 fputs ("\n ", output_file
);
8945 decl
= description
->decls
[i
];
8946 if (j
++ != DECL_INSN_RESERV (decl
)->insn_num
)
8948 fprintf (output_file
, "% 4d,",
8949 DECL_INSN_RESERV (decl
)->default_latency
);
8951 if (j
!= DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
)
8953 fputs ("\n };\n", output_file
);
8955 fprintf (output_file
, " if (%s >= %s || %s >= %s)\n return 0;\n",
8956 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
8957 INTERNAL_INSN2_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
8959 fprintf (output_file
, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME
);
8960 for (i
= 0; i
< description
->decls_num
; i
++)
8961 if (description
->decls
[i
]->mode
== dm_insn_reserv
8962 && DECL_INSN_RESERV (description
->decls
[i
])->bypass_list
)
8964 decl
= description
->decls
[i
];
8965 fprintf (output_file
,
8966 " case %d:\n switch (%s)\n {\n",
8967 DECL_INSN_RESERV (decl
)->insn_num
,
8968 INTERNAL_INSN2_CODE_NAME
);
8969 for (bypass
= DECL_INSN_RESERV (decl
)->bypass_list
;
8971 bypass
= bypass
->next
)
8973 if (bypass
->in_insn_reserv
->insn_num
8974 == DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
)
8976 fprintf (output_file
, " case %d:\n",
8977 bypass
->in_insn_reserv
->insn_num
);
8978 if (bypass
->bypass_guard_name
== NULL
)
8979 fprintf (output_file
, " return %d;\n",
8983 fprintf (output_file
,
8984 " if (%s (%s, %s))\n",
8985 bypass
->bypass_guard_name
, INSN_PARAMETER_NAME
,
8986 INSN2_PARAMETER_NAME
);
8987 fprintf (output_file
,
8988 " return %d;\n break;\n",
8992 fputs (" }\n break;\n", output_file
);
8995 fprintf (output_file
, " }\n return default_latencies[%s];\n}\n\n",
8996 INTERNAL_INSN_CODE_NAME
);
8999 /* The function outputs PHR interface function `insn_latency'. */
9001 output_insn_latency_func ()
9003 fprintf (output_file
, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
9004 INSN_LATENCY_FUNC_NAME
, INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
,
9005 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
9006 fprintf (output_file
, "{\n int %s, %s;\n",
9007 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
);
9008 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME
,
9009 INTERNAL_INSN_CODE_NAME
, 0);
9010 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME
,
9011 INTERNAL_INSN2_CODE_NAME
, 0);
9012 fprintf (output_file
, " return %s (%s, %s, %s, %s);\n}\n\n",
9013 INTERNAL_INSN_LATENCY_FUNC_NAME
,
9014 INTERNAL_INSN_CODE_NAME
, INTERNAL_INSN2_CODE_NAME
,
9015 INSN_PARAMETER_NAME
, INSN2_PARAMETER_NAME
);
9018 /* The function outputs PHR interface function `print_reservation'. */
9020 output_print_reservation_func ()
9025 fprintf (output_file
,
9026 "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s ATTRIBUTE_UNUSED;\n{\n",
9027 PRINT_RESERVATION_FUNC_NAME
, FILE_PARAMETER_NAME
,
9028 INSN_PARAMETER_NAME
, FILE_PARAMETER_NAME
,
9029 INSN_PARAMETER_NAME
);
9031 if (DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
== 0)
9033 fprintf (output_file
, " fputs (\"%s\", %s);\n}\n\n",
9034 NOTHING_NAME
, FILE_PARAMETER_NAME
);
9039 fputs (" static const char *const reservation_names[] =\n {",
9042 for (i
= 0, j
= 0; i
< description
->decls_num
; i
++)
9044 decl
= description
->decls
[i
];
9045 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9047 if (j
++ != DECL_INSN_RESERV (decl
)->insn_num
)
9049 fprintf (output_file
, "\n \"%s\",",
9050 regexp_representation (DECL_INSN_RESERV (decl
)->regexp
));
9051 finish_regexp_representation ();
9054 if (j
!= DECL_INSN_RESERV (advance_cycle_insn_decl
)->insn_num
)
9057 fprintf (output_file
, "\n \"%s\"\n };\n int %s;\n\n",
9058 NOTHING_NAME
, INTERNAL_INSN_CODE_NAME
);
9060 fprintf (output_file
, " if (%s == 0)\n %s = %s;\n",
9061 INSN_PARAMETER_NAME
,
9062 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
9063 fprintf (output_file
, " else\n\
9069 INTERNAL_INSN_CODE_NAME
, DFA_INSN_CODE_FUNC_NAME
,
9070 INSN_PARAMETER_NAME
,
9071 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
,
9072 INTERNAL_INSN_CODE_NAME
, ADVANCE_CYCLE_VALUE_NAME
);
9074 fprintf (output_file
, " fputs (reservation_names[%s], %s);\n}\n\n",
9075 INTERNAL_INSN_CODE_NAME
, FILE_PARAMETER_NAME
);
9078 /* The following function is used to sort unit declaration by their
9081 units_cmp (unit1
, unit2
)
9082 const void *unit1
, *unit2
;
9084 const unit_decl_t u1
= *(unit_decl_t
*) unit1
;
9085 const unit_decl_t u2
= *(unit_decl_t
*) unit2
;
9087 return strcmp (u1
->name
, u2
->name
);
9090 /* The following macro value is name of struct containing unit name
9092 #define NAME_CODE_STRUCT_NAME "name_code"
9094 /* The following macro value is name of table of struct name_code. */
9095 #define NAME_CODE_TABLE_NAME "name_code_table"
9097 /* The following macro values are member names for struct name_code. */
9098 #define NAME_MEMBER_NAME "name"
9099 #define CODE_MEMBER_NAME "code"
9101 /* The following macro values are local variable names for function
9102 `get_cpu_unit_code'. */
9103 #define CMP_VARIABLE_NAME "cmp"
9104 #define LOW_VARIABLE_NAME "l"
9105 #define MIDDLE_VARIABLE_NAME "m"
9106 #define HIGH_VARIABLE_NAME "h"
9108 /* The following function outputs function to obtain internal cpu unit
9109 code by the cpu unit name. */
9111 output_get_cpu_unit_code_func ()
9116 fprintf (output_file
, "int\n%s (%s)\n\tconst char *%s;\n",
9117 GET_CPU_UNIT_CODE_FUNC_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
9118 CPU_UNIT_NAME_PARAMETER_NAME
);
9119 fprintf (output_file
, "{\n struct %s {const char *%s; int %s;};\n",
9120 NAME_CODE_STRUCT_NAME
, NAME_MEMBER_NAME
, CODE_MEMBER_NAME
);
9121 fprintf (output_file
, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME
,
9122 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
9123 fprintf (output_file
, " static struct %s %s [] =\n {\n",
9124 NAME_CODE_STRUCT_NAME
, NAME_CODE_TABLE_NAME
);
9125 units
= (unit_decl_t
*) xmalloc (sizeof (unit_decl_t
)
9126 * description
->units_num
);
9127 memcpy (units
, units_array
, sizeof (unit_decl_t
) * description
->units_num
);
9128 qsort (units
, description
->units_num
, sizeof (unit_decl_t
), units_cmp
);
9129 for (i
= 0; i
< description
->units_num
; i
++)
9130 if (units
[i
]->query_p
)
9131 fprintf (output_file
, " {\"%s\", %d},\n",
9132 units
[i
]->name
, units
[i
]->query_num
);
9133 fprintf (output_file
, " };\n\n");
9134 fprintf (output_file
, " /* The following is binary search: */\n");
9135 fprintf (output_file
, " %s = 0;\n", LOW_VARIABLE_NAME
);
9136 fprintf (output_file
, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
9137 HIGH_VARIABLE_NAME
, NAME_CODE_TABLE_NAME
, NAME_CODE_STRUCT_NAME
);
9138 fprintf (output_file
, " while (%s <= %s)\n {\n",
9139 LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
9140 fprintf (output_file
, " %s = (%s + %s) / 2;\n",
9141 MIDDLE_VARIABLE_NAME
, LOW_VARIABLE_NAME
, HIGH_VARIABLE_NAME
);
9142 fprintf (output_file
, " %s = strcmp (%s, %s [%s].%s);\n",
9143 CMP_VARIABLE_NAME
, CPU_UNIT_NAME_PARAMETER_NAME
,
9144 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, NAME_MEMBER_NAME
);
9145 fprintf (output_file
, " if (%s < 0)\n", CMP_VARIABLE_NAME
);
9146 fprintf (output_file
, " %s = %s - 1;\n",
9147 HIGH_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
9148 fprintf (output_file
, " else if (%s > 0)\n", CMP_VARIABLE_NAME
);
9149 fprintf (output_file
, " %s = %s + 1;\n",
9150 LOW_VARIABLE_NAME
, MIDDLE_VARIABLE_NAME
);
9151 fprintf (output_file
, " else\n");
9152 fprintf (output_file
, " return %s [%s].%s;\n }\n",
9153 NAME_CODE_TABLE_NAME
, MIDDLE_VARIABLE_NAME
, CODE_MEMBER_NAME
);
9154 fprintf (output_file
, " return -1;\n}\n\n");
9158 /* The following function outputs function to check reservation of cpu
9159 unit (its internal code will be passed as the function argument) in
9162 output_cpu_unit_reservation_p ()
9164 automaton_t automaton
;
9166 fprintf (output_file
, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
9167 CPU_UNIT_RESERVATION_P_FUNC_NAME
, STATE_NAME
,
9168 CPU_CODE_PARAMETER_NAME
, STATE_TYPE_NAME
, STATE_NAME
,
9169 CPU_CODE_PARAMETER_NAME
);
9170 fprintf (output_file
, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
9171 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
,
9172 description
->query_units_num
);
9173 for (automaton
= description
->first_automaton
;
9175 automaton
= automaton
->next_automaton
)
9177 fprintf (output_file
, " if ((");
9178 output_reserved_units_table_name (output_file
, automaton
);
9179 fprintf (output_file
, " [((struct %s *) %s)->", CHIP_NAME
, STATE_NAME
);
9180 output_chip_member_name (output_file
, automaton
);
9181 fprintf (output_file
, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
9182 (description
->query_units_num
+ 7) / 8,
9183 CPU_CODE_PARAMETER_NAME
, CPU_CODE_PARAMETER_NAME
);
9184 fprintf (output_file
, " return 1;\n");
9186 fprintf (output_file
, " return 0;\n}\n\n");
9189 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
9191 output_dfa_clean_insn_cache_func ()
9193 fprintf (output_file
,
9194 "void\n%s ()\n{\n int %s;\n\n",
9195 DFA_CLEAN_INSN_CACHE_FUNC_NAME
, I_VARIABLE_NAME
);
9196 fprintf (output_file
,
9197 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
9198 I_VARIABLE_NAME
, I_VARIABLE_NAME
,
9199 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
, I_VARIABLE_NAME
,
9200 DFA_INSN_CODES_VARIABLE_NAME
, I_VARIABLE_NAME
);
9203 /* The function outputs PHR interface function `dfa_start'. */
9205 output_dfa_start_func ()
9207 fprintf (output_file
,
9208 "void\n%s ()\n{\n %s = get_max_uid ();\n",
9209 DFA_START_FUNC_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9210 fprintf (output_file
, " %s = (int *) xmalloc (%s * sizeof (int));\n",
9211 DFA_INSN_CODES_VARIABLE_NAME
, DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
9212 fprintf (output_file
, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME
);
9215 /* The function outputs PHR interface function `dfa_finish'. */
9217 output_dfa_finish_func ()
9219 fprintf (output_file
, "void\n%s ()\n{\n free (%s);\n}\n\n",
9220 DFA_FINISH_FUNC_NAME
, DFA_INSN_CODES_VARIABLE_NAME
);
9225 /* The page contains code for output description file (readable
9226 representation of original description and generated DFA(s). */
9228 /* The function outputs string representation of IR reservation. */
9230 output_regexp (regexp
)
9233 fprintf (output_description_file
, "%s", regexp_representation (regexp
));
9234 finish_regexp_representation ();
9237 /* Output names of units in LIST separated by comma. */
9239 output_unit_set_el_list (list
)
9244 for (el
= list
; el
!= NULL
; el
= el
->next_unit_set_el
)
9247 fprintf (output_description_file
, ", ");
9248 fprintf (output_description_file
, "%s", el
->unit_decl
->name
);
9252 /* Output patterns in LIST separated by comma. */
9254 output_pattern_set_el_list (list
)
9255 pattern_set_el_t list
;
9257 pattern_set_el_t el
;
9260 for (el
= list
; el
!= NULL
; el
= el
->next_pattern_set_el
)
9263 fprintf (output_description_file
, ", ");
9264 for (i
= 0; i
< el
->units_num
; i
++)
9265 fprintf (output_description_file
, (i
== 0 ? "%s" : " %s"),
9266 el
->unit_decls
[i
]->name
);
9270 /* The function outputs string representation of IR define_reservation
9271 and define_insn_reservation. */
9273 output_description ()
9278 for (i
= 0; i
< description
->decls_num
; i
++)
9280 decl
= description
->decls
[i
];
9281 if (decl
->mode
== dm_unit
)
9283 if (DECL_UNIT (decl
)->excl_list
!= NULL
)
9285 fprintf (output_description_file
, "unit %s exlusion_set: ",
9286 DECL_UNIT (decl
)->name
);
9287 output_unit_set_el_list (DECL_UNIT (decl
)->excl_list
);
9288 fprintf (output_description_file
, "\n");
9290 if (DECL_UNIT (decl
)->presence_list
!= NULL
)
9292 fprintf (output_description_file
, "unit %s presence_set: ",
9293 DECL_UNIT (decl
)->name
);
9294 output_pattern_set_el_list (DECL_UNIT (decl
)->presence_list
);
9295 fprintf (output_description_file
, "\n");
9297 if (DECL_UNIT (decl
)->final_presence_list
!= NULL
)
9299 fprintf (output_description_file
, "unit %s final_presence_set: ",
9300 DECL_UNIT (decl
)->name
);
9301 output_pattern_set_el_list
9302 (DECL_UNIT (decl
)->final_presence_list
);
9303 fprintf (output_description_file
, "\n");
9305 if (DECL_UNIT (decl
)->absence_list
!= NULL
)
9307 fprintf (output_description_file
, "unit %s absence_set: ",
9308 DECL_UNIT (decl
)->name
);
9309 output_pattern_set_el_list (DECL_UNIT (decl
)->absence_list
);
9310 fprintf (output_description_file
, "\n");
9312 if (DECL_UNIT (decl
)->final_absence_list
!= NULL
)
9314 fprintf (output_description_file
, "unit %s final_absence_set: ",
9315 DECL_UNIT (decl
)->name
);
9316 output_pattern_set_el_list
9317 (DECL_UNIT (decl
)->final_absence_list
);
9318 fprintf (output_description_file
, "\n");
9322 fprintf (output_description_file
, "\n");
9323 for (i
= 0; i
< description
->decls_num
; i
++)
9325 decl
= description
->decls
[i
];
9326 if (decl
->mode
== dm_reserv
)
9328 fprintf (output_description_file
, "reservation ");
9329 fprintf (output_description_file
, DECL_RESERV (decl
)->name
);
9330 fprintf (output_description_file
, ": ");
9331 output_regexp (DECL_RESERV (decl
)->regexp
);
9332 fprintf (output_description_file
, "\n");
9334 else if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9336 fprintf (output_description_file
, "insn reservation %s ",
9337 DECL_INSN_RESERV (decl
)->name
);
9338 print_rtl (output_description_file
,
9339 DECL_INSN_RESERV (decl
)->condexp
);
9340 fprintf (output_description_file
, ": ");
9341 output_regexp (DECL_INSN_RESERV (decl
)->regexp
);
9342 fprintf (output_description_file
, "\n");
9344 else if (decl
->mode
== dm_bypass
)
9345 fprintf (output_description_file
, "bypass %d %s %s\n",
9346 DECL_BYPASS (decl
)->latency
,
9347 DECL_BYPASS (decl
)->out_insn_name
,
9348 DECL_BYPASS (decl
)->in_insn_name
);
9350 fprintf (output_description_file
, "\n\f\n");
9353 /* The function outputs name of AUTOMATON. */
9355 output_automaton_name (f
, automaton
)
9357 automaton_t automaton
;
9359 if (automaton
->corresponding_automaton_decl
== NULL
)
9360 fprintf (f
, "#%d", automaton
->automaton_order_num
);
9362 fprintf (f
, "`%s'", automaton
->corresponding_automaton_decl
->name
);
9365 /* Maximal length of line for pretty printing into description
9367 #define MAX_LINE_LENGTH 70
9369 /* The function outputs units name belonging to AUTOMATON. */
9371 output_automaton_units (automaton
)
9372 automaton_t automaton
;
9376 int curr_line_length
;
9377 int there_is_an_automaton_unit
;
9380 fprintf (output_description_file
, "\n Coresponding units:\n");
9381 fprintf (output_description_file
, " ");
9382 curr_line_length
= 4;
9383 there_is_an_automaton_unit
= 0;
9384 for (i
= 0; i
< description
->decls_num
; i
++)
9386 decl
= description
->decls
[i
];
9387 if (decl
->mode
== dm_unit
9388 && (DECL_UNIT (decl
)->corresponding_automaton_num
9389 == automaton
->automaton_order_num
))
9391 there_is_an_automaton_unit
= 1;
9392 name
= DECL_UNIT (decl
)->name
;
9393 if (curr_line_length
+ strlen (name
) + 1 > MAX_LINE_LENGTH
)
9395 curr_line_length
= strlen (name
) + 4;
9396 fprintf (output_description_file
, "\n ");
9400 curr_line_length
+= strlen (name
) + 1;
9401 fprintf (output_description_file
, " ");
9403 fprintf (output_description_file
, name
);
9406 if (!there_is_an_automaton_unit
)
9407 fprintf (output_description_file
, "<None>");
9408 fprintf (output_description_file
, "\n\n");
9411 /* The following variable is used for forming array of all possible cpu unit
9412 reservations described by the current DFA state. */
9413 static vla_ptr_t state_reservs
;
9415 /* The function forms `state_reservs' for STATE. */
9417 add_state_reservs (state
)
9420 alt_state_t curr_alt_state
;
9421 reserv_sets_t reservs
;
9423 if (state
->component_states
!= NULL
)
9424 for (curr_alt_state
= state
->component_states
;
9425 curr_alt_state
!= NULL
;
9426 curr_alt_state
= curr_alt_state
->next_sorted_alt_state
)
9427 add_state_reservs (curr_alt_state
->state
);
9430 reservs
= state
->reservs
;
9431 VLA_PTR_ADD (state_reservs
, reservs
);
9435 /* The function outputs readable representation of all out arcs of
9438 output_state_arcs (state
)
9444 int curr_line_length
;
9446 for (arc
= first_out_arc (state
); arc
!= NULL
; arc
= next_out_arc (arc
))
9449 if (!ainsn
->first_insn_with_same_reservs
)
9451 fprintf (output_description_file
, " ");
9452 curr_line_length
= 7;
9453 fprintf (output_description_file
, "%2d: ", ainsn
->insn_equiv_class_num
);
9456 insn_name
= ainsn
->insn_reserv_decl
->name
;
9457 if (curr_line_length
+ strlen (insn_name
) > MAX_LINE_LENGTH
)
9459 if (ainsn
!= arc
->insn
)
9461 fprintf (output_description_file
, ",\n ");
9462 curr_line_length
= strlen (insn_name
) + 6;
9465 curr_line_length
+= strlen (insn_name
);
9469 curr_line_length
+= strlen (insn_name
);
9470 if (ainsn
!= arc
->insn
)
9472 curr_line_length
+= 2;
9473 fprintf (output_description_file
, ", ");
9476 fprintf (output_description_file
, insn_name
);
9477 ainsn
= ainsn
->next_same_reservs_insn
;
9479 while (ainsn
!= NULL
);
9480 fprintf (output_description_file
, " %d (%d)\n",
9481 arc
->to_state
->order_state_num
, arc
->state_alts
);
9483 fprintf (output_description_file
, "\n");
9486 /* The following function is used for sorting possible cpu unit
9487 reservation of a DFA state. */
9489 state_reservs_cmp (reservs_ptr_1
, reservs_ptr_2
)
9490 const void *reservs_ptr_1
;
9491 const void *reservs_ptr_2
;
9493 return reserv_sets_cmp (*(reserv_sets_t
*) reservs_ptr_1
,
9494 *(reserv_sets_t
*) reservs_ptr_2
);
9497 /* The following function is used for sorting possible cpu unit
9498 reservation of a DFA state. */
9500 remove_state_duplicate_reservs ()
9502 reserv_sets_t
*reservs_ptr
;
9503 reserv_sets_t
*last_formed_reservs_ptr
;
9505 last_formed_reservs_ptr
= NULL
;
9506 for (reservs_ptr
= VLA_PTR_BEGIN (state_reservs
);
9507 reservs_ptr
<= (reserv_sets_t
*) VLA_PTR_LAST (state_reservs
);
9509 if (last_formed_reservs_ptr
== NULL
)
9510 last_formed_reservs_ptr
= reservs_ptr
;
9511 else if (reserv_sets_cmp (*last_formed_reservs_ptr
, *reservs_ptr
) != 0)
9513 ++last_formed_reservs_ptr
;
9514 *last_formed_reservs_ptr
= *reservs_ptr
;
9516 VLA_PTR_SHORTEN (state_reservs
, reservs_ptr
- last_formed_reservs_ptr
- 1);
9519 /* The following function output readable representation of DFA(s)
9520 state used for fast recognition of pipeline hazards. State is
9521 described by possible (current and scheduled) cpu unit
9524 output_state (state
)
9527 reserv_sets_t
*reservs_ptr
;
9529 VLA_PTR_CREATE (state_reservs
, 150, "state reservations");
9530 fprintf (output_description_file
, " State #%d", state
->order_state_num
);
9531 fprintf (output_description_file
,
9532 state
->new_cycle_p
? " (new cycle)\n" : "\n");
9533 add_state_reservs (state
);
9534 qsort (VLA_PTR_BEGIN (state_reservs
), VLA_PTR_LENGTH (state_reservs
),
9535 sizeof (reserv_sets_t
), state_reservs_cmp
);
9536 remove_state_duplicate_reservs ();
9537 for (reservs_ptr
= VLA_PTR_BEGIN (state_reservs
);
9538 reservs_ptr
<= (reserv_sets_t
*) VLA_PTR_LAST (state_reservs
);
9541 fprintf (output_description_file
, " ");
9542 output_reserv_sets (output_description_file
, *reservs_ptr
);
9543 fprintf (output_description_file
, "\n");
9545 fprintf (output_description_file
, "\n");
9546 output_state_arcs (state
);
9547 VLA_PTR_DELETE (state_reservs
);
9550 /* The following function output readable representation of
9551 DFAs used for fast recognition of pipeline hazards. */
9553 output_automaton_descriptions ()
9555 automaton_t automaton
;
9557 for (automaton
= description
->first_automaton
;
9559 automaton
= automaton
->next_automaton
)
9561 fprintf (output_description_file
, "\nAutomaton ");
9562 output_automaton_name (output_description_file
, automaton
);
9563 fprintf (output_description_file
, "\n");
9564 output_automaton_units (automaton
);
9565 pass_states (automaton
, output_state
);
9571 /* The page contains top level function for generation DFA(s) used for
9574 /* The function outputs statistics about work of different phases of
9577 output_statistics (f
)
9580 automaton_t automaton
;
9583 int transition_comb_vect_els
= 0;
9584 int transition_full_vect_els
= 0;
9585 int state_alts_comb_vect_els
= 0;
9586 int state_alts_full_vect_els
= 0;
9587 int min_issue_delay_vect_els
= 0;
9590 for (automaton
= description
->first_automaton
;
9592 automaton
= automaton
->next_automaton
)
9594 fprintf (f
, "\nAutomaton ");
9595 output_automaton_name (f
, automaton
);
9596 fprintf (f
, "\n %5d NDFA states, %5d NDFA arcs\n",
9597 automaton
->NDFA_states_num
, automaton
->NDFA_arcs_num
);
9598 fprintf (f
, " %5d DFA states, %5d DFA arcs\n",
9599 automaton
->DFA_states_num
, automaton
->DFA_arcs_num
);
9600 states_num
= automaton
->DFA_states_num
;
9601 if (!no_minimization_flag
)
9603 fprintf (f
, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9604 automaton
->minimal_DFA_states_num
,
9605 automaton
->minimal_DFA_arcs_num
);
9606 states_num
= automaton
->minimal_DFA_states_num
;
9608 fprintf (f
, " %5d all insns %5d insn equivalence classes\n",
9609 description
->insns_num
, automaton
->insn_equiv_classes_num
);
9612 (f
, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9613 (long) VLA_HWINT_LENGTH (automaton
->trans_table
->comb_vect
),
9614 (long) VLA_HWINT_LENGTH (automaton
->trans_table
->full_vect
),
9615 (comb_vect_p (automaton
->trans_table
)
9616 ? "use comb vect" : "use simple vect"));
9618 (f
, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9619 (long) VLA_HWINT_LENGTH (automaton
->state_alts_table
->comb_vect
),
9620 (long) VLA_HWINT_LENGTH (automaton
->state_alts_table
->full_vect
),
9621 (comb_vect_p (automaton
->state_alts_table
)
9622 ? "use comb vect" : "use simple vect"));
9624 (f
, "%5ld min delay table els, compression factor %d\n",
9625 (long) states_num
* automaton
->insn_equiv_classes_num
,
9626 automaton
->min_issue_delay_table_compression_factor
);
9627 transition_comb_vect_els
9628 += VLA_HWINT_LENGTH (automaton
->trans_table
->comb_vect
);
9629 transition_full_vect_els
9630 += VLA_HWINT_LENGTH (automaton
->trans_table
->full_vect
);
9631 state_alts_comb_vect_els
9632 += VLA_HWINT_LENGTH (automaton
->state_alts_table
->comb_vect
);
9633 state_alts_full_vect_els
9634 += VLA_HWINT_LENGTH (automaton
->state_alts_table
->full_vect
);
9635 min_issue_delay_vect_els
9636 += states_num
* automaton
->insn_equiv_classes_num
;
9640 fprintf (f
, "\n%5d all allocated states, %5d all allocated arcs\n",
9641 allocated_states_num
, allocated_arcs_num
);
9642 fprintf (f
, "%5d all allocated alternative states\n",
9643 allocated_alt_states_num
);
9644 fprintf (f
, "%5d all transition comb vector els, %5d all trans table els\n",
9645 transition_comb_vect_els
, transition_full_vect_els
);
9647 (f
, "%5d all state alts comb vector els, %5d all state alts table els\n",
9648 state_alts_comb_vect_els
, state_alts_full_vect_els
);
9649 fprintf (f
, "%5d all min delay table els\n", min_issue_delay_vect_els
);
9650 fprintf (f
, "%5d locked states num\n", locked_states_num
);
9654 /* The function output times of work of different phases of DFA
9657 output_time_statistics (f
)
9660 fprintf (f
, "\n transformation: ");
9661 print_active_time (f
, transform_time
);
9662 fprintf (f
, (!ndfa_flag
? ", building DFA: " : ", building NDFA: "));
9663 print_active_time (f
, NDFA_time
);
9666 fprintf (f
, ", NDFA -> DFA: ");
9667 print_active_time (f
, NDFA_to_DFA_time
);
9669 fprintf (f
, "\n DFA minimization: ");
9670 print_active_time (f
, minimize_time
);
9671 fprintf (f
, ", making insn equivalence: ");
9672 print_active_time (f
, equiv_time
);
9673 fprintf (f
, "\n all automaton generation: ");
9674 print_active_time (f
, automaton_generation_time
);
9675 fprintf (f
, ", output: ");
9676 print_active_time (f
, output_time
);
9680 /* The function generates DFA (deterministic finite state automaton)
9681 for fast recognition of pipeline hazards. No errors during
9682 checking must be fixed before this function call. */
9686 automata_num
= split_argument
;
9687 if (description
->units_num
< automata_num
)
9688 automata_num
= description
->units_num
;
9691 initiate_automata_lists ();
9692 initiate_pass_states ();
9693 initiate_excl_sets ();
9694 initiate_presence_absence_pattern_sets ();
9695 automaton_generation_time
= create_ticker ();
9697 ticker_off (&automaton_generation_time
);
9702 /* The following function creates insn attribute whose values are
9703 number alternatives in insn reservations. */
9705 make_insn_alts_attr ()
9711 condexp
= rtx_alloc (COND
);
9712 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9713 XEXP (condexp
, 1) = make_numeric_value (0);
9714 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9716 decl
= description
->decls
[i
];
9717 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9719 XVECEXP (condexp
, 0, 2 * insn_num
)
9720 = DECL_INSN_RESERV (decl
)->condexp
;
9721 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9722 = make_numeric_value
9723 (DECL_INSN_RESERV (decl
)->transformed_regexp
->mode
!= rm_oneof
9724 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl
)
9725 ->transformed_regexp
)->regexps_num
);
9729 if (description
->insns_num
!= insn_num
+ 1)
9731 make_internal_attr (attr_printf (sizeof ("*")
9732 + strlen (INSN_ALTS_FUNC_NAME
) + 1,
9733 "*%s", INSN_ALTS_FUNC_NAME
),
9739 /* The following function creates attribute which is order number of
9740 insn in pipeline hazard description translator. */
9742 make_internal_dfa_insn_code_attr ()
9748 condexp
= rtx_alloc (COND
);
9749 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9751 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl
)
9753 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9755 decl
= description
->decls
[i
];
9756 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9758 XVECEXP (condexp
, 0, 2 * insn_num
)
9759 = DECL_INSN_RESERV (decl
)->condexp
;
9760 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9761 = make_numeric_value (DECL_INSN_RESERV (decl
)->insn_num
);
9765 if (description
->insns_num
!= insn_num
+ 1)
9768 (attr_printf (sizeof ("*")
9769 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME
) + 1,
9770 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME
),
9776 /* The following function creates attribute which order number of insn
9777 in pipeline hazard description translator. */
9779 make_default_insn_latency_attr ()
9785 condexp
= rtx_alloc (COND
);
9786 XVEC (condexp
, 0) = rtvec_alloc ((description
->insns_num
- 1) * 2);
9787 XEXP (condexp
, 1) = make_numeric_value (0);
9788 for (i
= insn_num
= 0; i
< description
->decls_num
; i
++)
9790 decl
= description
->decls
[i
];
9791 if (decl
->mode
== dm_insn_reserv
&& decl
!= advance_cycle_insn_decl
)
9793 XVECEXP (condexp
, 0, 2 * insn_num
)
9794 = DECL_INSN_RESERV (decl
)->condexp
;
9795 XVECEXP (condexp
, 0, 2 * insn_num
+ 1)
9796 = make_numeric_value (DECL_INSN_RESERV (decl
)->default_latency
);
9800 if (description
->insns_num
!= insn_num
+ 1)
9802 make_internal_attr (attr_printf (sizeof ("*")
9803 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME
)
9804 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME
),
9810 /* The following function creates attribute which returns 1 if given
9811 output insn has bypassing and 0 otherwise. */
9816 int bypass_insns_num
= 0;
9820 for (i
= 0; i
< description
->decls_num
; i
++)
9822 decl
= description
->decls
[i
];
9823 if (decl
->mode
== dm_insn_reserv
9824 && DECL_INSN_RESERV (decl
)->condexp
!= NULL
9825 && DECL_INSN_RESERV (decl
)->bypass_list
!= NULL
)
9828 if (bypass_insns_num
== 0)
9829 result_rtx
= make_numeric_value (0);
9832 result_rtx
= rtx_alloc (COND
);
9833 XVEC (result_rtx
, 0) = rtvec_alloc (bypass_insns_num
* 2);
9834 XEXP (result_rtx
, 1) = make_numeric_value (0);
9836 for (i
= bypass_insn
= 0; i
< description
->decls_num
; i
++)
9838 decl
= description
->decls
[i
];
9839 if (decl
->mode
== dm_insn_reserv
9840 && DECL_INSN_RESERV (decl
)->condexp
!= NULL
9841 && DECL_INSN_RESERV (decl
)->bypass_list
!= NULL
)
9843 XVECEXP (result_rtx
, 0, 2 * bypass_insn
)
9844 = DECL_INSN_RESERV (decl
)->condexp
;
9845 XVECEXP (result_rtx
, 0, 2 * bypass_insn
+ 1)
9846 = make_numeric_value (1);
9851 make_internal_attr (attr_printf (sizeof ("*")
9852 + strlen (BYPASS_P_FUNC_NAME
) + 1,
9853 "*%s", BYPASS_P_FUNC_NAME
),
9859 /* This page mainly contains top level functions of pipeline hazards
9860 description translator. */
9862 /* The following macro value is suffix of name of description file of
9863 pipeline hazards description translator. */
9864 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9866 /* The function returns suffix of given file name. The returned
9867 string can not be changed. */
9869 file_name_suffix (file_name
)
9870 const char *file_name
;
9872 const char *last_period
;
9874 for (last_period
= NULL
; *file_name
!= '\0'; file_name
++)
9875 if (*file_name
== '.')
9876 last_period
= file_name
;
9877 return (last_period
== NULL
? file_name
: last_period
);
9880 /* The function returns base name of given file name, i.e. pointer to
9881 first char after last `/' (or `\' for WIN32) in given file name,
9882 given file name itself if the directory name is absent. The
9883 returned string can not be changed. */
9885 base_file_name (file_name
)
9886 const char *file_name
;
9888 int directory_name_length
;
9890 directory_name_length
= strlen (file_name
);
9892 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/'
9893 && file_name
[directory_name_length
] != '\\')
9895 while (directory_name_length
>= 0 && file_name
[directory_name_length
] != '/')
9897 directory_name_length
--;
9898 return file_name
+ directory_name_length
+ 1;
9901 /* The following is top level function to initialize the work of
9902 pipeline hazards description translator. */
9904 initiate_automaton_gen (argc
, argv
)
9908 const char *base_name
;
9912 split_argument
= 0; /* default value */
9913 no_minimization_flag
= 0;
9917 for (i
= 2; i
< argc
; i
++)
9918 if (strcmp (argv
[i
], NO_MINIMIZATION_OPTION
) == 0)
9919 no_minimization_flag
= 1;
9920 else if (strcmp (argv
[i
], TIME_OPTION
) == 0)
9922 else if (strcmp (argv
[i
], V_OPTION
) == 0)
9924 else if (strcmp (argv
[i
], W_OPTION
) == 0)
9926 else if (strcmp (argv
[i
], NDFA_OPTION
) == 0)
9928 else if (strcmp (argv
[i
], "-split") == 0)
9931 fatal ("-split has no argument.");
9932 fatal ("option `-split' has not been implemented yet\n");
9933 /* split_argument = atoi (argument_vect [i + 1]); */
9935 VLA_PTR_CREATE (decls
, 150, "decls");
9936 /* Initialize IR storage. */
9937 obstack_init (&irp
);
9938 initiate_automaton_decl_table ();
9939 initiate_insn_decl_table ();
9940 initiate_decl_table ();
9941 output_file
= stdout
;
9942 output_description_file
= NULL
;
9943 base_name
= base_file_name (argv
[1]);
9944 obstack_grow (&irp
, base_name
,
9945 strlen (base_name
) - strlen (file_name_suffix (base_name
)));
9946 obstack_grow (&irp
, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
,
9947 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX
) + 1);
9948 obstack_1grow (&irp
, '\0');
9949 output_description_file_name
= obstack_base (&irp
);
9950 obstack_finish (&irp
);
9953 /* The following function checks existence at least one arc marked by
9956 check_automata_insn_issues ()
9958 automaton_t automaton
;
9959 ainsn_t ainsn
, reserv_ainsn
;
9961 for (automaton
= description
->first_automaton
;
9963 automaton
= automaton
->next_automaton
)
9965 for (ainsn
= automaton
->ainsn_list
;
9967 ainsn
= ainsn
->next_ainsn
)
9968 if (ainsn
->first_insn_with_same_reservs
&& !ainsn
->arc_exists_p
)
9970 for (reserv_ainsn
= ainsn
;
9971 reserv_ainsn
!= NULL
;
9972 reserv_ainsn
= reserv_ainsn
->next_same_reservs_insn
)
9973 if (automaton
->corresponding_automaton_decl
!= NULL
)
9976 error ("Automaton `%s': Insn `%s' will never be issued",
9977 automaton
->corresponding_automaton_decl
->name
,
9978 reserv_ainsn
->insn_reserv_decl
->name
);
9981 ("Automaton `%s': Insn `%s' will never be issued",
9982 automaton
->corresponding_automaton_decl
->name
,
9983 reserv_ainsn
->insn_reserv_decl
->name
);
9988 error ("Insn `%s' will never be issued",
9989 reserv_ainsn
->insn_reserv_decl
->name
);
9991 warning ("Insn `%s' will never be issued",
9992 reserv_ainsn
->insn_reserv_decl
->name
);
9998 /* The following vla is used for storing pointers to all achieved
10000 static vla_ptr_t automaton_states
;
10002 /* This function is called by function pass_states to add an achieved
10005 add_automaton_state (state
)
10008 VLA_PTR_ADD (automaton_states
, state
);
10011 /* The following function forms list of important automata (whose
10012 states may be changed after the insn issue) for each insn. */
10014 form_important_insn_automata_lists ()
10016 automaton_t automaton
;
10017 state_t
*state_ptr
;
10023 VLA_PTR_CREATE (automaton_states
, 1500,
10024 "automaton states for forming important insn automata sets");
10025 /* Mark important ainsns. */
10026 for (automaton
= description
->first_automaton
;
10028 automaton
= automaton
->next_automaton
)
10030 VLA_PTR_NULLIFY (automaton_states
);
10031 pass_states (automaton
, add_automaton_state
);
10032 for (state_ptr
= VLA_PTR_BEGIN (automaton_states
);
10033 state_ptr
<= (state_t
*) VLA_PTR_LAST (automaton_states
);
10036 for (arc
= first_out_arc (*state_ptr
);
10038 arc
= next_out_arc (arc
))
10039 if (arc
->to_state
!= *state_ptr
)
10041 if (!arc
->insn
->first_insn_with_same_reservs
)
10043 for (ainsn
= arc
->insn
;
10045 ainsn
= ainsn
->next_same_reservs_insn
)
10046 ainsn
->important_p
= TRUE
;
10050 VLA_PTR_DELETE (automaton_states
);
10051 /* Create automata sets for the insns. */
10052 for (i
= 0; i
< description
->decls_num
; i
++)
10054 decl
= description
->decls
[i
];
10055 if (decl
->mode
== dm_insn_reserv
)
10057 automata_list_start ();
10058 for (automaton
= description
->first_automaton
;
10060 automaton
= automaton
->next_automaton
)
10061 for (ainsn
= automaton
->ainsn_list
;
10063 ainsn
= ainsn
->next_ainsn
)
10064 if (ainsn
->important_p
10065 && ainsn
->insn_reserv_decl
== DECL_INSN_RESERV (decl
))
10067 automata_list_add (automaton
);
10070 DECL_INSN_RESERV (decl
)->important_automata_list
10071 = automata_list_finish ();
10077 /* The following is top level function to generate automat(a,on) for
10078 fast recognition of pipeline hazards. */
10084 description
= create_node (sizeof (struct description
)
10085 /* One entry for cycle advancing insn. */
10086 + sizeof (decl_t
) * VLA_PTR_LENGTH (decls
));
10087 description
->decls_num
= VLA_PTR_LENGTH (decls
);
10088 description
->query_units_num
= 0;
10089 for (i
= 0; i
< description
->decls_num
; i
++)
10091 description
->decls
[i
] = VLA_PTR (decls
, i
);
10092 if (description
->decls
[i
]->mode
== dm_unit
10093 && DECL_UNIT (description
->decls
[i
])->query_p
)
10094 DECL_UNIT (description
->decls
[i
])->query_num
10095 = description
->query_units_num
++;
10097 all_time
= create_ticker ();
10098 check_time
= create_ticker ();
10099 fprintf (stderr
, "Check description...");
10101 check_all_description ();
10102 fprintf (stderr
, "done\n");
10103 ticker_off (&check_time
);
10104 generation_time
= create_ticker ();
10107 transform_insn_regexps ();
10108 check_unit_distributions_to_automata ();
10113 check_automata_insn_issues ();
10117 form_important_insn_automata_lists ();
10118 fprintf (stderr
, "Generation of attributes...");
10120 make_internal_dfa_insn_code_attr ();
10121 make_insn_alts_attr ();
10122 make_default_insn_latency_attr ();
10123 make_bypass_attr ();
10124 fprintf (stderr
, "done\n");
10126 ticker_off (&generation_time
);
10127 ticker_off (&all_time
);
10128 fprintf (stderr
, "All other genattrtab stuff...");
10132 /* The following is top level function to output PHR and to finish
10133 work with pipeline description translator. */
10137 fprintf (stderr
, "done\n");
10139 fatal ("Errors in DFA description");
10140 ticker_on (&all_time
);
10141 output_time
= create_ticker ();
10142 fprintf (stderr
, "Forming and outputing automata tables...");
10144 output_dfa_max_issue_rate ();
10146 fprintf (stderr
, "done\n");
10147 fprintf (stderr
, "Output functions to work with automata...");
10149 output_chip_definitions ();
10150 output_max_insn_queue_index_def ();
10151 output_internal_min_issue_delay_func ();
10152 output_internal_trans_func ();
10153 /* Cache of insn dfa codes: */
10154 fprintf (output_file
, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME
);
10155 fprintf (output_file
, "\nstatic int %s;\n\n",
10156 DFA_INSN_CODES_LENGTH_VARIABLE_NAME
);
10157 output_dfa_insn_code_func ();
10158 output_trans_func ();
10159 fprintf (output_file
, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME
);
10160 output_internal_state_alts_func ();
10161 output_state_alts_func ();
10162 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
10163 AUTOMATON_STATE_ALTS_MACRO_NAME
);
10164 output_min_issue_delay_func ();
10165 output_internal_dead_lock_func ();
10166 output_dead_lock_func ();
10167 output_size_func ();
10168 output_internal_reset_func ();
10169 output_reset_func ();
10170 output_min_insn_conflict_delay_func ();
10171 output_internal_insn_latency_func ();
10172 output_insn_latency_func ();
10173 output_print_reservation_func ();
10174 /* Output function get_cpu_unit_code. */
10175 fprintf (output_file
, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME
);
10176 output_get_cpu_unit_code_func ();
10177 output_cpu_unit_reservation_p ();
10178 fprintf (output_file
, "\n#endif /* #if %s */\n\n",
10179 CPU_UNITS_QUERY_MACRO_NAME
);
10180 output_dfa_clean_insn_cache_func ();
10181 output_dfa_start_func ();
10182 output_dfa_finish_func ();
10183 fprintf (stderr
, "done\n");
10186 output_description_file
= fopen (output_description_file_name
, "w");
10187 if (output_description_file
== NULL
)
10189 perror (output_description_file_name
);
10190 exit (FATAL_EXIT_CODE
);
10192 fprintf (stderr
, "Output automata description...");
10194 output_description ();
10195 output_automaton_descriptions ();
10196 fprintf (stderr
, "done\n");
10197 output_statistics (output_description_file
);
10199 output_statistics (stderr
);
10200 ticker_off (&output_time
);
10201 output_time_statistics (stderr
);
10204 finish_automata_lists ();
10207 fprintf (stderr
, "Summary:\n");
10208 fprintf (stderr
, " check time ");
10209 print_active_time (stderr
, check_time
);
10210 fprintf (stderr
, ", generation time ");
10211 print_active_time (stderr
, generation_time
);
10212 fprintf (stderr
, ", all time ");
10213 print_active_time (stderr
, all_time
);
10214 fprintf (stderr
, "\n");
10216 /* Finish all work. */
10217 if (output_description_file
!= NULL
)
10219 fflush (output_description_file
);
10220 if (ferror (stdout
) != 0)
10221 fatal ("Error in writing DFA description file %s",
10222 output_description_file_name
);
10223 fclose (output_description_file
);
10225 finish_automaton_decl_table ();
10226 finish_insn_decl_table ();
10227 finish_decl_table ();
10228 obstack_free (&irp
, NULL
);
10229 if (have_error
&& output_description_file
!= NULL
)
10230 remove (output_description_file_name
);