configure.in (GLIBCPP_ENABLE_CXX_FLAGS): Do not pass arguments, let the defaults...
[official-gcc.git] / gcc / genautomata.c
blobb64f6f5fbcf7e72db47c0d93e151829936e040b9
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
4 Written by Vladimir Makarov <vmakarov@redhat.com>
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
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
16 for more details.
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
21 02111-1307, USA. */
23 /* References:
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
36 recognizers.
38 The current implementation is different from the 2nd article in the
39 following:
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministicly and
43 non-deterministicly.
45 2. Possibility of usage of nondeterministic automata too.
47 3. Possibility to query functional unit reservations for given
48 automaton state.
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', and `absence_set').
53 5. No reverse automata are generated. Trace instruction scheduling
54 requires this. It can be easily added in the future if we
55 really need this.
57 6. Union of automaton states are not generated yet. It is planned
58 to be implemented. Such feature is needed to make more accurate
59 interlock insn scheduling to get state describing functional
60 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
66 VLIW insn packing.
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_absence_set', `gen_automaton', `gen_automata_option',
71 `gen_reserv', `gen_insn_reserv' are called from file
72 `genattrtab.c'. They transform RTL constructions describing
73 automata in .md file into internal representation convenient for
74 further processing.
76 The translator major function `expand_automata' processes the
77 description internal representation into finite state automaton.
78 It can be divided on:
80 o checking correctness of the automaton pipeline description
81 (major function is `check_all_description').
83 o generating automaton (automata) from the description (major
84 function is `make_automaton').
86 o optional transformation of nondeterministic finite state
87 automata into deterministic ones if the alternative operator
88 `|' is treated nondeterministically in the description (major
89 function is NDFA_to_DFA).
91 o optional minimization of the finite state automata by merging
92 equivalent automaton states (major function is `minimize_DFA').
94 o forming tables (some as comb vectors) and attributes
95 representing the automata (functions output_..._table).
97 Function `write_automata' outputs the created finite state
98 automaton as different tables and functions which works with the
99 automata to inquire automaton state and to change its state. These
100 function are used by gcc instruction scheduler and may be some
101 other gcc code. */
103 #include "bconfig.h"
104 #include "system.h"
105 #include "coretypes.h"
106 #include "tm.h"
107 #include "rtl.h"
108 #include "obstack.h"
109 #include "errors.h"
111 #include <math.h>
112 #include "hashtab.h"
113 #include "varray.h"
115 #ifndef CHAR_BIT
116 #define CHAR_BIT 8
117 #endif
119 #include "genattrtab.h"
121 /* Positions in machine description file. Now they are not used. But
122 they could be used in the future for better diagnostic messages. */
123 typedef int pos_t;
125 /* The following is element of vector of current (and planned in the
126 future) functional unit reservations. */
127 typedef unsigned HOST_WIDE_INT set_el_t;
129 /* Reservations of function units are represented by value of the following
130 type. */
131 typedef set_el_t *reserv_sets_t;
133 /* The following structure represents variable length array (vla) of
134 pointers and HOST WIDE INTs. We could be use only varray. But we
135 add new lay because we add elements very frequently and this could
136 stress OS allocator when varray is used only. */
137 typedef struct {
138 size_t length; /* current size of vla. */
139 varray_type varray; /* container for vla. */
140 } vla_ptr_t;
142 typedef vla_ptr_t vla_hwint_t;
144 /* The following structure describes a ticker. */
145 struct ticker
147 /* The following member value is time of the ticker creation with
148 taking into account time when the ticker is off. Active time of
149 the ticker is current time minus the value. */
150 int modified_creation_time;
151 /* The following member value is time (incremented by one) when the
152 ticker was off. Zero value means that now the ticker is on. */
153 int incremented_off_time;
156 /* The ticker is represented by the following type. */
157 typedef struct ticker ticker_t;
159 /* The following type describes elements of output vectors. */
160 typedef HOST_WIDE_INT vect_el_t;
162 /* Forward declaration of structures of internal representation of
163 pipeline description based on NDFA. */
165 struct unit_decl;
166 struct bypass_decl;
167 struct result_decl;
168 struct automaton_decl;
169 struct unit_rel_decl;
170 struct reserv_decl;
171 struct insn_reserv_decl;
172 struct decl;
173 struct unit_regexp;
174 struct result_regexp;
175 struct reserv_regexp;
176 struct nothing_regexp;
177 struct sequence_regexp;
178 struct repeat_regexp;
179 struct allof_regexp;
180 struct oneof_regexp;
181 struct regexp;
182 struct description;
183 struct unit_set_el;
184 struct state;
185 struct alt_state;
186 struct arc;
187 struct ainsn;
188 struct automaton;
189 struct state_ainsn_table;
191 /* The following typedefs are for brevity. */
192 typedef struct unit_decl *unit_decl_t;
193 typedef struct decl *decl_t;
194 typedef struct regexp *regexp_t;
195 typedef struct unit_set_el *unit_set_el_t;
196 typedef struct alt_state *alt_state_t;
197 typedef struct state *state_t;
198 typedef struct arc *arc_t;
199 typedef struct ainsn *ainsn_t;
200 typedef struct automaton *automaton_t;
201 typedef struct automata_list_el *automata_list_el_t;
202 typedef struct state_ainsn_table *state_ainsn_table_t;
205 /* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
206 gen_bypass, gen_excl_set, gen_presence_set, gen_absence_set,
207 gen_automaton, gen_automata_option, gen_reserv, gen_insn_reserv,
208 initiate_automaton_gen, expand_automata, write_automata are
209 described on the file top because the functions are called from
210 function `main'. */
212 static void *create_node PARAMS ((size_t));
213 static void *copy_node PARAMS ((const void *, size_t));
214 static char *check_name PARAMS ((char *, pos_t));
215 static char *next_sep_el PARAMS ((char **, int, int));
216 static int n_sep_els PARAMS ((char *, int, int));
217 static char **get_str_vect PARAMS ((char *, int *, int, int));
218 static regexp_t gen_regexp_el PARAMS ((char *));
219 static regexp_t gen_regexp_repeat PARAMS ((char *));
220 static regexp_t gen_regexp_allof PARAMS ((char *));
221 static regexp_t gen_regexp_oneof PARAMS ((char *));
222 static regexp_t gen_regexp_sequence PARAMS ((char *));
223 static regexp_t gen_regexp PARAMS ((char *));
225 static unsigned string_hash PARAMS ((const char *));
226 static hashval_t automaton_decl_hash PARAMS ((const void *));
227 static int automaton_decl_eq_p PARAMS ((const void *,
228 const void *));
229 static decl_t insert_automaton_decl PARAMS ((decl_t));
230 static decl_t find_automaton_decl PARAMS ((char *));
231 static void initiate_automaton_decl_table PARAMS ((void));
232 static void finish_automaton_decl_table PARAMS ((void));
234 static hashval_t insn_decl_hash PARAMS ((const void *));
235 static int insn_decl_eq_p PARAMS ((const void *,
236 const void *));
237 static decl_t insert_insn_decl PARAMS ((decl_t));
238 static decl_t find_insn_decl PARAMS ((char *));
239 static void initiate_insn_decl_table PARAMS ((void));
240 static void finish_insn_decl_table PARAMS ((void));
242 static hashval_t decl_hash PARAMS ((const void *));
243 static int decl_eq_p PARAMS ((const void *,
244 const void *));
245 static decl_t insert_decl PARAMS ((decl_t));
246 static decl_t find_decl PARAMS ((char *));
247 static void initiate_decl_table PARAMS ((void));
248 static void finish_decl_table PARAMS ((void));
250 static unit_set_el_t process_excls PARAMS ((char **, int, pos_t));
251 static void add_excls PARAMS ((unit_set_el_t, unit_set_el_t,
252 pos_t));
253 static unit_set_el_t process_presence_absence
254 PARAMS ((char **, int, pos_t, int));
255 static void add_presence_absence PARAMS ((unit_set_el_t, unit_set_el_t,
256 pos_t, int));
257 static void process_decls PARAMS ((void));
258 static struct bypass_decl *find_bypass PARAMS ((struct bypass_decl *,
259 struct insn_reserv_decl *));
260 static void check_automaton_usage PARAMS ((void));
261 static regexp_t process_regexp PARAMS ((regexp_t));
262 static void process_regexp_decls PARAMS ((void));
263 static void check_usage PARAMS ((void));
264 static int loop_in_regexp PARAMS ((regexp_t, decl_t));
265 static void check_loops_in_regexps PARAMS ((void));
266 static int process_regexp_cycles PARAMS ((regexp_t, int));
267 static void evaluate_max_reserv_cycles PARAMS ((void));
268 static void check_all_description PARAMS ((void));
270 static ticker_t create_ticker PARAMS ((void));
271 static void ticker_off PARAMS ((ticker_t *));
272 static void ticker_on PARAMS ((ticker_t *));
273 static int active_time PARAMS ((ticker_t));
274 static void print_active_time PARAMS ((FILE *, ticker_t));
276 static void add_advance_cycle_insn_decl PARAMS ((void));
278 static alt_state_t get_free_alt_state PARAMS ((void));
279 static void free_alt_state PARAMS ((alt_state_t));
280 static void free_alt_states PARAMS ((alt_state_t));
281 static int alt_state_cmp PARAMS ((const void *alt_state_ptr_1,
282 const void *alt_state_ptr_2));
283 static alt_state_t uniq_sort_alt_states PARAMS ((alt_state_t));
284 static int alt_states_eq PARAMS ((alt_state_t, alt_state_t));
285 static void initiate_alt_states PARAMS ((void));
286 static void finish_alt_states PARAMS ((void));
288 static reserv_sets_t alloc_empty_reserv_sets PARAMS ((void));
289 static unsigned reserv_sets_hash_value PARAMS ((reserv_sets_t));
290 static int reserv_sets_cmp PARAMS ((reserv_sets_t, reserv_sets_t));
291 static int reserv_sets_eq PARAMS ((reserv_sets_t, reserv_sets_t));
292 static void set_unit_reserv PARAMS ((reserv_sets_t, int, int));
293 static int test_unit_reserv PARAMS ((reserv_sets_t, int, int));
294 static int it_is_empty_reserv_sets PARAMS ((reserv_sets_t))
295 ATTRIBUTE_UNUSED;
296 static int reserv_sets_are_intersected PARAMS ((reserv_sets_t, reserv_sets_t));
297 static void reserv_sets_shift PARAMS ((reserv_sets_t, reserv_sets_t));
298 static void reserv_sets_or PARAMS ((reserv_sets_t, reserv_sets_t,
299 reserv_sets_t));
300 static void reserv_sets_and PARAMS ((reserv_sets_t, reserv_sets_t,
301 reserv_sets_t))
302 ATTRIBUTE_UNUSED;
303 static void output_cycle_reservs PARAMS ((FILE *, reserv_sets_t,
304 int, int));
305 static void output_reserv_sets PARAMS ((FILE *, reserv_sets_t));
306 static state_t get_free_state PARAMS ((int, automaton_t));
307 static void free_state PARAMS ((state_t));
308 static hashval_t state_hash PARAMS ((const void *));
309 static int state_eq_p PARAMS ((const void *, const void *));
310 static state_t insert_state PARAMS ((state_t));
311 static void set_state_reserv PARAMS ((state_t, int, int));
312 static int intersected_state_reservs_p PARAMS ((state_t, state_t));
313 static state_t states_union PARAMS ((state_t, state_t));
314 static state_t state_shift PARAMS ((state_t));
315 static void initiate_states PARAMS ((void));
316 static void finish_states PARAMS ((void));
318 static void free_arc PARAMS ((arc_t));
319 static void remove_arc PARAMS ((state_t, arc_t));
320 static arc_t find_arc PARAMS ((state_t, state_t, ainsn_t));
321 static arc_t add_arc PARAMS ((state_t, state_t, ainsn_t, int));
322 static arc_t first_out_arc PARAMS ((state_t));
323 static arc_t next_out_arc PARAMS ((arc_t));
324 static void initiate_arcs PARAMS ((void));
325 static void finish_arcs PARAMS ((void));
327 static automata_list_el_t get_free_automata_list_el PARAMS ((void));
328 static void free_automata_list_el PARAMS ((automata_list_el_t));
329 static void free_automata_list PARAMS ((automata_list_el_t));
330 static hashval_t automata_list_hash PARAMS ((const void *));
331 static int automata_list_eq_p PARAMS ((const void *, const void *));
332 static void initiate_automata_lists PARAMS ((void));
333 static void automata_list_start PARAMS ((void));
334 static void automata_list_add PARAMS ((automaton_t));
335 static automata_list_el_t automata_list_finish PARAMS ((void));
336 static void finish_automata_lists PARAMS ((void));
338 static void initiate_excl_sets PARAMS ((void));
339 static reserv_sets_t get_excl_set PARAMS ((reserv_sets_t));
341 static void initiate_presence_absence_sets PARAMS ((void));
342 static reserv_sets_t get_presence_absence_set PARAMS ((reserv_sets_t, int));
344 static regexp_t copy_insn_regexp PARAMS ((regexp_t));
345 static regexp_t transform_1 PARAMS ((regexp_t));
346 static regexp_t transform_2 PARAMS ((regexp_t));
347 static regexp_t transform_3 PARAMS ((regexp_t));
348 static regexp_t regexp_transform_func
349 PARAMS ((regexp_t, regexp_t (*) (regexp_t)));
350 static regexp_t transform_regexp PARAMS ((regexp_t));
351 static void transform_insn_regexps PARAMS ((void));
353 static void process_unit_to_form_the_same_automaton_unit_lists
354 PARAMS ((regexp_t, regexp_t, int));
355 static void form_the_same_automaton_unit_lists_from_regexp PARAMS ((regexp_t));
356 static void form_the_same_automaton_unit_lists PARAMS ((void));
357 static void check_unit_distributions_to_automata PARAMS ((void));
359 static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t,
360 int));
361 static void finish_forming_alt_state PARAMS ((alt_state_t,
362 automaton_t));
363 static void process_alts_for_forming_states PARAMS ((regexp_t,
364 automaton_t, int));
365 static void create_alt_states PARAMS ((automaton_t));
367 static void form_ainsn_with_same_reservs PARAMS ((automaton_t));
369 static void make_automaton PARAMS ((automaton_t));
370 static void form_arcs_marked_by_insn PARAMS ((state_t));
371 static void create_composed_state PARAMS ((state_t, arc_t, vla_ptr_t *));
372 static void NDFA_to_DFA PARAMS ((automaton_t));
373 static void pass_state_graph PARAMS ((state_t, void (*) (state_t)));
374 static void pass_states PARAMS ((automaton_t,
375 void (*) (state_t)));
376 static void initiate_pass_states PARAMS ((void));
377 static void add_achieved_state PARAMS ((state_t));
378 static int set_out_arc_insns_equiv_num PARAMS ((state_t, int));
379 static void clear_arc_insns_equiv_num PARAMS ((state_t));
380 static void copy_equiv_class PARAMS ((vla_ptr_t *to,
381 const vla_ptr_t *from));
382 static int state_is_differed PARAMS ((state_t, int, int));
383 static state_t init_equiv_class PARAMS ((state_t *states, int));
384 static int partition_equiv_class PARAMS ((state_t *, int,
385 vla_ptr_t *, int *));
386 static void evaluate_equiv_classes PARAMS ((automaton_t, vla_ptr_t *));
387 static void merge_states PARAMS ((automaton_t, vla_ptr_t *));
388 static void set_new_cycle_flags PARAMS ((state_t));
389 static void minimize_DFA PARAMS ((automaton_t));
390 static void incr_states_and_arcs_nums PARAMS ((state_t));
391 static void count_states_and_arcs PARAMS ((automaton_t, int *, int *));
392 static void build_automaton PARAMS ((automaton_t));
394 static void set_order_state_num PARAMS ((state_t));
395 static void enumerate_states PARAMS ((automaton_t));
397 static ainsn_t insert_ainsn_into_equiv_class PARAMS ((ainsn_t, ainsn_t));
398 static void delete_ainsn_from_equiv_class PARAMS ((ainsn_t));
399 static void process_insn_equiv_class PARAMS ((ainsn_t, arc_t *));
400 static void process_state_for_insn_equiv_partition PARAMS ((state_t));
401 static void set_insn_equiv_classes PARAMS ((automaton_t));
403 static double estimate_one_automaton_bound PARAMS ((void));
404 static int compare_max_occ_cycle_nums PARAMS ((const void *,
405 const void *));
406 static void units_to_automata_heuristic_distr PARAMS ((void));
407 static ainsn_t create_ainsns PARAMS ((void));
408 static void units_to_automata_distr PARAMS ((void));
409 static void create_automata PARAMS ((void));
411 static void form_regexp PARAMS ((regexp_t));
412 static const char *regexp_representation PARAMS ((regexp_t));
413 static void finish_regexp_representation PARAMS ((void));
415 static void output_range_type PARAMS ((FILE *, long int, long int));
416 static int longest_path_length PARAMS ((state_t));
417 static void process_state_longest_path_length PARAMS ((state_t));
418 static void output_dfa_max_issue_rate PARAMS ((void));
419 static void output_vect PARAMS ((vect_el_t *, int));
420 static void output_chip_member_name PARAMS ((FILE *, automaton_t));
421 static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t));
422 static void output_translate_vect_name PARAMS ((FILE *, automaton_t));
423 static void output_trans_full_vect_name PARAMS ((FILE *, automaton_t));
424 static void output_trans_comb_vect_name PARAMS ((FILE *, automaton_t));
425 static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t));
426 static void output_trans_base_vect_name PARAMS ((FILE *, automaton_t));
427 static void output_state_alts_full_vect_name PARAMS ((FILE *, automaton_t));
428 static void output_state_alts_comb_vect_name PARAMS ((FILE *, automaton_t));
429 static void output_state_alts_check_vect_name PARAMS ((FILE *, automaton_t));
430 static void output_state_alts_base_vect_name PARAMS ((FILE *, automaton_t));
431 static void output_min_issue_delay_vect_name PARAMS ((FILE *, automaton_t));
432 static void output_dead_lock_vect_name PARAMS ((FILE *, automaton_t));
433 static void output_reserved_units_table_name PARAMS ((FILE *, automaton_t));
434 static void output_state_member_type PARAMS ((FILE *, automaton_t));
435 static void output_chip_definitions PARAMS ((void));
436 static void output_translate_vect PARAMS ((automaton_t));
437 static int comb_vect_p PARAMS ((state_ainsn_table_t));
438 static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t));
439 static void output_state_ainsn_table
440 PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
441 void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
442 void (*) (FILE *, automaton_t)));
443 static void add_vect PARAMS ((state_ainsn_table_t,
444 int, vect_el_t *, int));
445 static int out_state_arcs_num PARAMS ((state_t));
446 static int compare_transition_els_num PARAMS ((const void *, const void *));
447 static void add_vect_el PARAMS ((vla_hwint_t *,
448 ainsn_t, int));
449 static void add_states_vect_el PARAMS ((state_t));
450 static void output_trans_table PARAMS ((automaton_t));
451 static void output_state_alts_table PARAMS ((automaton_t));
452 static int min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
453 static int min_issue_delay PARAMS ((state_t, ainsn_t));
454 static void initiate_min_issue_delay_pass_states PARAMS ((void));
455 static void output_min_issue_delay_table PARAMS ((automaton_t));
456 static void output_dead_lock_vect PARAMS ((automaton_t));
457 static void output_reserved_units_table PARAMS ((automaton_t));
458 static void output_tables PARAMS ((void));
459 static void output_max_insn_queue_index_def PARAMS ((void));
460 static void output_insn_code_cases PARAMS ((void (*) (automata_list_el_t)));
461 static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
462 static void output_internal_min_issue_delay_func PARAMS ((void));
463 static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
464 static void output_internal_trans_func PARAMS ((void));
465 static void output_internal_insn_code_evaluation PARAMS ((const char *,
466 const char *, int));
467 static void output_dfa_insn_code_func PARAMS ((void));
468 static void output_trans_func PARAMS ((void));
469 static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
470 static void output_internal_state_alts_func PARAMS ((void));
471 static void output_state_alts_func PARAMS ((void));
472 static void output_min_issue_delay_func PARAMS ((void));
473 static void output_internal_dead_lock_func PARAMS ((void));
474 static void output_dead_lock_func PARAMS ((void));
475 static void output_internal_reset_func PARAMS ((void));
476 static void output_size_func PARAMS ((void));
477 static void output_reset_func PARAMS ((void));
478 static void output_min_insn_conflict_delay_func PARAMS ((void));
479 static void output_internal_insn_latency_func PARAMS ((void));
480 static void output_insn_latency_func PARAMS ((void));
481 static void output_print_reservation_func PARAMS ((void));
482 static int units_cmp PARAMS ((const void *,
483 const void *));
484 static void output_get_cpu_unit_code_func PARAMS ((void));
485 static void output_cpu_unit_reservation_p PARAMS ((void));
486 static void output_dfa_start_func PARAMS ((void));
487 static void output_dfa_finish_func PARAMS ((void));
489 static void output_regexp PARAMS ((regexp_t ));
490 static void output_unit_set_el_list PARAMS ((unit_set_el_t));
491 static void output_description PARAMS ((void));
492 static void output_automaton_name PARAMS ((FILE *, automaton_t));
493 static void output_automaton_units PARAMS ((automaton_t));
494 static void add_state_reservs PARAMS ((state_t));
495 static void output_state_arcs PARAMS ((state_t));
496 static int state_reservs_cmp PARAMS ((const void *,
497 const void *));
498 static void remove_state_duplicate_reservs PARAMS ((void));
499 static void output_state PARAMS ((state_t));
500 static void output_automaton_descriptions PARAMS ((void));
501 static void output_statistics PARAMS ((FILE *));
502 static void output_time_statistics PARAMS ((FILE *));
503 static void generate PARAMS ((void));
505 static void make_insn_alts_attr PARAMS ((void));
506 static void make_internal_dfa_insn_code_attr PARAMS ((void));
507 static void make_default_insn_latency_attr PARAMS ((void));
508 static void make_bypass_attr PARAMS ((void));
509 static const char *file_name_suffix PARAMS ((const char *));
510 static const char *base_file_name PARAMS ((const char *));
511 static void check_automata_insn_issues PARAMS ((void));
512 static void add_automaton_state PARAMS ((state_t));
513 static void form_important_insn_automata_lists PARAMS ((void));
515 /* Undefined position. */
516 static pos_t no_pos = 0;
518 /* All IR is stored in the following obstack. */
519 static struct obstack irp;
523 /* This page contains code for work with variable length array (vla)
524 of pointers. We could be use only varray. But we add new lay
525 because we add elements very frequently and this could stress OS
526 allocator when varray is used only. */
528 /* Start work with vla. */
529 #define VLA_PTR_CREATE(vla, allocated_length, name) \
530 do \
532 vla_ptr_t *const vla_ptr = &(vla); \
534 VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\
535 vla_ptr->length = 0; \
537 while (0)
539 /* Finish work with the vla. */
540 #define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
542 /* Return start address of the vla. */
543 #define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
545 /* Address of the last element of the vla. Do not use side effects in
546 the macro argument. */
547 #define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \
548 (vla).length - 1))
549 /* Nullify the vla. */
550 #define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
552 /* Shorten the vla on given number bytes. */
553 #define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
555 /* Expand the vla on N elements. The values of new elements are
556 undefined. */
557 #define VLA_PTR_EXPAND(vla, n) \
558 do { \
559 vla_ptr_t *const expand_vla_ptr = &(vla); \
560 const size_t new_length = (n) + expand_vla_ptr->length; \
562 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
563 VARRAY_GROW (expand_vla_ptr->varray, \
564 (new_length - expand_vla_ptr->length < 128 \
565 ? expand_vla_ptr->length + 128 : new_length)); \
566 expand_vla_ptr->length = new_length; \
567 } while (0)
569 /* Add element to the end of the vla. */
570 #define VLA_PTR_ADD(vla, ptr) \
571 do { \
572 vla_ptr_t *const vla_ptr = &(vla); \
574 VLA_PTR_EXPAND (*vla_ptr, 1); \
575 VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\
576 } while (0)
578 /* Length of the vla in elements. */
579 #define VLA_PTR_LENGTH(vla) ((vla).length)
581 /* N-th element of the vla. */
582 #define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
585 /* The following macros are analogous to the previous ones but for
586 VLAs of HOST WIDE INTs. */
588 #define VLA_HWINT_CREATE(vla, allocated_length, name) \
589 do { \
590 vla_hwint_t *const vla_ptr = &(vla); \
592 VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name); \
593 vla_ptr->length = 0; \
594 } while (0)
596 #define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
598 #define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
600 #define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
602 #define VLA_HWINT_EXPAND(vla, n) \
603 do { \
604 vla_hwint_t *const expand_vla_ptr = &(vla); \
605 const size_t new_length = (n) + expand_vla_ptr->length; \
607 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
608 VARRAY_GROW (expand_vla_ptr->varray, \
609 (new_length - expand_vla_ptr->length < 128 \
610 ? expand_vla_ptr->length + 128 : new_length)); \
611 expand_vla_ptr->length = new_length; \
612 } while (0)
614 #define VLA_HWINT_ADD(vla, ptr) \
615 do { \
616 vla_hwint_t *const vla_ptr = &(vla); \
618 VLA_HWINT_EXPAND (*vla_ptr, 1); \
619 VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr); \
620 } while (0)
622 #define VLA_HWINT_LENGTH(vla) ((vla).length)
624 #define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
628 /* Options with the following names can be set up in automata_option
629 construction. Because the strings occur more one time we use the
630 macros. */
632 #define NO_MINIMIZATION_OPTION "-no-minimization"
634 #define TIME_OPTION "-time"
636 #define V_OPTION "-v"
638 #define W_OPTION "-w"
640 #define NDFA_OPTION "-ndfa"
642 /* The following flags are set up by function `initiate_automaton_gen'. */
644 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
645 static int ndfa_flag;
647 /* Do not make minimization of DFA (`-no-minimization'). */
648 static int no_minimization_flag;
650 /* Value of this variable is number of automata being generated. The
651 actual number of automata may be less this value if there is not
652 sufficient number of units. This value is defined by argument of
653 option `-split' or by constructions automaton if the value is zero
654 (it is default value of the argument). */
655 static int split_argument;
657 /* Flag of output time statistics (`-time'). */
658 static int time_flag;
660 /* Flag of creation of description file which contains description of
661 result automaton and statistics information (`-v'). */
662 static int v_flag;
664 /* Flag of generating warning instead of error for non-critical errors
665 (`-w'). */
666 static int w_flag;
669 /* Output file for pipeline hazard recognizer (PHR) being generated.
670 The value is NULL if the file is not defined. */
671 static FILE *output_file;
673 /* Description file of PHR. The value is NULL if the file is not
674 created. */
675 static FILE *output_description_file;
677 /* PHR description file name. */
678 static char *output_description_file_name;
680 /* Value of the following variable is node representing description
681 being processed. This is start point of IR. */
682 static struct description *description;
686 /* This page contains description of IR structure (nodes). */
688 enum decl_mode
690 dm_unit,
691 dm_bypass,
692 dm_automaton,
693 dm_excl,
694 dm_presence,
695 dm_absence,
696 dm_reserv,
697 dm_insn_reserv
700 /* This describes define_cpu_unit and define_query_cpu_unit (see file
701 rtl.def). */
702 struct unit_decl
704 char *name;
705 /* NULL if the automaton name is absent. */
706 char *automaton_name;
707 /* If the following value is not zero, the cpu unit reservation is
708 described in define_query_cpu_unit. */
709 char query_p;
711 /* The following fields are defined by checker. */
713 /* The following field value is nonzero if the unit is used in an
714 regexp. */
715 char unit_is_used;
717 /* The following field value is used to form cyclic lists of units
718 which should be in the same automaton because the unit is
719 reserved not on all alternatives of a regexp on a cycle. */
720 unit_decl_t the_same_automaton_unit;
721 /* The following field is TRUE if we already reported that the unit
722 is not in the same automaton. */
723 int the_same_automaton_message_reported_p;
725 /* The following field value is order number (0, 1, ...) of given
726 unit. */
727 int unit_num;
728 /* The following field value is corresponding declaration of
729 automaton which was given in description. If the field value is
730 NULL then automaton in the unit declaration was absent. */
731 struct automaton_decl *automaton_decl;
732 /* The following field value is maximal cycle number (1, ...) on
733 which given unit occurs in insns. Zero value means that given
734 unit is not used in insns. */
735 int max_occ_cycle_num;
736 /* The following list contains units which conflict with given
737 unit. */
738 unit_set_el_t excl_list;
739 /* The following list contains units which are required to
740 reservation of given unit. */
741 unit_set_el_t presence_list;
742 /* The following list contains units which should be not present in
743 reservation for given unit. */
744 unit_set_el_t absence_list;
745 /* The following is used only when `query_p' has nonzero value.
746 This is query number for the unit. */
747 int query_num;
749 /* The following fields are defined by automaton generator. */
751 /* The following field value is number of the automaton to which
752 given unit belongs. */
753 int corresponding_automaton_num;
756 /* This describes define_bypass (see file rtl.def). */
757 struct bypass_decl
759 int latency;
760 char *out_insn_name;
761 char *in_insn_name;
762 char *bypass_guard_name;
764 /* The following fields are defined by checker. */
766 /* output and input insns of given bypass. */
767 struct insn_reserv_decl *out_insn_reserv;
768 struct insn_reserv_decl *in_insn_reserv;
769 /* The next bypass for given output insn. */
770 struct bypass_decl *next;
773 /* This describes define_automaton (see file rtl.def). */
774 struct automaton_decl
776 char *name;
778 /* The following fields are defined by automaton generator. */
780 /* The following field value is nonzero if the automaton is used in
781 an regexp definition. */
782 char automaton_is_used;
784 /* The following fields are defined by checker. */
786 /* The following field value is the corresponding automaton. This
787 field is not NULL only if the automaton is present in unit
788 declarations and the automatic partition on automata is not
789 used. */
790 automaton_t corresponding_automaton;
793 /* This describes unit relations: exclusion_set, presence_set, or
794 absence_set (see file rtl.def). */
795 struct unit_rel_decl
797 int names_num;
798 int first_list_length;
799 char *names [1];
802 /* This describes define_reservation (see file rtl.def). */
803 struct reserv_decl
805 char *name;
806 regexp_t regexp;
808 /* The following fields are defined by checker. */
810 /* The following field value is nonzero if the unit is used in an
811 regexp. */
812 char reserv_is_used;
813 /* The following field is used to check up cycle in expression
814 definition. */
815 int loop_pass_num;
818 /* This describes define_insn_reservation (see file rtl.def). */
819 struct insn_reserv_decl
821 rtx condexp;
822 int default_latency;
823 regexp_t regexp;
824 char *name;
826 /* The following fields are defined by checker. */
828 /* The following field value is order number (0, 1, ...) of given
829 insn. */
830 int insn_num;
831 /* The following field value is list of bypasses in which given insn
832 is output insn. */
833 struct bypass_decl *bypass_list;
835 /* The following fields are defined by automaton generator. */
837 /* The following field is the insn regexp transformed that
838 the regexp has not optional regexp, repetition regexp, and an
839 reservation name (i.e. reservation identifiers are changed by the
840 corresponding regexp) and all alternations are the topest level
841 of the regexp. The value can be NULL only if it is special
842 insn `cycle advancing'. */
843 regexp_t transformed_regexp;
844 /* The following field value is list of arcs marked given
845 insn. The field is used in transformation NDFA -> DFA. */
846 arc_t arcs_marked_by_insn;
847 /* The two following fields are used during minimization of a finite state
848 automaton. */
849 /* The field value is number of equivalence class of state into
850 which arc marked by given insn enters from a state (fixed during
851 an automaton minimization). */
852 int equiv_class_num;
853 /* The field value is state_alts of arc leaving a state (fixed
854 during an automaton minimization) and marked by given insn
855 enters. */
856 int state_alts;
857 /* The following member value is the list to automata which can be
858 changed by the insn issue. */
859 automata_list_el_t important_automata_list;
860 /* The following member is used to process insn once for output. */
861 int processed_p;
864 /* This contains a declaration mentioned above. */
865 struct decl
867 /* What node in the union? */
868 enum decl_mode mode;
869 pos_t pos;
870 union
872 struct unit_decl unit;
873 struct bypass_decl bypass;
874 struct automaton_decl automaton;
875 struct unit_rel_decl excl;
876 struct unit_rel_decl presence;
877 struct unit_rel_decl absence;
878 struct reserv_decl reserv;
879 struct insn_reserv_decl insn_reserv;
880 } decl;
883 /* The following structures represent parsed reservation strings. */
884 enum regexp_mode
886 rm_unit,
887 rm_reserv,
888 rm_nothing,
889 rm_sequence,
890 rm_repeat,
891 rm_allof,
892 rm_oneof
895 /* Cpu unit in reservation. */
896 struct unit_regexp
898 char *name;
899 unit_decl_t unit_decl;
902 /* Define_reservation in a reservation. */
903 struct reserv_regexp
905 char *name;
906 struct reserv_decl *reserv_decl;
909 /* Absence of reservation (represented by string `nothing'). */
910 struct nothing_regexp
912 /* This used to be empty but ISO C doesn't allow that. */
913 char unused;
916 /* Representation of reservations separated by ',' (see file
917 rtl.def). */
918 struct sequence_regexp
920 int regexps_num;
921 regexp_t regexps [1];
924 /* Representation of construction `repeat' (see file rtl.def). */
925 struct repeat_regexp
927 int repeat_num;
928 regexp_t regexp;
931 /* Representation of reservations separated by '+' (see file
932 rtl.def). */
933 struct allof_regexp
935 int regexps_num;
936 regexp_t regexps [1];
939 /* Representation of reservations separated by '|' (see file
940 rtl.def). */
941 struct oneof_regexp
943 int regexps_num;
944 regexp_t regexps [1];
947 /* Representation of a reservation string. */
948 struct regexp
950 /* What node in the union? */
951 enum regexp_mode mode;
952 pos_t pos;
953 union
955 struct unit_regexp unit;
956 struct reserv_regexp reserv;
957 struct nothing_regexp nothing;
958 struct sequence_regexp sequence;
959 struct repeat_regexp repeat;
960 struct allof_regexp allof;
961 struct oneof_regexp oneof;
962 } regexp;
965 /* Represents description of pipeline hazard description based on
966 NDFA. */
967 struct description
969 int decls_num;
971 /* The following fields are defined by checker. */
973 /* The following fields values are correspondingly number of all
974 units, query units, and insns in the description. */
975 int units_num;
976 int query_units_num;
977 int insns_num;
978 /* The following field value is max length (in cycles) of
979 reservations of insns. The field value is defined only for
980 correct programs. */
981 int max_insn_reserv_cycles;
983 /* The following fields are defined by automaton generator. */
985 /* The following field value is the first automaton. */
986 automaton_t first_automaton;
988 /* The following field is created by pipeline hazard parser and
989 contains all declarations. We allocate additional entry for
990 special insn "cycle advancing" which is added by the automaton
991 generator. */
992 decl_t decls [1];
997 /* The following nodes are created in automaton checker. */
999 /* The following nodes represent exclusion, presence, absence set for
1000 cpu units. Each element are accessed through only one excl_list,
1001 presence_list, absence_list. */
1002 struct unit_set_el
1004 unit_decl_t unit_decl;
1005 unit_set_el_t next_unit_set_el;
1010 /* The following nodes are created in automaton generator. */
1012 /* The following node type describes state automaton. The state may
1013 be deterministic or non-deterministic. Non-deterministic state has
1014 several component states which represent alternative cpu units
1015 reservations. The state also is used for describing a
1016 deterministic reservation of automaton insn. */
1017 struct state
1019 /* The following member value is nonzero if there is a transition by
1020 cycle advancing. */
1021 int new_cycle_p;
1022 /* The following field is list of processor unit reservations on
1023 each cycle. */
1024 reserv_sets_t reservs;
1025 /* The following field is unique number of given state between other
1026 states. */
1027 int unique_num;
1028 /* The following field value is automaton to which given state
1029 belongs. */
1030 automaton_t automaton;
1031 /* The following field value is the first arc output from given
1032 state. */
1033 arc_t first_out_arc;
1034 /* The following field is used to form NDFA. */
1035 char it_was_placed_in_stack_for_NDFA_forming;
1036 /* The following field is used to form DFA. */
1037 char it_was_placed_in_stack_for_DFA_forming;
1038 /* The following field is used to transform NDFA to DFA. The field
1039 value is not NULL if the state is a compound state. In this case
1040 the value of field `unit_sets_list' is NULL. All states in the
1041 list are in the hash table. The list is formed through field
1042 `next_sorted_alt_state'. */
1043 alt_state_t component_states;
1044 /* The following field is used for passing graph of states. */
1045 int pass_num;
1046 /* The list of states belonging to one equivalence class is formed
1047 with the aid of the following field. */
1048 state_t next_equiv_class_state;
1049 /* The two following fields are used during minimization of a finite
1050 state automaton. */
1051 int equiv_class_num_1, equiv_class_num_2;
1052 /* The following field is used during minimization of a finite state
1053 automaton. The field value is state corresponding to equivalence
1054 class to which given state belongs. */
1055 state_t equiv_class_state;
1056 /* The following field value is the order number of given state.
1057 The states in final DFA is enumerated with the aid of the
1058 following field. */
1059 int order_state_num;
1060 /* This member is used for passing states for searching minimal
1061 delay time. */
1062 int state_pass_num;
1063 /* The following member is used to evaluate min issue delay of insn
1064 for a state. */
1065 int min_insn_issue_delay;
1066 /* The following member is used to evaluate max issue rate of the
1067 processor. The value of the member is maximal length of the path
1068 from given state no containing arcs marked by special insn `cycle
1069 advancing'. */
1070 int longest_path_length;
1073 /* The following macro is an initial value of member
1074 `longest_path_length' of a state. */
1075 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1077 /* Automaton arc. */
1078 struct arc
1080 /* The following field refers for the state into which given arc
1081 enters. */
1082 state_t to_state;
1083 /* The following field describes that the insn issue (with cycle
1084 advancing for special insn `cycle advancing' and without cycle
1085 advancing for others) makes transition from given state to
1086 another given state. */
1087 ainsn_t insn;
1088 /* The following field value is the next arc output from the same
1089 state. */
1090 arc_t next_out_arc;
1091 /* List of arcs marked given insn is formed with the following
1092 field. The field is used in transformation NDFA -> DFA. */
1093 arc_t next_arc_marked_by_insn;
1094 /* The following field is defined if NDFA_FLAG is zero. The member
1095 value is number of alternative reservations which can be used for
1096 transition for given state by given insn. */
1097 int state_alts;
1100 /* The following node type describes a deterministic alternative in
1101 non-deterministic state which characterizes cpu unit reservations
1102 of automaton insn or which is part of NDFA. */
1103 struct alt_state
1105 /* The following field is a determinist state which characterizes
1106 unit reservations of the instruction. */
1107 state_t state;
1108 /* The following field refers to the next state which characterizes
1109 unit reservations of the instruction. */
1110 alt_state_t next_alt_state;
1111 /* The following field refers to the next state in sorted list. */
1112 alt_state_t next_sorted_alt_state;
1115 /* The following node type describes insn of automaton. They are
1116 labels of FA arcs. */
1117 struct ainsn
1119 /* The following field value is the corresponding insn declaration
1120 of description. */
1121 struct insn_reserv_decl *insn_reserv_decl;
1122 /* The following field value is the next insn declaration for an
1123 automaton. */
1124 ainsn_t next_ainsn;
1125 /* The following field is states which characterize automaton unit
1126 reservations of the instruction. The value can be NULL only if it
1127 is special insn `cycle advancing'. */
1128 alt_state_t alt_states;
1129 /* The following field is sorted list of states which characterize
1130 automaton unit reservations of the instruction. The value can be
1131 NULL only if it is special insn `cycle advancing'. */
1132 alt_state_t sorted_alt_states;
1133 /* The following field refers the next automaton insn with
1134 the same reservations. */
1135 ainsn_t next_same_reservs_insn;
1136 /* The following field is flag of the first automaton insn with the
1137 same reservations in the declaration list. Only arcs marked such
1138 insn is present in the automaton. This significantly decreases
1139 memory requirements especially when several automata are
1140 formed. */
1141 char first_insn_with_same_reservs;
1142 /* The following member has nonzero value if there is arc from state of
1143 the automaton marked by the ainsn. */
1144 char arc_exists_p;
1145 /* Cyclic list of insns of an equivalence class is formed with the
1146 aid of the following field. */
1147 ainsn_t next_equiv_class_insn;
1148 /* The following field value is nonzero if the insn declaration is
1149 the first insn declaration with given equivalence number. */
1150 char first_ainsn_with_given_equialence_num;
1151 /* The following field is number of class of equivalence of insns.
1152 It is necessary because many insns may be equivalent with the
1153 point of view of pipeline hazards. */
1154 int insn_equiv_class_num;
1155 /* The following member value is TRUE if there is an arc in the
1156 automaton marked by the insn into another state. In other
1157 words, the insn can change the state of the automaton. */
1158 int important_p;
1161 /* The folowing describes an automaton for PHR. */
1162 struct automaton
1164 /* The following field value is the list of insn declarations for
1165 given automaton. */
1166 ainsn_t ainsn_list;
1167 /* The following field value is the corresponding automaton
1168 declaration. This field is not NULL only if the automatic
1169 partition on automata is not used. */
1170 struct automaton_decl *corresponding_automaton_decl;
1171 /* The following field value is the next automaton. */
1172 automaton_t next_automaton;
1173 /* The following field is start state of FA. There are not unit
1174 reservations in the state. */
1175 state_t start_state;
1176 /* The following field value is number of equivalence classes of
1177 insns (see field `insn_equiv_class_num' in
1178 `insn_reserv_decl'). */
1179 int insn_equiv_classes_num;
1180 /* The following field value is number of states of final DFA. */
1181 int achieved_states_num;
1182 /* The following field value is the order number (0, 1, ...) of
1183 given automaton. */
1184 int automaton_order_num;
1185 /* The following fields contain statistics information about
1186 building automaton. */
1187 int NDFA_states_num, DFA_states_num;
1188 /* The following field value is defined only if minimization of DFA
1189 is used. */
1190 int minimal_DFA_states_num;
1191 int NDFA_arcs_num, DFA_arcs_num;
1192 /* The following field value is defined only if minimization of DFA
1193 is used. */
1194 int minimal_DFA_arcs_num;
1195 /* The following two members refer for two table state x ainsn ->
1196 int. */
1197 state_ainsn_table_t trans_table;
1198 state_ainsn_table_t state_alts_table;
1199 /* The following member value is maximal value of min issue delay
1200 for insns of the automaton. */
1201 int max_min_delay;
1202 /* Usually min issue delay is small and we can place several (2, 4,
1203 8) elements in one vector element. So the compression factor can
1204 be 1 (no compression), 2, 4, 8. */
1205 int min_issue_delay_table_compression_factor;
1208 /* The following is the element of the list of automata. */
1209 struct automata_list_el
1211 /* The automaton itself. */
1212 automaton_t automaton;
1213 /* The next automata set element. */
1214 automata_list_el_t next_automata_list_el;
1217 /* The following structure describes a table state X ainsn -> int(>= 0). */
1218 struct state_ainsn_table
1220 /* Automaton to which given table belongs. */
1221 automaton_t automaton;
1222 /* The following tree vectors for comb vector implementation of the
1223 table. */
1224 vla_hwint_t comb_vect;
1225 vla_hwint_t check_vect;
1226 vla_hwint_t base_vect;
1227 /* This is simple implementation of the table. */
1228 vla_hwint_t full_vect;
1229 /* Minimal and maximal values of the previous vectors. */
1230 int min_comb_vect_el_value, max_comb_vect_el_value;
1231 int min_base_vect_el_value, max_base_vect_el_value;
1234 /* Macros to access members of unions. Use only them for access to
1235 union members of declarations and regexps. */
1237 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1239 #define DECL_UNIT(d) __extension__ \
1240 (({ struct decl *const _decl = (d); \
1241 if (_decl->mode != dm_unit) \
1242 decl_mode_check_failed (_decl->mode, "dm_unit", \
1243 __FILE__, __LINE__, __FUNCTION__); \
1244 &(_decl)->decl.unit; }))
1246 #define DECL_BYPASS(d) __extension__ \
1247 (({ struct decl *const _decl = (d); \
1248 if (_decl->mode != dm_bypass) \
1249 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1250 __FILE__, __LINE__, __FUNCTION__); \
1251 &(_decl)->decl.bypass; }))
1253 #define DECL_AUTOMATON(d) __extension__ \
1254 (({ struct decl *const _decl = (d); \
1255 if (_decl->mode != dm_automaton) \
1256 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1257 __FILE__, __LINE__, __FUNCTION__); \
1258 &(_decl)->decl.automaton; }))
1260 #define DECL_EXCL(d) __extension__ \
1261 (({ struct decl *const _decl = (d); \
1262 if (_decl->mode != dm_excl) \
1263 decl_mode_check_failed (_decl->mode, "dm_excl", \
1264 __FILE__, __LINE__, __FUNCTION__); \
1265 &(_decl)->decl.excl; }))
1267 #define DECL_PRESENCE(d) __extension__ \
1268 (({ struct decl *const _decl = (d); \
1269 if (_decl->mode != dm_presence) \
1270 decl_mode_check_failed (_decl->mode, "dm_presence", \
1271 __FILE__, __LINE__, __FUNCTION__); \
1272 &(_decl)->decl.presence; }))
1274 #define DECL_ABSENCE(d) __extension__ \
1275 (({ struct decl *const _decl = (d); \
1276 if (_decl->mode != dm_absence) \
1277 decl_mode_check_failed (_decl->mode, "dm_absence", \
1278 __FILE__, __LINE__, __FUNCTION__); \
1279 &(_decl)->decl.absence; }))
1281 #define DECL_RESERV(d) __extension__ \
1282 (({ struct decl *const _decl = (d); \
1283 if (_decl->mode != dm_reserv) \
1284 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1285 __FILE__, __LINE__, __FUNCTION__); \
1286 &(_decl)->decl.reserv; }))
1288 #define DECL_INSN_RESERV(d) __extension__ \
1289 (({ struct decl *const _decl = (d); \
1290 if (_decl->mode != dm_insn_reserv) \
1291 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1292 __FILE__, __LINE__, __FUNCTION__); \
1293 &(_decl)->decl.insn_reserv; }))
1295 static const char *decl_name PARAMS ((enum decl_mode));
1296 static void decl_mode_check_failed PARAMS ((enum decl_mode, const char *,
1297 const char *, int, const char *));
1299 /* Return string representation of declaration mode MODE. */
1300 static const char *
1301 decl_name (mode)
1302 enum decl_mode mode;
1304 static char str [100];
1306 if (mode == dm_unit)
1307 return "dm_unit";
1308 else if (mode == dm_bypass)
1309 return "dm_bypass";
1310 else if (mode == dm_automaton)
1311 return "dm_automaton";
1312 else if (mode == dm_excl)
1313 return "dm_excl";
1314 else if (mode == dm_presence)
1315 return "dm_presence";
1316 else if (mode == dm_absence)
1317 return "dm_absence";
1318 else if (mode == dm_reserv)
1319 return "dm_reserv";
1320 else if (mode == dm_insn_reserv)
1321 return "dm_insn_reserv";
1322 else
1323 sprintf (str, "unknown (%d)", (int) mode);
1324 return str;
1327 /* The function prints message about unexpected declaration and finish
1328 the program. */
1329 static void
1330 decl_mode_check_failed (mode, expected_mode_str, file, line, func)
1331 enum decl_mode mode;
1332 const char *expected_mode_str;
1333 const char *file;
1334 int line;
1335 const char *func;
1337 fprintf
1338 (stderr,
1339 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1340 file, line, func, expected_mode_str, decl_name (mode));
1341 exit (1);
1345 #define REGEXP_UNIT(r) __extension__ \
1346 (({ struct regexp *const _regexp = (r); \
1347 if (_regexp->mode != rm_unit) \
1348 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1349 __FILE__, __LINE__, __FUNCTION__); \
1350 &(_regexp)->regexp.unit; }))
1352 #define REGEXP_RESERV(r) __extension__ \
1353 (({ struct regexp *const _regexp = (r); \
1354 if (_regexp->mode != rm_reserv) \
1355 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1356 __FILE__, __LINE__, __FUNCTION__); \
1357 &(_regexp)->regexp.reserv; }))
1359 #define REGEXP_SEQUENCE(r) __extension__ \
1360 (({ struct regexp *const _regexp = (r); \
1361 if (_regexp->mode != rm_sequence) \
1362 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1363 __FILE__, __LINE__, __FUNCTION__); \
1364 &(_regexp)->regexp.sequence; }))
1366 #define REGEXP_REPEAT(r) __extension__ \
1367 (({ struct regexp *const _regexp = (r); \
1368 if (_regexp->mode != rm_repeat) \
1369 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1370 __FILE__, __LINE__, __FUNCTION__); \
1371 &(_regexp)->regexp.repeat; }))
1373 #define REGEXP_ALLOF(r) __extension__ \
1374 (({ struct regexp *const _regexp = (r); \
1375 if (_regexp->mode != rm_allof) \
1376 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1377 __FILE__, __LINE__, __FUNCTION__); \
1378 &(_regexp)->regexp.allof; }))
1380 #define REGEXP_ONEOF(r) __extension__ \
1381 (({ struct regexp *const _regexp = (r); \
1382 if (_regexp->mode != rm_oneof) \
1383 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1384 __FILE__, __LINE__, __FUNCTION__); \
1385 &(_regexp)->regexp.oneof; }))
1387 static const char *regexp_name PARAMS ((enum regexp_mode));
1388 static void regexp_mode_check_failed PARAMS ((enum regexp_mode, const char *,
1389 const char *, int,
1390 const char *));
1393 /* Return string representation of regexp mode MODE. */
1394 static const char *
1395 regexp_name (mode)
1396 enum regexp_mode mode;
1398 static char str [100];
1400 if (mode == rm_unit)
1401 return "rm_unit";
1402 else if (mode == rm_reserv)
1403 return "rm_reserv";
1404 else if (mode == rm_nothing)
1405 return "rm_nothing";
1406 else if (mode == rm_sequence)
1407 return "rm_sequence";
1408 else if (mode == rm_repeat)
1409 return "rm_repeat";
1410 else if (mode == rm_allof)
1411 return "rm_allof";
1412 else if (mode == rm_oneof)
1413 return "rm_oneof";
1414 else
1415 sprintf (str, "unknown (%d)", (int) mode);
1416 return str;
1419 /* The function prints message about unexpected regexp and finish the
1420 program. */
1421 static void
1422 regexp_mode_check_failed (mode, expected_mode_str, file, line, func)
1423 enum regexp_mode mode;
1424 const char *expected_mode_str;
1425 const char *file;
1426 int line;
1427 const char *func;
1429 fprintf
1430 (stderr,
1431 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1432 file, line, func, expected_mode_str, regexp_name (mode));
1433 exit (1);
1436 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1438 #define DECL_UNIT(d) (&(d)->decl.unit)
1439 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1440 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1441 #define DECL_EXCL(d) (&(d)->decl.excl)
1442 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1443 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1444 #define DECL_RESERV(d) (&(d)->decl.reserv)
1445 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1447 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1448 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1449 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1450 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1451 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1452 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1454 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1456 /* Create IR structure (node). */
1457 static void *
1458 create_node (size)
1459 size_t size;
1461 void *result;
1463 obstack_blank (&irp, size);
1464 result = obstack_base (&irp);
1465 obstack_finish (&irp);
1466 /* Default values of members are NULL and zero. */
1467 memset (result, 0, size);
1468 return result;
1471 /* Copy IR structure (node). */
1472 static void *
1473 copy_node (from, size)
1474 const void *from;
1475 size_t size;
1477 void *const result = create_node (size);
1478 memcpy (result, from, size);
1479 return result;
1482 /* The function checks that NAME does not contain quotes (`"'). */
1483 static char *
1484 check_name (name, pos)
1485 char * name;
1486 pos_t pos ATTRIBUTE_UNUSED;
1488 const char *str;
1490 for (str = name; *str != '\0'; str++)
1491 if (*str == '\"')
1492 error ("Name `%s' contains quotes", name);
1493 return name;
1496 /* Pointers to all declarations during IR generation are stored in the
1497 following. */
1498 static vla_ptr_t decls;
1500 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1501 string containing the next separated element, taking parentheses
1502 into account if PAR_FLAG has nonzero value. Advance the pointer to
1503 after the string scanned, or the end-of-string. Return NULL if at
1504 end of string. */
1505 static char *
1506 next_sep_el (pstr, sep, par_flag)
1507 char **pstr;
1508 int sep;
1509 int par_flag;
1511 char *out_str;
1512 char *p;
1513 int pars_num;
1514 int n_spaces;
1516 /* Remove leading whitespaces. */
1517 while (ISSPACE ((int) **pstr))
1518 (*pstr)++;
1520 if (**pstr == '\0')
1521 return NULL;
1523 n_spaces = 0;
1524 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1526 if (par_flag && *p == '(')
1527 pars_num++;
1528 else if (par_flag && *p == ')')
1529 pars_num--;
1530 else if (pars_num == 0 && *p == sep)
1531 break;
1532 if (pars_num == 0 && ISSPACE ((int) *p))
1533 n_spaces++;
1534 else
1536 for (; n_spaces != 0; n_spaces--)
1537 obstack_1grow (&irp, p [-n_spaces]);
1538 obstack_1grow (&irp, *p);
1541 obstack_1grow (&irp, '\0');
1542 out_str = obstack_base (&irp);
1543 obstack_finish (&irp);
1545 *pstr = p;
1546 if (**pstr == sep)
1547 (*pstr)++;
1549 return out_str;
1552 /* Given a string and a separator, return the number of separated
1553 elements in it, taking parentheses into account if PAR_FLAG has
1554 nonzero value. Return 0 for the null string, -1 if parantheses is
1555 not balanced. */
1556 static int
1557 n_sep_els (s, sep, par_flag)
1558 char *s;
1559 int sep;
1560 int par_flag;
1562 int n;
1563 int pars_num;
1565 if (*s == '\0')
1566 return 0;
1568 for (pars_num = 0, n = 1; *s; s++)
1569 if (par_flag && *s == '(')
1570 pars_num++;
1571 else if (par_flag && *s == ')')
1572 pars_num--;
1573 else if (pars_num == 0 && *s == sep)
1574 n++;
1576 return (pars_num != 0 ? -1 : n);
1579 /* Given a string and a separator, return vector of strings which are
1580 elements in the string and number of elements through els_num.
1581 Take parentheses into account if PAR_FLAG has nonzero value.
1582 Return 0 for the null string, -1 if parantheses are not balanced. */
1583 static char **
1584 get_str_vect (str, els_num, sep, par_flag)
1585 char *str;
1586 int *els_num;
1587 int sep;
1588 int par_flag;
1590 int i;
1591 char **vect;
1592 char **pstr;
1594 *els_num = n_sep_els (str, sep, par_flag);
1595 if (*els_num <= 0)
1596 return NULL;
1597 obstack_blank (&irp, sizeof (char *) * (*els_num));
1598 vect = (char **) obstack_base (&irp);
1599 obstack_finish (&irp);
1600 pstr = &str;
1601 for (i = 0; i < *els_num; i++)
1602 vect [i] = next_sep_el (pstr, sep, par_flag);
1603 if (next_sep_el (pstr, sep, par_flag) != NULL)
1604 abort ();
1605 return vect;
1608 /* Process a DEFINE_CPU_UNIT.
1610 This gives information about a unit contained in CPU. We fill a
1611 struct unit_decl with information used later by `expand_automata'. */
1612 void
1613 gen_cpu_unit (def)
1614 rtx def;
1616 decl_t decl;
1617 char **str_cpu_units;
1618 int vect_length;
1619 int i;
1621 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1622 if (str_cpu_units == NULL)
1623 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1624 for (i = 0; i < vect_length; i++)
1626 decl = create_node (sizeof (struct decl));
1627 decl->mode = dm_unit;
1628 decl->pos = 0;
1629 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1630 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1631 DECL_UNIT (decl)->query_p = 0;
1632 VLA_PTR_ADD (decls, decl);
1633 num_dfa_decls++;
1637 /* Process a DEFINE_QUERY_CPU_UNIT.
1639 This gives information about a unit contained in CPU. We fill a
1640 struct unit_decl with information used later by `expand_automata'. */
1641 void
1642 gen_query_cpu_unit (def)
1643 rtx def;
1645 decl_t decl;
1646 char **str_cpu_units;
1647 int vect_length;
1648 int i;
1650 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1651 if (str_cpu_units == NULL)
1652 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1653 for (i = 0; i < vect_length; i++)
1655 decl = create_node (sizeof (struct decl));
1656 decl->mode = dm_unit;
1657 decl->pos = 0;
1658 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1659 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1660 DECL_UNIT (decl)->query_p = 1;
1661 VLA_PTR_ADD (decls, decl);
1662 num_dfa_decls++;
1666 /* Process a DEFINE_BYPASS.
1668 This gives information about a unit contained in the CPU. We fill
1669 in a struct bypass_decl with information used later by
1670 `expand_automata'. */
1671 void
1672 gen_bypass (def)
1673 rtx def;
1675 decl_t decl;
1676 char **out_insns;
1677 int out_length;
1678 char **in_insns;
1679 int in_length;
1680 int i, j;
1682 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', 0);
1683 if (out_insns == NULL)
1684 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1685 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', 0);
1686 if (in_insns == NULL)
1687 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1688 for (i = 0; i < out_length; i++)
1689 for (j = 0; j < in_length; j++)
1691 decl = create_node (sizeof (struct decl));
1692 decl->mode = dm_bypass;
1693 decl->pos = 0;
1694 DECL_BYPASS (decl)->latency = XINT (def, 0);
1695 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1696 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1697 DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
1698 VLA_PTR_ADD (decls, decl);
1699 num_dfa_decls++;
1703 /* Process an EXCLUSION_SET.
1705 This gives information about a cpu unit conflicts. We fill a
1706 struct unit_rel_decl (excl) with information used later by
1707 `expand_automata'. */
1708 void
1709 gen_excl_set (def)
1710 rtx def;
1712 decl_t decl;
1713 char **first_str_cpu_units;
1714 char **second_str_cpu_units;
1715 int first_vect_length;
1716 int length;
1717 int i;
1719 first_str_cpu_units
1720 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1721 if (first_str_cpu_units == NULL)
1722 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1723 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1725 if (second_str_cpu_units == NULL)
1726 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1727 length += first_vect_length;
1728 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1729 decl->mode = dm_excl;
1730 decl->pos = 0;
1731 DECL_EXCL (decl)->names_num = length;
1732 DECL_EXCL (decl)->first_list_length = first_vect_length;
1733 for (i = 0; i < length; i++)
1734 if (i < first_vect_length)
1735 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1736 else
1737 DECL_EXCL (decl)->names [i]
1738 = second_str_cpu_units [i - first_vect_length];
1739 VLA_PTR_ADD (decls, decl);
1740 num_dfa_decls++;
1743 /* Process a PRESENCE_SET.
1745 This gives information about a cpu unit reservation requirements.
1746 We fill a struct unit_rel_decl (presence) with information used
1747 later by `expand_automata'. */
1748 void
1749 gen_presence_set (def)
1750 rtx def;
1752 decl_t decl;
1753 char **first_str_cpu_units;
1754 char **second_str_cpu_units;
1755 int first_vect_length;
1756 int length;
1757 int i;
1759 first_str_cpu_units
1760 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1761 if (first_str_cpu_units == NULL)
1762 fatal ("invalid first string `%s' in presence_set", XSTR (def, 0));
1763 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1765 if (second_str_cpu_units == NULL)
1766 fatal ("invalid second string `%s' in presence_set", XSTR (def, 1));
1767 length += first_vect_length;
1768 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1769 decl->mode = dm_presence;
1770 decl->pos = 0;
1771 DECL_PRESENCE (decl)->names_num = length;
1772 DECL_PRESENCE (decl)->first_list_length = first_vect_length;
1773 for (i = 0; i < length; i++)
1774 if (i < first_vect_length)
1775 DECL_PRESENCE (decl)->names [i] = first_str_cpu_units [i];
1776 else
1777 DECL_PRESENCE (decl)->names [i]
1778 = second_str_cpu_units [i - first_vect_length];
1779 VLA_PTR_ADD (decls, decl);
1780 num_dfa_decls++;
1783 /* Process an ABSENCE_SET.
1785 This gives information about a cpu unit reservation requirements.
1786 We fill a struct unit_rel_decl (absence) with information used
1787 later by `expand_automata'. */
1788 void
1789 gen_absence_set (def)
1790 rtx def;
1792 decl_t decl;
1793 char **first_str_cpu_units;
1794 char **second_str_cpu_units;
1795 int first_vect_length;
1796 int length;
1797 int i;
1799 first_str_cpu_units
1800 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1801 if (first_str_cpu_units == NULL)
1802 fatal ("invalid first string `%s' in absence_set", XSTR (def, 0));
1803 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1805 if (second_str_cpu_units == NULL)
1806 fatal ("invalid second string `%s' in absence_set", XSTR (def, 1));
1807 length += first_vect_length;
1808 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1809 decl->mode = dm_absence;
1810 decl->pos = 0;
1811 DECL_ABSENCE (decl)->names_num = length;
1812 DECL_ABSENCE (decl)->first_list_length = first_vect_length;
1813 for (i = 0; i < length; i++)
1814 if (i < first_vect_length)
1815 DECL_ABSENCE (decl)->names [i] = first_str_cpu_units [i];
1816 else
1817 DECL_ABSENCE (decl)->names [i]
1818 = second_str_cpu_units [i - first_vect_length];
1819 VLA_PTR_ADD (decls, decl);
1820 num_dfa_decls++;
1823 /* Process a DEFINE_AUTOMATON.
1825 This gives information about a finite state automaton used for
1826 recognizing pipeline hazards. We fill a struct automaton_decl
1827 with information used later by `expand_automata'. */
1828 void
1829 gen_automaton (def)
1830 rtx def;
1832 decl_t decl;
1833 char **str_automata;
1834 int vect_length;
1835 int i;
1837 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1838 if (str_automata == NULL)
1839 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1840 for (i = 0; i < vect_length; i++)
1842 decl = create_node (sizeof (struct decl));
1843 decl->mode = dm_automaton;
1844 decl->pos = 0;
1845 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1846 VLA_PTR_ADD (decls, decl);
1847 num_dfa_decls++;
1851 /* Process an AUTOMATA_OPTION.
1853 This gives information how to generate finite state automaton used
1854 for recognizing pipeline hazards. */
1855 void
1856 gen_automata_option (def)
1857 rtx def;
1859 if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1860 no_minimization_flag = 1;
1861 else if (strcmp ((char *) XSTR (def, 0), TIME_OPTION + 1) == 0)
1862 time_flag = 1;
1863 else if (strcmp ((char *) XSTR (def, 0), V_OPTION + 1) == 0)
1864 v_flag = 1;
1865 else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
1866 w_flag = 1;
1867 else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
1868 ndfa_flag = 1;
1869 else
1870 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1873 /* Name in reservation to denote absence reservation. */
1874 #define NOTHING_NAME "nothing"
1876 /* The following string contains original reservation string being
1877 parsed. */
1878 static char *reserv_str;
1880 /* Parse an element in STR. */
1881 static regexp_t
1882 gen_regexp_el (str)
1883 char *str;
1885 regexp_t regexp;
1886 int len;
1888 if (*str == '(')
1890 len = strlen (str);
1891 if (str [len - 1] != ')')
1892 fatal ("garbage after ) in reservation `%s'", reserv_str);
1893 str [len - 1] = '\0';
1894 regexp = gen_regexp_sequence (str + 1);
1896 else if (strcmp (str, NOTHING_NAME) == 0)
1898 regexp = create_node (sizeof (struct decl));
1899 regexp->mode = rm_nothing;
1901 else
1903 regexp = create_node (sizeof (struct decl));
1904 regexp->mode = rm_unit;
1905 REGEXP_UNIT (regexp)->name = str;
1907 return regexp;
1910 /* Parse construction `repeat' in STR. */
1911 static regexp_t
1912 gen_regexp_repeat (str)
1913 char *str;
1915 regexp_t regexp;
1916 regexp_t repeat;
1917 char **repeat_vect;
1918 int els_num;
1919 int i;
1921 repeat_vect = get_str_vect (str, &els_num, '*', 1);
1922 if (repeat_vect == NULL)
1923 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1924 if (els_num > 1)
1926 regexp = gen_regexp_el (repeat_vect [0]);
1927 for (i = 1; i < els_num; i++)
1929 repeat = create_node (sizeof (struct regexp));
1930 repeat->mode = rm_repeat;
1931 REGEXP_REPEAT (repeat)->regexp = regexp;
1932 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1933 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1934 fatal ("repetition `%s' <= 1 in reservation `%s'",
1935 str, reserv_str);
1936 regexp = repeat;
1938 return regexp;
1940 else
1941 return gen_regexp_el (str);
1944 /* Parse reservation STR which possibly contains separator '+'. */
1945 static regexp_t
1946 gen_regexp_allof (str)
1947 char *str;
1949 regexp_t allof;
1950 char **allof_vect;
1951 int els_num;
1952 int i;
1954 allof_vect = get_str_vect (str, &els_num, '+', 1);
1955 if (allof_vect == NULL)
1956 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1957 if (els_num > 1)
1959 allof = create_node (sizeof (struct regexp)
1960 + sizeof (regexp_t) * (els_num - 1));
1961 allof->mode = rm_allof;
1962 REGEXP_ALLOF (allof)->regexps_num = els_num;
1963 for (i = 0; i < els_num; i++)
1964 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1965 return allof;
1967 else
1968 return gen_regexp_repeat (str);
1971 /* Parse reservation STR which possibly contains separator '|'. */
1972 static regexp_t
1973 gen_regexp_oneof (str)
1974 char *str;
1976 regexp_t oneof;
1977 char **oneof_vect;
1978 int els_num;
1979 int i;
1981 oneof_vect = get_str_vect (str, &els_num, '|', 1);
1982 if (oneof_vect == NULL)
1983 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1984 if (els_num > 1)
1986 oneof = create_node (sizeof (struct regexp)
1987 + sizeof (regexp_t) * (els_num - 1));
1988 oneof->mode = rm_oneof;
1989 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1990 for (i = 0; i < els_num; i++)
1991 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1992 return oneof;
1994 else
1995 return gen_regexp_allof (str);
1998 /* Parse reservation STR which possibly contains separator ','. */
1999 static regexp_t
2000 gen_regexp_sequence (str)
2001 char *str;
2003 regexp_t sequence;
2004 char **sequence_vect;
2005 int els_num;
2006 int i;
2008 sequence_vect = get_str_vect (str, &els_num, ',', 1);
2009 if (els_num > 1)
2011 sequence = create_node (sizeof (struct regexp)
2012 + sizeof (regexp_t) * (els_num - 1));
2013 sequence->mode = rm_sequence;
2014 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2015 for (i = 0; i < els_num; i++)
2016 REGEXP_SEQUENCE (sequence)->regexps [i]
2017 = gen_regexp_oneof (sequence_vect [i]);
2018 return sequence;
2020 else
2021 return gen_regexp_oneof (str);
2024 /* Parse construction reservation STR. */
2025 static regexp_t
2026 gen_regexp (str)
2027 char *str;
2029 reserv_str = str;
2030 return gen_regexp_sequence (str);;
2033 /* Process a DEFINE_RESERVATION.
2035 This gives information about a reservation of cpu units. We fill
2036 in a struct reserv_decl with information used later by
2037 `expand_automata'. */
2038 void
2039 gen_reserv (def)
2040 rtx def;
2042 decl_t decl;
2044 decl = create_node (sizeof (struct decl));
2045 decl->mode = dm_reserv;
2046 decl->pos = 0;
2047 DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2048 DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2049 VLA_PTR_ADD (decls, decl);
2050 num_dfa_decls++;
2053 /* Process a DEFINE_INSN_RESERVATION.
2055 This gives information about the reservation of cpu units by an
2056 insn. We fill a struct insn_reserv_decl with information used
2057 later by `expand_automata'. */
2058 void
2059 gen_insn_reserv (def)
2060 rtx def;
2062 decl_t decl;
2064 decl = create_node (sizeof (struct decl));
2065 decl->mode = dm_insn_reserv;
2066 decl->pos = 0;
2067 DECL_INSN_RESERV (decl)->name
2068 = check_name ((char *) XSTR (def, 0), decl->pos);
2069 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2070 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2071 DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2072 VLA_PTR_ADD (decls, decl);
2073 num_dfa_decls++;
2078 /* The function evaluates hash value (0..UINT_MAX) of string. */
2079 static unsigned
2080 string_hash (string)
2081 const char *string;
2083 unsigned result, i;
2085 for (result = i = 0;*string++ != '\0'; i++)
2086 result += ((unsigned char) *string << (i % CHAR_BIT));
2087 return result;
2092 /* This page contains abstract data `table of automaton declarations'.
2093 Elements of the table is nodes representing automaton declarations.
2094 Key of the table elements is name of given automaton. Remember
2095 that automaton names have own space. */
2097 /* The function evaluates hash value of an automaton declaration. The
2098 function is used by abstract data `hashtab'. The function returns
2099 hash value (0..UINT_MAX) of given automaton declaration. */
2100 static hashval_t
2101 automaton_decl_hash (automaton_decl)
2102 const void *automaton_decl;
2104 const decl_t decl = (decl_t) automaton_decl;
2106 if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
2107 abort ();
2108 return string_hash (DECL_AUTOMATON (decl)->name);
2111 /* The function tests automaton declarations on equality of their
2112 keys. The function is used by abstract data `hashtab'. The
2113 function returns 1 if the declarations have the same key, 0
2114 otherwise. */
2115 static int
2116 automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
2117 const void* automaton_decl_1;
2118 const void* automaton_decl_2;
2120 const decl_t decl1 = (decl_t) automaton_decl_1;
2121 const decl_t decl2 = (decl_t) automaton_decl_2;
2123 if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
2124 || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
2125 abort ();
2126 return strcmp (DECL_AUTOMATON (decl1)->name,
2127 DECL_AUTOMATON (decl2)->name) == 0;
2130 /* The automaton declaration table itself is represented by the
2131 following variable. */
2132 static htab_t automaton_decl_table;
2134 /* The function inserts automaton declaration into the table. The
2135 function does nothing if an automaton declaration with the same key
2136 exists already in the table. The function returns automaton
2137 declaration node in the table with the same key as given automaton
2138 declaration node. */
2139 static decl_t
2140 insert_automaton_decl (automaton_decl)
2141 decl_t automaton_decl;
2143 void **entry_ptr;
2145 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
2146 if (*entry_ptr == NULL)
2147 *entry_ptr = (void *) automaton_decl;
2148 return (decl_t) *entry_ptr;
2151 /* The following variable value is node representing automaton
2152 declaration. The node used for searching automaton declaration
2153 with given name. */
2154 static struct decl work_automaton_decl;
2156 /* The function searches for automaton declaration in the table with
2157 the same key as node representing name of the automaton
2158 declaration. The function returns node found in the table, NULL if
2159 such node does not exist in the table. */
2160 static decl_t
2161 find_automaton_decl (name)
2162 char *name;
2164 void *entry;
2166 work_automaton_decl.mode = dm_automaton;
2167 DECL_AUTOMATON (&work_automaton_decl)->name = name;
2168 entry = htab_find (automaton_decl_table, &work_automaton_decl);
2169 return (decl_t) entry;
2172 /* The function creates empty automaton declaration table and node
2173 representing automaton declaration and used for searching automaton
2174 declaration with given name. The function must be called only once
2175 before any work with the automaton declaration table. */
2176 static void
2177 initiate_automaton_decl_table ()
2179 work_automaton_decl.mode = dm_automaton;
2180 automaton_decl_table = htab_create (10, automaton_decl_hash,
2181 automaton_decl_eq_p, (htab_del) 0);
2184 /* The function deletes the automaton declaration table. Only call of
2185 function `initiate_automaton_decl_table' is possible immediately
2186 after this function call. */
2187 static void
2188 finish_automaton_decl_table ()
2190 htab_delete (automaton_decl_table);
2195 /* This page contains abstract data `table of insn declarations'.
2196 Elements of the table is nodes representing insn declarations. Key
2197 of the table elements is name of given insn (in corresponding
2198 define_insn_reservation). Remember that insn names have own
2199 space. */
2201 /* The function evaluates hash value of an insn declaration. The
2202 function is used by abstract data `hashtab'. The function returns
2203 hash value (0..UINT_MAX) of given insn declaration. */
2204 static hashval_t
2205 insn_decl_hash (insn_decl)
2206 const void *insn_decl;
2208 const decl_t decl = (decl_t) insn_decl;
2210 if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
2211 abort ();
2212 return string_hash (DECL_INSN_RESERV (decl)->name);
2215 /* The function tests insn declarations on equality of their keys.
2216 The function is used by abstract data `hashtab'. The function
2217 returns 1 if declarations have the same key, 0 otherwise. */
2218 static int
2219 insn_decl_eq_p (insn_decl_1, insn_decl_2)
2220 const void *insn_decl_1;
2221 const void *insn_decl_2;
2223 const decl_t decl1 = (decl_t) insn_decl_1;
2224 const decl_t decl2 = (decl_t) insn_decl_2;
2226 if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
2227 || decl2->mode != dm_insn_reserv
2228 || DECL_INSN_RESERV (decl2)->name == NULL)
2229 abort ();
2230 return strcmp (DECL_INSN_RESERV (decl1)->name,
2231 DECL_INSN_RESERV (decl2)->name) == 0;
2234 /* The insn declaration table itself is represented by the following
2235 variable. The table does not contain insn reservation
2236 declarations. */
2237 static htab_t insn_decl_table;
2239 /* The function inserts insn declaration into the table. The function
2240 does nothing if an insn declaration with the same key exists
2241 already in the table. The function returns insn declaration node
2242 in the table with the same key as given insn declaration node. */
2243 static decl_t
2244 insert_insn_decl (insn_decl)
2245 decl_t insn_decl;
2247 void **entry_ptr;
2249 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2250 if (*entry_ptr == NULL)
2251 *entry_ptr = (void *) insn_decl;
2252 return (decl_t) *entry_ptr;
2255 /* The following variable value is node representing insn reservation
2256 declaration. The node used for searching insn reservation
2257 declaration with given name. */
2258 static struct decl work_insn_decl;
2260 /* The function searches for insn reservation declaration in the table
2261 with the same key as node representing name of the insn reservation
2262 declaration. The function returns node found in the table, NULL if
2263 such node does not exist in the table. */
2264 static decl_t
2265 find_insn_decl (name)
2266 char *name;
2268 void *entry;
2270 work_insn_decl.mode = dm_insn_reserv;
2271 DECL_INSN_RESERV (&work_insn_decl)->name = name;
2272 entry = htab_find (insn_decl_table, &work_insn_decl);
2273 return (decl_t) entry;
2276 /* The function creates empty insn declaration table and node
2277 representing insn declaration and used for searching insn
2278 declaration with given name. The function must be called only once
2279 before any work with the insn declaration table. */
2280 static void
2281 initiate_insn_decl_table ()
2283 work_insn_decl.mode = dm_insn_reserv;
2284 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2285 (htab_del) 0);
2288 /* The function deletes the insn declaration table. Only call of
2289 function `initiate_insn_decl_table' is possible immediately after
2290 this function call. */
2291 static void
2292 finish_insn_decl_table ()
2294 htab_delete (insn_decl_table);
2299 /* This page contains abstract data `table of declarations'. Elements
2300 of the table is nodes representing declarations (of units and
2301 reservations). Key of the table elements is names of given
2302 declarations. */
2304 /* The function evaluates hash value of a declaration. The function
2305 is used by abstract data `hashtab'. The function returns hash
2306 value (0..UINT_MAX) of given declaration. */
2307 static hashval_t
2308 decl_hash (decl)
2309 const void *decl;
2311 const decl_t d = (const decl_t) decl;
2313 if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
2314 && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
2315 abort ();
2316 return string_hash (d->mode == dm_unit
2317 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
2320 /* The function tests declarations on equality of their keys. The
2321 function is used by abstract data `hashtab'. The function
2322 returns 1 if the declarations have the same key, 0 otherwise. */
2323 static int
2324 decl_eq_p (decl_1, decl_2)
2325 const void *decl_1;
2326 const void *decl_2;
2328 const decl_t d1 = (const decl_t) decl_1;
2329 const decl_t d2 = (const decl_t) decl_2;
2331 if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
2332 && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
2333 || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
2334 && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
2335 abort ();
2336 return strcmp ((d1->mode == dm_unit
2337 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
2338 (d2->mode == dm_unit
2339 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2342 /* The declaration table itself is represented by the following
2343 variable. */
2344 static htab_t decl_table;
2346 /* The function inserts declaration into the table. The function does
2347 nothing if a declaration with the same key exists already in the
2348 table. The function returns declaration node in the table with the
2349 same key as given declaration node. */
2351 static decl_t
2352 insert_decl (decl)
2353 decl_t decl;
2355 void **entry_ptr;
2357 entry_ptr = htab_find_slot (decl_table, decl, 1);
2358 if (*entry_ptr == NULL)
2359 *entry_ptr = (void *) decl;
2360 return (decl_t) *entry_ptr;
2363 /* The following variable value is node representing declaration. The
2364 node used for searching declaration with given name. */
2365 static struct decl work_decl;
2367 /* The function searches for declaration in the table with the same
2368 key as node representing name of the declaration. The function
2369 returns node found in the table, NULL if such node does not exist
2370 in the table. */
2371 static decl_t
2372 find_decl (name)
2373 char *name;
2375 void *entry;
2377 work_decl.mode = dm_unit;
2378 DECL_UNIT (&work_decl)->name = name;
2379 entry = htab_find (decl_table, &work_decl);
2380 return (decl_t) entry;
2383 /* The function creates empty declaration table and node representing
2384 declaration and used for searching declaration with given name.
2385 The function must be called only once before any work with the
2386 declaration table. */
2387 static void
2388 initiate_decl_table ()
2390 work_decl.mode = dm_unit;
2391 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2394 /* The function deletes the declaration table. Only call of function
2395 `initiate_declaration_table' is possible immediately after this
2396 function call. */
2397 static void
2398 finish_decl_table ()
2400 htab_delete (decl_table);
2405 /* This page contains checker of pipeline hazard description. */
2407 /* Checking NAMES in an exclusion clause vector and returning formed
2408 unit_set_el_list. */
2409 static unit_set_el_t
2410 process_excls (names, num, excl_pos)
2411 char **names;
2412 int num;
2413 pos_t excl_pos ATTRIBUTE_UNUSED;
2415 unit_set_el_t el_list;
2416 unit_set_el_t last_el;
2417 unit_set_el_t new_el;
2418 decl_t decl_in_table;
2419 int i;
2421 el_list = NULL;
2422 last_el = NULL;
2423 for (i = 0; i < num; i++)
2425 decl_in_table = find_decl (names [i]);
2426 if (decl_in_table == NULL)
2427 error ("unit `%s' in exclusion is not declared", names [i]);
2428 else if (decl_in_table->mode != dm_unit)
2429 error ("`%s' in exclusion is not unit", names [i]);
2430 else
2432 new_el = create_node (sizeof (struct unit_set_el));
2433 new_el->unit_decl = DECL_UNIT (decl_in_table);
2434 new_el->next_unit_set_el = NULL;
2435 if (last_el == NULL)
2436 el_list = last_el = new_el;
2437 else
2439 last_el->next_unit_set_el = new_el;
2440 last_el = last_el->next_unit_set_el;
2444 return el_list;
2447 /* The function adds each element from SOURCE_LIST to the exclusion
2448 list of the each element from DEST_LIST. Checking situation "unit
2449 excludes itself". */
2450 static void
2451 add_excls (dest_list, source_list, excl_pos)
2452 unit_set_el_t dest_list;
2453 unit_set_el_t source_list;
2454 pos_t excl_pos ATTRIBUTE_UNUSED;
2456 unit_set_el_t dst;
2457 unit_set_el_t src;
2458 unit_set_el_t curr_el;
2459 unit_set_el_t prev_el;
2460 unit_set_el_t copy;
2462 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2463 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2465 if (dst->unit_decl == src->unit_decl)
2467 error ("unit `%s' excludes itself", src->unit_decl->name);
2468 continue;
2470 if (dst->unit_decl->automaton_name != NULL
2471 && src->unit_decl->automaton_name != NULL
2472 && strcmp (dst->unit_decl->automaton_name,
2473 src->unit_decl->automaton_name) != 0)
2475 error ("units `%s' and `%s' in exclusion set belong to different automata",
2476 src->unit_decl->name, dst->unit_decl->name);
2477 continue;
2479 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2480 curr_el != NULL;
2481 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2482 if (curr_el->unit_decl == src->unit_decl)
2483 break;
2484 if (curr_el == NULL)
2486 /* Element not found - insert. */
2487 copy = copy_node (src, sizeof (*src));
2488 copy->next_unit_set_el = NULL;
2489 if (prev_el == NULL)
2490 dst->unit_decl->excl_list = copy;
2491 else
2492 prev_el->next_unit_set_el = copy;
2497 /* Checking NAMES in a presence clause vector and returning formed
2498 unit_set_el_list. The function is called only after processing all
2499 exclusion sets. */
2500 static unit_set_el_t
2501 process_presence_absence (names, num, req_pos, presence_p)
2502 char **names;
2503 int num;
2504 pos_t req_pos ATTRIBUTE_UNUSED;
2505 int presence_p;
2507 unit_set_el_t el_list;
2508 unit_set_el_t last_el;
2509 unit_set_el_t new_el;
2510 decl_t decl_in_table;
2511 int i;
2513 el_list = NULL;
2514 last_el = NULL;
2515 for (i = 0; i < num; i++)
2517 decl_in_table = find_decl (names [i]);
2518 if (decl_in_table == NULL)
2519 error ((presence_p
2520 ? "unit `%s' in presence set is not declared"
2521 : "unit `%s' in absence set is not declared"), names [i]);
2522 else if (decl_in_table->mode != dm_unit)
2523 error ((presence_p
2524 ? "`%s' in presence set is not unit"
2525 : "`%s' in absence set is not unit"), names [i]);
2526 else
2528 new_el = create_node (sizeof (struct unit_set_el));
2529 new_el->unit_decl = DECL_UNIT (decl_in_table);
2530 new_el->next_unit_set_el = NULL;
2531 if (last_el == NULL)
2532 el_list = last_el = new_el;
2533 else
2535 last_el->next_unit_set_el = new_el;
2536 last_el = last_el->next_unit_set_el;
2540 return el_list;
2543 /* The function adds each element from SOURCE_LIST to presence (if
2544 PRESENCE_P) or absence list of the each element from DEST_LIST.
2545 Checking situations "unit requires own presence", "unit requires
2546 own absence", and "unit excludes and requires presence of ...".
2547 Remember that we process absence sets only after all presence
2548 sets. */
2549 static void
2550 add_presence_absence (dest_list, source_list, req_pos, presence_p)
2551 unit_set_el_t dest_list;
2552 unit_set_el_t source_list;
2553 pos_t req_pos ATTRIBUTE_UNUSED;
2554 int presence_p;
2556 unit_set_el_t dst;
2557 unit_set_el_t src;
2558 unit_set_el_t curr_el;
2559 unit_set_el_t prev_el;
2560 unit_set_el_t copy;
2562 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2563 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2565 if (dst->unit_decl == src->unit_decl)
2567 error ((presence_p
2568 ? "unit `%s' requires own presence"
2569 : "unit `%s' requires own absence"), src->unit_decl->name);
2570 continue;
2572 if (dst->unit_decl->automaton_name != NULL
2573 && src->unit_decl->automaton_name != NULL
2574 && strcmp (dst->unit_decl->automaton_name,
2575 src->unit_decl->automaton_name) != 0)
2577 error ((presence_p
2578 ? "units `%s' and `%s' in presence set belong to different automata"
2579 : "units `%s' and `%s' in absence set belong to different automata"),
2580 src->unit_decl->name, dst->unit_decl->name);
2581 continue;
2583 for (curr_el = (presence_p
2584 ? dst->unit_decl->presence_list
2585 : dst->unit_decl->absence_list), prev_el = NULL;
2586 curr_el != NULL;
2587 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2588 if (curr_el->unit_decl == src->unit_decl)
2589 break;
2590 if (curr_el == NULL)
2592 /* Element not found - insert if there is no error. */
2593 int no_error_flag = 1;
2595 if (presence_p)
2596 for (curr_el = dst->unit_decl->excl_list;
2597 curr_el != NULL;
2598 curr_el = curr_el->next_unit_set_el)
2600 if (src->unit_decl == curr_el->unit_decl)
2602 if (!w_flag)
2604 error
2605 ("unit `%s' excludes and requires presence of `%s'",
2606 dst->unit_decl->name, src->unit_decl->name);
2607 no_error_flag = 0;
2609 else
2610 warning
2611 ("unit `%s' excludes and requires presence of `%s'",
2612 dst->unit_decl->name, src->unit_decl->name);
2615 else
2616 for (curr_el = dst->unit_decl->presence_list;
2617 curr_el != NULL;
2618 curr_el = curr_el->next_unit_set_el)
2620 if (src->unit_decl == curr_el->unit_decl)
2622 if (!w_flag)
2624 error
2625 ("unit `%s' requires absence and presence of `%s'",
2626 dst->unit_decl->name, src->unit_decl->name);
2627 no_error_flag = 0;
2629 else
2630 warning
2631 ("unit `%s' requires absence and presence of `%s'",
2632 dst->unit_decl->name, src->unit_decl->name);
2635 if (no_error_flag)
2637 copy = copy_node (src, sizeof (*src));
2638 copy->next_unit_set_el = NULL;
2639 if (prev_el == NULL)
2641 if (presence_p)
2642 dst->unit_decl->presence_list = copy;
2643 else
2644 dst->unit_decl->absence_list = copy;
2646 else
2647 prev_el->next_unit_set_el = copy;
2653 /* The function searches for bypass with given IN_INSN_RESERV in given
2654 BYPASS_LIST. */
2655 static struct bypass_decl *
2656 find_bypass (bypass_list, in_insn_reserv)
2657 struct bypass_decl *bypass_list;
2658 struct insn_reserv_decl *in_insn_reserv;
2660 struct bypass_decl *bypass;
2662 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2663 if (bypass->in_insn_reserv == in_insn_reserv)
2664 break;
2665 return bypass;
2668 /* The function processes pipeline description declarations, checks
2669 their correctness, and forms exclusion/presence/absence sets. */
2670 static void
2671 process_decls ()
2673 decl_t decl;
2674 decl_t automaton_decl;
2675 decl_t decl_in_table;
2676 decl_t out_insn_reserv;
2677 decl_t in_insn_reserv;
2678 struct bypass_decl *bypass;
2679 int automaton_presence;
2680 int i;
2682 /* Checking repeated automata declarations. */
2683 automaton_presence = 0;
2684 for (i = 0; i < description->decls_num; i++)
2686 decl = description->decls [i];
2687 if (decl->mode == dm_automaton)
2689 automaton_presence = 1;
2690 decl_in_table = insert_automaton_decl (decl);
2691 if (decl_in_table != decl)
2693 if (!w_flag)
2694 error ("repeated declaration of automaton `%s'",
2695 DECL_AUTOMATON (decl)->name);
2696 else
2697 warning ("repeated declaration of automaton `%s'",
2698 DECL_AUTOMATON (decl)->name);
2702 /* Checking undeclared automata, repeated declarations (except for
2703 automata) and correctness of their attributes (insn latency times
2704 etc.). */
2705 for (i = 0; i < description->decls_num; i++)
2707 decl = description->decls [i];
2708 if (decl->mode == dm_insn_reserv)
2710 DECL_INSN_RESERV (decl)->condexp
2711 = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
2712 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2713 error ("define_insn_reservation `%s' has negative latency time",
2714 DECL_INSN_RESERV (decl)->name);
2715 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2716 description->insns_num++;
2717 decl_in_table = insert_insn_decl (decl);
2718 if (decl_in_table != decl)
2719 error ("`%s' is already used as insn reservation name",
2720 DECL_INSN_RESERV (decl)->name);
2722 else if (decl->mode == dm_bypass)
2724 if (DECL_BYPASS (decl)->latency < 0)
2725 error ("define_bypass `%s - %s' has negative latency time",
2726 DECL_BYPASS (decl)->out_insn_name,
2727 DECL_BYPASS (decl)->in_insn_name);
2729 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2731 if (decl->mode == dm_unit)
2733 DECL_UNIT (decl)->automaton_decl = NULL;
2734 if (DECL_UNIT (decl)->automaton_name != NULL)
2736 automaton_decl
2737 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2738 if (automaton_decl == NULL)
2739 error ("automaton `%s' is not declared",
2740 DECL_UNIT (decl)->automaton_name);
2741 else
2743 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2744 DECL_UNIT (decl)->automaton_decl
2745 = DECL_AUTOMATON (automaton_decl);
2748 else if (automaton_presence)
2749 error ("define_unit `%s' without automaton when one defined",
2750 DECL_UNIT (decl)->name);
2751 DECL_UNIT (decl)->unit_num = description->units_num;
2752 description->units_num++;
2753 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2755 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2756 continue;
2758 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2760 else
2762 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2764 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2765 continue;
2767 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2769 if (decl_in_table == NULL)
2770 decl_in_table = insert_decl (decl);
2771 else
2773 if (decl->mode == dm_unit)
2774 error ("repeated declaration of unit `%s'",
2775 DECL_UNIT (decl)->name);
2776 else
2777 error ("repeated declaration of reservation `%s'",
2778 DECL_RESERV (decl)->name);
2782 /* Check bypasses and form list of bypasses for each (output)
2783 insn. */
2784 for (i = 0; i < description->decls_num; i++)
2786 decl = description->decls [i];
2787 if (decl->mode == dm_bypass)
2789 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2790 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2791 if (out_insn_reserv == NULL)
2792 error ("there is no insn reservation `%s'",
2793 DECL_BYPASS (decl)->out_insn_name);
2794 else if (in_insn_reserv == NULL)
2795 error ("there is no insn reservation `%s'",
2796 DECL_BYPASS (decl)->in_insn_name);
2797 else
2799 DECL_BYPASS (decl)->out_insn_reserv
2800 = DECL_INSN_RESERV (out_insn_reserv);
2801 DECL_BYPASS (decl)->in_insn_reserv
2802 = DECL_INSN_RESERV (in_insn_reserv);
2803 bypass
2804 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2805 DECL_BYPASS (decl)->in_insn_reserv);
2806 if (bypass != NULL)
2808 if (DECL_BYPASS (decl)->latency == bypass->latency)
2810 if (!w_flag)
2811 error
2812 ("the same bypass `%s - %s' is already defined",
2813 DECL_BYPASS (decl)->out_insn_name,
2814 DECL_BYPASS (decl)->in_insn_name);
2815 else
2816 warning
2817 ("the same bypass `%s - %s' is already defined",
2818 DECL_BYPASS (decl)->out_insn_name,
2819 DECL_BYPASS (decl)->in_insn_name);
2821 else
2822 error ("bypass `%s - %s' is already defined",
2823 DECL_BYPASS (decl)->out_insn_name,
2824 DECL_BYPASS (decl)->in_insn_name);
2826 else
2828 DECL_BYPASS (decl)->next
2829 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2830 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2831 = DECL_BYPASS (decl);
2837 /* Check exclusion set declarations and form exclusion sets. */
2838 for (i = 0; i < description->decls_num; i++)
2840 decl = description->decls [i];
2841 if (decl->mode == dm_excl)
2843 unit_set_el_t unit_set_el_list;
2844 unit_set_el_t unit_set_el_list_2;
2846 unit_set_el_list
2847 = process_excls (DECL_EXCL (decl)->names,
2848 DECL_EXCL (decl)->first_list_length, decl->pos);
2849 unit_set_el_list_2
2850 = process_excls (&DECL_EXCL (decl)->names
2851 [DECL_EXCL (decl)->first_list_length],
2852 DECL_EXCL (decl)->names_num
2853 - DECL_EXCL (decl)->first_list_length,
2854 decl->pos);
2855 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2856 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2860 /* Check presence set declarations and form presence sets. */
2861 for (i = 0; i < description->decls_num; i++)
2863 decl = description->decls [i];
2864 if (decl->mode == dm_presence)
2866 unit_set_el_t unit_set_el_list;
2867 unit_set_el_t unit_set_el_list_2;
2869 unit_set_el_list
2870 = process_presence_absence
2871 (DECL_PRESENCE (decl)->names,
2872 DECL_PRESENCE (decl)->first_list_length, decl->pos, 1);
2873 unit_set_el_list_2
2874 = process_presence_absence
2875 (&DECL_PRESENCE (decl)->names
2876 [DECL_PRESENCE (decl)->first_list_length],
2877 DECL_PRESENCE (decl)->names_num
2878 - DECL_PRESENCE (decl)->first_list_length,
2879 decl->pos, 1);
2880 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2881 decl->pos, 1);
2885 /* Check absence set declarations and form absence sets. */
2886 for (i = 0; i < description->decls_num; i++)
2888 decl = description->decls [i];
2889 if (decl->mode == dm_absence)
2891 unit_set_el_t unit_set_el_list;
2892 unit_set_el_t unit_set_el_list_2;
2894 unit_set_el_list
2895 = process_presence_absence
2896 (DECL_ABSENCE (decl)->names,
2897 DECL_ABSENCE (decl)->first_list_length, decl->pos, 0);
2898 unit_set_el_list_2
2899 = process_presence_absence
2900 (&DECL_ABSENCE (decl)->names
2901 [DECL_ABSENCE (decl)->first_list_length],
2902 DECL_ABSENCE (decl)->names_num
2903 - DECL_ABSENCE (decl)->first_list_length,
2904 decl->pos, 0);
2905 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2906 decl->pos, 0);
2911 /* The following function checks that declared automaton is used. If
2912 the automaton is not used, the function fixes error/warning. The
2913 following function must be called only after `process_decls'. */
2914 static void
2915 check_automaton_usage ()
2917 decl_t decl;
2918 int i;
2920 for (i = 0; i < description->decls_num; i++)
2922 decl = description->decls [i];
2923 if (decl->mode == dm_automaton
2924 && !DECL_AUTOMATON (decl)->automaton_is_used)
2926 if (!w_flag)
2927 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2928 else
2929 warning ("automaton `%s' is not used",
2930 DECL_AUTOMATON (decl)->name);
2935 /* The following recursive function processes all regexp in order to
2936 fix usage of units or reservations and to fix errors of undeclared
2937 name. The function may change unit_regexp onto reserv_regexp.
2938 Remember that reserv_regexp does not exist before the function
2939 call. */
2940 static regexp_t
2941 process_regexp (regexp)
2942 regexp_t regexp;
2944 decl_t decl_in_table;
2945 regexp_t new_regexp;
2946 int i;
2948 if (regexp->mode == rm_unit)
2950 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2951 if (decl_in_table == NULL)
2952 error ("undeclared unit or reservation `%s'",
2953 REGEXP_UNIT (regexp)->name);
2954 else if (decl_in_table->mode == dm_unit)
2956 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2957 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2959 else if (decl_in_table->mode == dm_reserv)
2961 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2962 new_regexp = create_node (sizeof (struct regexp));
2963 new_regexp->mode = rm_reserv;
2964 new_regexp->pos = regexp->pos;
2965 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2966 REGEXP_RESERV (new_regexp)->reserv_decl
2967 = DECL_RESERV (decl_in_table);
2968 regexp = new_regexp;
2970 else
2971 abort ();
2973 else if (regexp->mode == rm_sequence)
2974 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2975 REGEXP_SEQUENCE (regexp)->regexps [i]
2976 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2977 else if (regexp->mode == rm_allof)
2978 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2979 REGEXP_ALLOF (regexp)->regexps [i]
2980 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2981 else if (regexp->mode == rm_oneof)
2982 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2983 REGEXP_ONEOF (regexp)->regexps [i]
2984 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2985 else if (regexp->mode == rm_repeat)
2986 REGEXP_REPEAT (regexp)->regexp
2987 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2988 else if (regexp->mode != rm_nothing)
2989 abort ();
2990 return regexp;
2993 /* The following function processes regexp of define_reservation and
2994 define_insn_reservation with the aid of function
2995 `process_regexp'. */
2996 static void
2997 process_regexp_decls ()
2999 decl_t decl;
3000 int i;
3002 for (i = 0; i < description->decls_num; i++)
3004 decl = description->decls [i];
3005 if (decl->mode == dm_reserv)
3006 DECL_RESERV (decl)->regexp
3007 = process_regexp (DECL_RESERV (decl)->regexp);
3008 else if (decl->mode == dm_insn_reserv)
3009 DECL_INSN_RESERV (decl)->regexp
3010 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3014 /* The following function checks that declared unit is used. If the
3015 unit is not used, the function fixes errors/warnings. The
3016 following function must be called only after `process_decls',
3017 `process_regexp_decls'. */
3018 static void
3019 check_usage ()
3021 decl_t decl;
3022 int i;
3024 for (i = 0; i < description->decls_num; i++)
3026 decl = description->decls [i];
3027 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3029 if (!w_flag)
3030 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3031 else
3032 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3034 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3036 if (!w_flag)
3037 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3038 else
3039 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3044 /* The following variable value is number of reservation being
3045 processed on loop recognition. */
3046 static int curr_loop_pass_num;
3048 /* The following recursive function returns nonzero value if REGEXP
3049 contains given decl or reservations in given regexp refers for
3050 given decl. */
3051 static int
3052 loop_in_regexp (regexp, start_decl)
3053 regexp_t regexp;
3054 decl_t start_decl;
3056 int i;
3058 if (regexp == NULL)
3059 return 0;
3060 if (regexp->mode == rm_unit)
3061 return 0;
3062 else if (regexp->mode == rm_reserv)
3064 if (start_decl->mode == dm_reserv
3065 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3066 return 1;
3067 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3068 == curr_loop_pass_num)
3069 /* declaration has been processed. */
3070 return 0;
3071 else
3073 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3074 = curr_loop_pass_num;
3075 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3076 start_decl);
3079 else if (regexp->mode == rm_sequence)
3081 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3082 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3083 return 1;
3084 return 0;
3086 else if (regexp->mode == rm_allof)
3088 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3089 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3090 return 1;
3091 return 0;
3093 else if (regexp->mode == rm_oneof)
3095 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3096 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3097 return 1;
3098 return 0;
3100 else if (regexp->mode == rm_repeat)
3101 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3102 else
3104 if (regexp->mode != rm_nothing)
3105 abort ();
3106 return 0;
3110 /* The following function fixes errors "cycle in definition ...". The
3111 function uses function `loop_in_regexp' for that. */
3112 static void
3113 check_loops_in_regexps ()
3115 decl_t decl;
3116 int i;
3118 for (i = 0; i < description->decls_num; i++)
3120 decl = description->decls [i];
3121 if (decl->mode == dm_reserv)
3122 DECL_RESERV (decl)->loop_pass_num = 0;
3124 for (i = 0; i < description->decls_num; i++)
3126 decl = description->decls [i];
3127 curr_loop_pass_num = i;
3129 if (decl->mode == dm_reserv)
3131 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
3132 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3134 if (DECL_RESERV (decl)->regexp == NULL)
3135 abort ();
3136 error ("cycle in definition of reservation `%s'",
3137 DECL_RESERV (decl)->name);
3143 /* The function recursively processes IR of reservation and defines
3144 max and min cycle for reservation of unit and for result in the
3145 reservation. */
3146 static int
3147 process_regexp_cycles (regexp, start_cycle)
3148 regexp_t regexp;
3149 int start_cycle;
3151 int i;
3153 if (regexp->mode == rm_unit)
3155 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < start_cycle)
3156 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = start_cycle;
3157 return start_cycle;
3159 else if (regexp->mode == rm_reserv)
3160 return process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3161 start_cycle);
3162 else if (regexp->mode == rm_repeat)
3164 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3165 start_cycle = process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3166 start_cycle) + 1;
3167 return start_cycle;
3169 else if (regexp->mode == rm_sequence)
3171 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3172 start_cycle
3173 = process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3174 start_cycle) + 1;
3175 return start_cycle;
3177 else if (regexp->mode == rm_allof)
3179 int finish_cycle = 0;
3180 int cycle;
3182 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3184 cycle = process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3185 start_cycle);
3186 if (finish_cycle < cycle)
3187 finish_cycle = cycle;
3189 return finish_cycle;
3191 else if (regexp->mode == rm_oneof)
3193 int finish_cycle = 0;
3194 int cycle;
3196 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3198 cycle = process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3199 start_cycle);
3200 if (finish_cycle < cycle)
3201 finish_cycle = cycle;
3203 return finish_cycle;
3205 else
3207 if (regexp->mode != rm_nothing)
3208 abort ();
3209 return start_cycle;
3213 /* The following function is called only for correct program. The
3214 function defines max reservation of insns in cycles. */
3215 static void
3216 evaluate_max_reserv_cycles ()
3218 int max_insn_cycles_num;
3219 decl_t decl;
3220 int i;
3222 description->max_insn_reserv_cycles = 0;
3223 for (i = 0; i < description->decls_num; i++)
3225 decl = description->decls [i];
3226 if (decl->mode == dm_insn_reserv)
3228 max_insn_cycles_num
3229 = process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0);
3230 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3231 description->max_insn_reserv_cycles = max_insn_cycles_num;
3234 description->max_insn_reserv_cycles++;
3237 /* The following function calls functions for checking all
3238 description. */
3239 static void
3240 check_all_description ()
3242 process_decls ();
3243 check_automaton_usage ();
3244 process_regexp_decls ();
3245 check_usage ();
3246 check_loops_in_regexps ();
3247 if (!have_error)
3248 evaluate_max_reserv_cycles ();
3253 /* The page contains abstract data `ticker'. This data is used to
3254 report time of different phases of building automata. It is
3255 possibly to write a description for which automata will be built
3256 during several minutes even on fast machine. */
3258 /* The following function creates ticker and makes it active. */
3259 static ticker_t
3260 create_ticker ()
3262 ticker_t ticker;
3264 ticker.modified_creation_time = get_run_time ();
3265 ticker.incremented_off_time = 0;
3266 return ticker;
3269 /* The following function switches off given ticker. */
3270 static void
3271 ticker_off (ticker)
3272 ticker_t *ticker;
3274 if (ticker->incremented_off_time == 0)
3275 ticker->incremented_off_time = get_run_time () + 1;
3278 /* The following function switches on given ticker. */
3279 static void
3280 ticker_on (ticker)
3281 ticker_t *ticker;
3283 if (ticker->incremented_off_time != 0)
3285 ticker->modified_creation_time
3286 += get_run_time () - ticker->incremented_off_time + 1;
3287 ticker->incremented_off_time = 0;
3291 /* The following function returns current time in milliseconds since
3292 the moment when given ticker was created. */
3293 static int
3294 active_time (ticker)
3295 ticker_t ticker;
3297 if (ticker.incremented_off_time != 0)
3298 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3299 else
3300 return get_run_time () - ticker.modified_creation_time;
3303 /* The following function returns string representation of active time
3304 of given ticker. The result is string representation of seconds
3305 with accuracy of 1/100 second. Only result of the last call of the
3306 function exists. Therefore the following code is not correct
3308 printf ("parser time: %s\ngeneration time: %s\n",
3309 active_time_string (parser_ticker),
3310 active_time_string (generation_ticker));
3312 Correct code has to be the following
3314 printf ("parser time: %s\n", active_time_string (parser_ticker));
3315 printf ("generation time: %s\n",
3316 active_time_string (generation_ticker));
3319 static void
3320 print_active_time (f, ticker)
3321 FILE *f;
3322 ticker_t ticker;
3324 int msecs;
3326 msecs = active_time (ticker);
3327 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3332 /* The following variable value is number of automaton which are
3333 really being created. This value is defined on the base of
3334 argument of option `-split'. If the variable has zero value the
3335 number of automata is defined by the constructions `%automaton'.
3336 This case occurs when option `-split' is absent or has zero
3337 argument. If constructions `define_automaton' is absent only one
3338 automaton is created. */
3339 static int automata_num;
3341 /* The following variable values are times of
3342 o transformation of regular expressions
3343 o building NDFA (DFA if !ndfa_flag)
3344 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3345 o DFA minimization
3346 o building insn equivalence classes
3347 o all previous ones
3348 o code output */
3349 static ticker_t transform_time;
3350 static ticker_t NDFA_time;
3351 static ticker_t NDFA_to_DFA_time;
3352 static ticker_t minimize_time;
3353 static ticker_t equiv_time;
3354 static ticker_t automaton_generation_time;
3355 static ticker_t output_time;
3357 /* The following variable values are times of
3358 all checking
3359 all generation
3360 all pipeline hazard translator work */
3361 static ticker_t check_time;
3362 static ticker_t generation_time;
3363 static ticker_t all_time;
3367 /* Pseudo insn decl which denotes advancing cycle. */
3368 static decl_t advance_cycle_insn_decl;
3369 static void
3370 add_advance_cycle_insn_decl ()
3372 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3373 advance_cycle_insn_decl->mode = dm_insn_reserv;
3374 advance_cycle_insn_decl->pos = no_pos;
3375 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3376 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
3377 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3378 = description->insns_num;
3379 description->decls [description->decls_num] = advance_cycle_insn_decl;
3380 description->decls_num++;
3381 description->insns_num++;
3382 num_dfa_decls++;
3386 /* Abstract data `alternative states' which represents
3387 nondeterministic nature of the description (see comments for
3388 structures alt_state and state). */
3390 /* List of free states. */
3391 static alt_state_t first_free_alt_state;
3393 #ifndef NDEBUG
3394 /* The following variables is maximal number of allocated nodes
3395 alt_state. */
3396 static int allocated_alt_states_num = 0;
3397 #endif
3399 /* The following function returns free node alt_state. It may be new
3400 allocated node or node freed earlier. */
3401 static alt_state_t
3402 get_free_alt_state ()
3404 alt_state_t result;
3406 if (first_free_alt_state != NULL)
3408 result = first_free_alt_state;
3409 first_free_alt_state = first_free_alt_state->next_alt_state;
3411 else
3413 #ifndef NDEBUG
3414 allocated_alt_states_num++;
3415 #endif
3416 result = create_node (sizeof (struct alt_state));
3418 result->state = NULL;
3419 result->next_alt_state = NULL;
3420 result->next_sorted_alt_state = NULL;
3421 return result;
3424 /* The function frees node ALT_STATE. */
3425 static void
3426 free_alt_state (alt_state)
3427 alt_state_t alt_state;
3429 if (alt_state == NULL)
3430 return;
3431 alt_state->next_alt_state = first_free_alt_state;
3432 first_free_alt_state = alt_state;
3435 /* The function frees list started with node ALT_STATE_LIST. */
3436 static void
3437 free_alt_states (alt_states_list)
3438 alt_state_t alt_states_list;
3440 alt_state_t curr_alt_state;
3441 alt_state_t next_alt_state;
3443 for (curr_alt_state = alt_states_list;
3444 curr_alt_state != NULL;
3445 curr_alt_state = next_alt_state)
3447 next_alt_state = curr_alt_state->next_alt_state;
3448 free_alt_state (curr_alt_state);
3452 /* The function compares unique numbers of alt states. */
3453 static int
3454 alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
3455 const void *alt_state_ptr_1;
3456 const void *alt_state_ptr_2;
3458 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3459 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3460 return 0;
3461 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3462 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3463 return -1;
3464 else
3465 return 1;
3468 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3469 states from the list. The comparison key is alt state unique
3470 number. */
3471 static alt_state_t
3472 uniq_sort_alt_states (alt_states_list)
3473 alt_state_t alt_states_list;
3475 alt_state_t curr_alt_state;
3476 vla_ptr_t alt_states;
3477 size_t i;
3478 size_t prev_unique_state_ind;
3479 alt_state_t result;
3480 alt_state_t *result_ptr;
3482 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3483 for (curr_alt_state = alt_states_list;
3484 curr_alt_state != NULL;
3485 curr_alt_state = curr_alt_state->next_alt_state)
3486 VLA_PTR_ADD (alt_states, curr_alt_state);
3487 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3488 sizeof (alt_state_t), alt_state_cmp);
3489 if (VLA_PTR_LENGTH (alt_states) == 0)
3490 result = NULL;
3491 else
3493 result_ptr = VLA_PTR_BEGIN (alt_states);
3494 prev_unique_state_ind = 0;
3495 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3496 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3498 prev_unique_state_ind++;
3499 result_ptr [prev_unique_state_ind] = result_ptr [i];
3501 #if 0
3502 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3503 free_alt_state (result_ptr [i]);
3504 #endif
3505 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3506 result_ptr = VLA_PTR_BEGIN (alt_states);
3507 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3508 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3509 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3510 result = *result_ptr;
3512 VLA_PTR_DELETE (alt_states);
3513 return result;
3516 /* The function checks equality of alt state lists. Remember that the
3517 lists must be already sorted by the previous function. */
3518 static int
3519 alt_states_eq (alt_states_1, alt_states_2)
3520 alt_state_t alt_states_1;
3521 alt_state_t alt_states_2;
3523 while (alt_states_1 != NULL && alt_states_2 != NULL
3524 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3526 alt_states_1 = alt_states_1->next_sorted_alt_state;
3527 alt_states_2 = alt_states_2->next_sorted_alt_state;
3529 return alt_states_1 == alt_states_2;
3532 /* Initialization of the abstract data. */
3533 static void
3534 initiate_alt_states ()
3536 first_free_alt_state = NULL;
3539 /* Finishing work with the abstract data. */
3540 static void
3541 finish_alt_states ()
3547 /* The page contains macros for work with bits strings. We could use
3548 standard gcc bitmap or sbitmap but it would result in difficulties
3549 of building canadian cross. */
3551 /* Set bit number bitno in the bit string. The macro is not side
3552 effect proof. */
3553 #define SET_BIT(bitstring, bitno) \
3554 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3556 /* Test if bit number bitno in the bitstring is set. The macro is not
3557 side effect proof. */
3558 #define TEST_BIT(bitstring, bitno) \
3559 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3563 /* This page contains abstract data `state'. */
3565 /* Maximal length of reservations in cycles (>= 1). */
3566 static int max_cycles_num;
3568 /* Number of set elements (see type set_el_t) needed for
3569 representation of one cycle reservation. It is depended on units
3570 number. */
3571 static int els_in_cycle_reserv;
3573 /* Number of set elements (see type set_el_t) needed for
3574 representation of maximal length reservation. Deterministic
3575 reservation is stored as set (bit string) of length equal to the
3576 variable value * number of bits in set_el_t. */
3577 static int els_in_reservs;
3579 /* VLA for representation of array of pointers to unit
3580 declarations. */
3581 static vla_ptr_t units_container;
3583 /* The start address of the array. */
3584 static unit_decl_t *units_array;
3586 /* The state table itself is represented by the following variable. */
3587 static htab_t state_table;
3589 /* VLA for representation of array of pointers to free nodes
3590 `state'. */
3591 static vla_ptr_t free_states;
3593 static int curr_unique_state_num;
3595 #ifndef NDEBUG
3596 /* The following variables is maximal number of allocated nodes
3597 `state'. */
3598 static int allocated_states_num = 0;
3599 #endif
3601 /* Allocate new reservation set. */
3602 static reserv_sets_t
3603 alloc_empty_reserv_sets ()
3605 reserv_sets_t result;
3607 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3608 result = (reserv_sets_t) obstack_base (&irp);
3609 obstack_finish (&irp);
3610 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3611 return result;
3614 /* Hash value of reservation set. */
3615 static unsigned
3616 reserv_sets_hash_value (reservs)
3617 reserv_sets_t reservs;
3619 set_el_t hash_value;
3620 unsigned result;
3621 int reservs_num, i;
3622 set_el_t *reserv_ptr;
3624 hash_value = 0;
3625 reservs_num = els_in_reservs;
3626 reserv_ptr = reservs;
3627 i = 0;
3628 while (reservs_num != 0)
3630 reservs_num--;
3631 hash_value += ((*reserv_ptr >> i)
3632 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3633 i++;
3634 if (i == sizeof (set_el_t) * CHAR_BIT)
3635 i = 0;
3636 reserv_ptr++;
3638 if (sizeof (set_el_t) <= sizeof (unsigned))
3639 return hash_value;
3640 result = 0;
3641 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3643 result += (unsigned) hash_value;
3644 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3646 return result;
3649 /* Comparison of given reservation sets. */
3650 static int
3651 reserv_sets_cmp (reservs_1, reservs_2)
3652 reserv_sets_t reservs_1;
3653 reserv_sets_t reservs_2;
3655 int reservs_num;
3656 set_el_t *reserv_ptr_1;
3657 set_el_t *reserv_ptr_2;
3659 if (reservs_1 == NULL || reservs_2 == NULL)
3660 abort ();
3661 reservs_num = els_in_reservs;
3662 reserv_ptr_1 = reservs_1;
3663 reserv_ptr_2 = reservs_2;
3664 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3666 reservs_num--;
3667 reserv_ptr_1++;
3668 reserv_ptr_2++;
3670 if (reservs_num == 0)
3671 return 0;
3672 else if (*reserv_ptr_1 < *reserv_ptr_2)
3673 return -1;
3674 else
3675 return 1;
3678 /* The function checks equality of the reservation sets. */
3679 static int
3680 reserv_sets_eq (reservs_1, reservs_2)
3681 reserv_sets_t reservs_1;
3682 reserv_sets_t reservs_2;
3684 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3687 /* Set up in the reservation set that unit with UNIT_NUM is used on
3688 CYCLE_NUM. */
3689 static void
3690 set_unit_reserv (reservs, cycle_num, unit_num)
3691 reserv_sets_t reservs;
3692 int cycle_num;
3693 int unit_num;
3695 if (cycle_num >= max_cycles_num)
3696 abort ();
3697 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3698 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3701 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3702 used on CYCLE_NUM. */
3703 static int
3704 test_unit_reserv (reservs, cycle_num, unit_num)
3705 reserv_sets_t reservs;
3706 int cycle_num;
3707 int unit_num;
3709 if (cycle_num >= max_cycles_num)
3710 abort ();
3711 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3712 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3715 /* The function checks that the reservation set represents no one unit
3716 reservation. */
3717 static int
3718 it_is_empty_reserv_sets (operand)
3719 reserv_sets_t operand;
3721 set_el_t *reserv_ptr;
3722 int reservs_num;
3724 if (operand == NULL)
3725 abort ();
3726 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3727 reservs_num != 0;
3728 reserv_ptr++, reservs_num--)
3729 if (*reserv_ptr != 0)
3730 return 0;
3731 return 1;
3734 /* The function checks that the reservation sets are intersected,
3735 i.e. there is a unit reservation on a cycle in both reservation
3736 sets. */
3737 static int
3738 reserv_sets_are_intersected (operand_1, operand_2)
3739 reserv_sets_t operand_1;
3740 reserv_sets_t operand_2;
3742 set_el_t *el_ptr_1;
3743 set_el_t *el_ptr_2;
3744 set_el_t *cycle_ptr_1;
3745 set_el_t *cycle_ptr_2;
3746 int nonzero_p;
3748 if (operand_1 == NULL || operand_2 == NULL)
3749 abort ();
3750 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3751 el_ptr_1 < operand_1 + els_in_reservs;
3752 el_ptr_1++, el_ptr_2++)
3753 if (*el_ptr_1 & *el_ptr_2)
3754 return 1;
3755 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3756 cycle_ptr_1 < operand_1 + els_in_reservs;
3757 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3759 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3760 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3761 el_ptr_1++, el_ptr_2++)
3762 if (*el_ptr_1 & *el_ptr_2)
3763 return 1;
3764 nonzero_p = 0;
3765 for (el_ptr_1 = cycle_ptr_1,
3766 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 1);
3767 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3768 el_ptr_1++, el_ptr_2++)
3769 if (*el_ptr_1 & *el_ptr_2)
3770 break;
3771 else if (*el_ptr_2 != 0)
3772 nonzero_p = 1;
3773 if (nonzero_p && el_ptr_1 >= cycle_ptr_1 + els_in_cycle_reserv)
3774 return 1;
3775 for (el_ptr_1 = cycle_ptr_1,
3776 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 0);
3777 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3778 el_ptr_1++, el_ptr_2++)
3779 /* It looks like code for exclusion but exclusion set is
3780 made as symmetric relation preliminary. */
3781 if (*el_ptr_1 & *el_ptr_2)
3782 return 1;
3784 return 0;
3787 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3788 cpu cycle. The remaining bits of OPERAND (representing the last
3789 cycle unit reservations) are not chenged. */
3790 static void
3791 reserv_sets_shift (result, operand)
3792 reserv_sets_t result;
3793 reserv_sets_t operand;
3795 int i;
3797 if (result == NULL || operand == NULL || result == operand)
3798 abort ();
3799 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3800 result [i - els_in_cycle_reserv] = operand [i];
3803 /* OR of the reservation sets. */
3804 static void
3805 reserv_sets_or (result, operand_1, operand_2)
3806 reserv_sets_t result;
3807 reserv_sets_t operand_1;
3808 reserv_sets_t operand_2;
3810 set_el_t *el_ptr_1;
3811 set_el_t *el_ptr_2;
3812 set_el_t *result_set_el_ptr;
3814 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3815 abort ();
3816 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3817 el_ptr_1 < operand_1 + els_in_reservs;
3818 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3819 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3822 /* AND of the reservation sets. */
3823 static void
3824 reserv_sets_and (result, operand_1, operand_2)
3825 reserv_sets_t result;
3826 reserv_sets_t operand_1;
3827 reserv_sets_t operand_2;
3829 set_el_t *el_ptr_1;
3830 set_el_t *el_ptr_2;
3831 set_el_t *result_set_el_ptr;
3833 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3834 abort ();
3835 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3836 el_ptr_1 < operand_1 + els_in_reservs;
3837 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3838 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3841 /* The function outputs string representation of units reservation on
3842 cycle START_CYCLE in the reservation set. The function uses repeat
3843 construction if REPETITION_NUM > 1. */
3844 static void
3845 output_cycle_reservs (f, reservs, start_cycle, repetition_num)
3846 FILE *f;
3847 reserv_sets_t reservs;
3848 int start_cycle;
3849 int repetition_num;
3851 int unit_num;
3852 int reserved_units_num;
3854 reserved_units_num = 0;
3855 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3856 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3857 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3858 reserved_units_num++;
3859 if (repetition_num <= 0)
3860 abort ();
3861 if (repetition_num != 1 && reserved_units_num > 1)
3862 fprintf (f, "(");
3863 reserved_units_num = 0;
3864 for (unit_num = 0;
3865 unit_num < description->units_num;
3866 unit_num++)
3867 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3868 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3870 if (reserved_units_num != 0)
3871 fprintf (f, "+");
3872 reserved_units_num++;
3873 fprintf (f, "%s", units_array [unit_num]->name);
3875 if (reserved_units_num == 0)
3876 fprintf (f, NOTHING_NAME);
3877 if (repetition_num <= 0)
3878 abort ();
3879 if (reserved_units_num > 1)
3880 fprintf (f, ")");
3881 if (repetition_num != 1)
3882 fprintf (f, "*%d", repetition_num);
3885 /* The function outputs string representation of units reservation in
3886 the reservation set. */
3887 static void
3888 output_reserv_sets (f, reservs)
3889 FILE *f;
3890 reserv_sets_t reservs;
3892 int start_cycle = 0;
3893 int cycle;
3894 int repetition_num;
3896 repetition_num = 0;
3897 for (cycle = 0; cycle < max_cycles_num; cycle++)
3898 if (repetition_num == 0)
3900 repetition_num++;
3901 start_cycle = cycle;
3903 else if (memcmp
3904 ((char *) reservs + start_cycle * els_in_cycle_reserv
3905 * sizeof (set_el_t),
3906 (char *) reservs + cycle * els_in_cycle_reserv
3907 * sizeof (set_el_t),
3908 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3909 repetition_num++;
3910 else
3912 if (start_cycle != 0)
3913 fprintf (f, ", ");
3914 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3915 repetition_num = 1;
3916 start_cycle = cycle;
3918 if (start_cycle < max_cycles_num)
3920 if (start_cycle != 0)
3921 fprintf (f, ", ");
3922 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3926 /* The following function returns free node state for AUTOMATON. It
3927 may be new allocated node or node freed earlier. The function also
3928 allocates reservation set if WITH_RESERVS has nonzero value. */
3929 static state_t
3930 get_free_state (with_reservs, automaton)
3931 int with_reservs;
3932 automaton_t automaton;
3934 state_t result;
3936 if (max_cycles_num <= 0 || automaton == NULL)
3937 abort ();
3938 if (VLA_PTR_LENGTH (free_states) != 0)
3940 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
3941 VLA_PTR_SHORTEN (free_states, 1);
3942 result->automaton = automaton;
3943 result->first_out_arc = NULL;
3944 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3945 result->it_was_placed_in_stack_for_DFA_forming = 0;
3946 result->component_states = NULL;
3947 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3949 else
3951 #ifndef NDEBUG
3952 allocated_states_num++;
3953 #endif
3954 result = create_node (sizeof (struct state));
3955 result->automaton = automaton;
3956 result->first_out_arc = NULL;
3957 result->unique_num = curr_unique_state_num;
3958 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3959 curr_unique_state_num++;
3961 if (with_reservs)
3963 if (result->reservs == NULL)
3964 result->reservs = alloc_empty_reserv_sets ();
3965 else
3966 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3968 return result;
3971 /* The function frees node STATE. */
3972 static void
3973 free_state (state)
3974 state_t state;
3976 free_alt_states (state->component_states);
3977 VLA_PTR_ADD (free_states, state);
3980 /* Hash value of STATE. If STATE represents deterministic state it is
3981 simply hash value of the corresponding reservation set. Otherwise
3982 it is formed from hash values of the component deterministic
3983 states. One more key is order number of state automaton. */
3984 static hashval_t
3985 state_hash (state)
3986 const void *state;
3988 unsigned int hash_value;
3989 alt_state_t alt_state;
3991 if (((state_t) state)->component_states == NULL)
3992 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3993 else
3995 hash_value = 0;
3996 for (alt_state = ((state_t) state)->component_states;
3997 alt_state != NULL;
3998 alt_state = alt_state->next_sorted_alt_state)
3999 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4000 | (hash_value << CHAR_BIT))
4001 + alt_state->state->unique_num);
4003 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4004 | (hash_value << CHAR_BIT))
4005 + ((state_t) state)->automaton->automaton_order_num);
4006 return hash_value;
4009 /* Return nonzero value if the states are the same. */
4010 static int
4011 state_eq_p (state_1, state_2)
4012 const void *state_1;
4013 const void *state_2;
4015 alt_state_t alt_state_1;
4016 alt_state_t alt_state_2;
4018 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
4019 return 0;
4020 else if (((state_t) state_1)->component_states == NULL
4021 && ((state_t) state_2)->component_states == NULL)
4022 return reserv_sets_eq (((state_t) state_1)->reservs,
4023 ((state_t) state_2)->reservs);
4024 else if (((state_t) state_1)->component_states != NULL
4025 && ((state_t) state_2)->component_states != NULL)
4027 for (alt_state_1 = ((state_t) state_1)->component_states,
4028 alt_state_2 = ((state_t) state_2)->component_states;
4029 alt_state_1 != NULL && alt_state_2 != NULL;
4030 alt_state_1 = alt_state_1->next_sorted_alt_state,
4031 alt_state_2 = alt_state_2->next_sorted_alt_state)
4032 /* All state in the list must be already in the hash table.
4033 Also the lists must be sorted. */
4034 if (alt_state_1->state != alt_state_2->state)
4035 return 0;
4036 return alt_state_1 == alt_state_2;
4038 else
4039 return 0;
4042 /* Insert STATE into the state table. */
4043 static state_t
4044 insert_state (state)
4045 state_t state;
4047 void **entry_ptr;
4049 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
4050 if (*entry_ptr == NULL)
4051 *entry_ptr = (void *) state;
4052 return (state_t) *entry_ptr;
4055 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4056 deterministic STATE. */
4057 static void
4058 set_state_reserv (state, cycle_num, unit_num)
4059 state_t state;
4060 int cycle_num;
4061 int unit_num;
4063 set_unit_reserv (state->reservs, cycle_num, unit_num);
4066 /* Return nonzero value if the deterministic states contains a
4067 reservation of the same cpu unit on the same cpu cycle. */
4068 static int
4069 intersected_state_reservs_p (state1, state2)
4070 state_t state1;
4071 state_t state2;
4073 if (state1->automaton != state2->automaton)
4074 abort ();
4075 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
4078 /* Return deterministic state (inserted into the table) which
4079 representing the automaton state whic is union of reservations of
4080 deterministic states. */
4081 static state_t
4082 states_union (state1, state2)
4083 state_t state1;
4084 state_t state2;
4086 state_t result;
4087 state_t state_in_table;
4089 if (state1->automaton != state2->automaton)
4090 abort ();
4091 result = get_free_state (1, state1->automaton);
4092 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
4093 state_in_table = insert_state (result);
4094 if (result != state_in_table)
4096 free_state (result);
4097 result = state_in_table;
4099 return result;
4102 /* Return deterministic state (inserted into the table) which
4103 represent the automaton state is obtained from deterministic STATE
4104 by advancing cpu cycle. */
4105 static state_t
4106 state_shift (state)
4107 state_t state;
4109 state_t result;
4110 state_t state_in_table;
4112 result = get_free_state (1, state->automaton);
4113 reserv_sets_shift (result->reservs, state->reservs);
4114 state_in_table = insert_state (result);
4115 if (result != state_in_table)
4117 free_state (result);
4118 result = state_in_table;
4120 return result;
4123 /* Initialization of the abstract data. */
4124 static void
4125 initiate_states ()
4127 decl_t decl;
4128 int i;
4130 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
4131 units_array
4132 = (description->decls_num && description->units_num
4133 ? VLA_PTR_BEGIN (units_container) : NULL);
4134 for (i = 0; i < description->decls_num; i++)
4136 decl = description->decls [i];
4137 if (decl->mode == dm_unit)
4138 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
4140 max_cycles_num = description->max_insn_reserv_cycles;
4141 els_in_cycle_reserv
4142 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
4143 / (sizeof (set_el_t) * CHAR_BIT));
4144 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
4145 curr_unique_state_num = 0;
4146 initiate_alt_states ();
4147 VLA_PTR_CREATE (free_states, 1500, "free states");
4148 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
4149 alloc_empty_reserv_sets ();
4152 /* Finishing work with the abstract data. */
4153 static void
4154 finish_states ()
4156 VLA_PTR_DELETE (units_container);
4157 htab_delete (state_table);
4158 VLA_PTR_DELETE (free_states);
4159 finish_alt_states ();
4164 /* Abstract data `arcs'. */
4166 /* List of free arcs. */
4167 static arc_t first_free_arc;
4169 #ifndef NDEBUG
4170 /* The following variables is maximal number of allocated nodes
4171 `arc'. */
4172 static int allocated_arcs_num = 0;
4173 #endif
4175 /* The function frees node ARC. */
4176 static void
4177 free_arc (arc)
4178 arc_t arc;
4180 arc->next_out_arc = first_free_arc;
4181 first_free_arc = arc;
4184 /* The function removes and frees ARC staring from FROM_STATE. */
4185 static void
4186 remove_arc (from_state, arc)
4187 state_t from_state;
4188 arc_t arc;
4190 arc_t prev_arc;
4191 arc_t curr_arc;
4193 if (arc == NULL)
4194 abort ();
4195 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
4196 curr_arc != NULL;
4197 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4198 if (curr_arc == arc)
4199 break;
4200 if (curr_arc == NULL)
4201 abort ();
4202 if (prev_arc == NULL)
4203 from_state->first_out_arc = arc->next_out_arc;
4204 else
4205 prev_arc->next_out_arc = arc->next_out_arc;
4206 free_arc (arc);
4209 /* The functions returns arc with given characteristics (or NULL if
4210 the arc does not exist). */
4211 static arc_t
4212 find_arc (from_state, to_state, insn)
4213 state_t from_state;
4214 state_t to_state;
4215 ainsn_t insn;
4217 arc_t arc;
4219 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4220 if (arc->to_state == to_state && arc->insn == insn)
4221 return arc;
4222 return NULL;
4225 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4226 and with given STATE_ALTS. The function returns added arc (or
4227 already existing arc). */
4228 static arc_t
4229 add_arc (from_state, to_state, ainsn, state_alts)
4230 state_t from_state;
4231 state_t to_state;
4232 ainsn_t ainsn;
4233 int state_alts;
4235 arc_t new_arc;
4237 new_arc = find_arc (from_state, to_state, ainsn);
4238 if (new_arc != NULL)
4239 return new_arc;
4240 if (first_free_arc == NULL)
4242 #ifndef NDEBUG
4243 allocated_arcs_num++;
4244 #endif
4245 new_arc = create_node (sizeof (struct arc));
4246 new_arc->to_state = NULL;
4247 new_arc->insn = NULL;
4248 new_arc->next_out_arc = NULL;
4250 else
4252 new_arc = first_free_arc;
4253 first_free_arc = first_free_arc->next_out_arc;
4255 new_arc->to_state = to_state;
4256 new_arc->insn = ainsn;
4257 ainsn->arc_exists_p = 1;
4258 new_arc->next_out_arc = from_state->first_out_arc;
4259 from_state->first_out_arc = new_arc;
4260 new_arc->next_arc_marked_by_insn = NULL;
4261 new_arc->state_alts = state_alts;
4262 return new_arc;
4265 /* The function returns the first arc starting from STATE. */
4266 static arc_t
4267 first_out_arc (state)
4268 state_t state;
4270 return state->first_out_arc;
4273 /* The function returns next out arc after ARC. */
4274 static arc_t
4275 next_out_arc (arc)
4276 arc_t arc;
4278 return arc->next_out_arc;
4281 /* Initialization of the abstract data. */
4282 static void
4283 initiate_arcs ()
4285 first_free_arc = NULL;
4288 /* Finishing work with the abstract data. */
4289 static void
4290 finish_arcs ()
4296 /* Abstract data `automata lists'. */
4298 /* List of free states. */
4299 static automata_list_el_t first_free_automata_list_el;
4301 /* The list being formed. */
4302 static automata_list_el_t current_automata_list;
4304 /* Hash table of automata lists. */
4305 static htab_t automata_list_table;
4307 /* The following function returns free automata list el. It may be
4308 new allocated node or node freed earlier. */
4309 static automata_list_el_t
4310 get_free_automata_list_el ()
4312 automata_list_el_t result;
4314 if (first_free_automata_list_el != NULL)
4316 result = first_free_automata_list_el;
4317 first_free_automata_list_el
4318 = first_free_automata_list_el->next_automata_list_el;
4320 else
4321 result = create_node (sizeof (struct automata_list_el));
4322 result->automaton = NULL;
4323 result->next_automata_list_el = NULL;
4324 return result;
4327 /* The function frees node AUTOMATA_LIST_EL. */
4328 static void
4329 free_automata_list_el (automata_list_el)
4330 automata_list_el_t automata_list_el;
4332 if (automata_list_el == NULL)
4333 return;
4334 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4335 first_free_automata_list_el = automata_list_el;
4338 /* The function frees list AUTOMATA_LIST. */
4339 static void
4340 free_automata_list (automata_list)
4341 automata_list_el_t automata_list;
4343 automata_list_el_t curr_automata_list_el;
4344 automata_list_el_t next_automata_list_el;
4346 for (curr_automata_list_el = automata_list;
4347 curr_automata_list_el != NULL;
4348 curr_automata_list_el = next_automata_list_el)
4350 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4351 free_automata_list_el (curr_automata_list_el);
4355 /* Hash value of AUTOMATA_LIST. */
4356 static hashval_t
4357 automata_list_hash (automata_list)
4358 const void *automata_list;
4360 unsigned int hash_value;
4361 automata_list_el_t curr_automata_list_el;
4363 hash_value = 0;
4364 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4365 curr_automata_list_el != NULL;
4366 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4367 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4368 | (hash_value << CHAR_BIT))
4369 + curr_automata_list_el->automaton->automaton_order_num);
4370 return hash_value;
4373 /* Return nonzero value if the automata_lists are the same. */
4374 static int
4375 automata_list_eq_p (automata_list_1, automata_list_2)
4376 const void *automata_list_1;
4377 const void *automata_list_2;
4379 automata_list_el_t automata_list_el_1;
4380 automata_list_el_t automata_list_el_2;
4382 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4383 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4384 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4385 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4386 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4387 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4388 return 0;
4389 return automata_list_el_1 == automata_list_el_2;
4392 /* Initialization of the abstract data. */
4393 static void
4394 initiate_automata_lists ()
4396 first_free_automata_list_el = NULL;
4397 automata_list_table = htab_create (1500, automata_list_hash,
4398 automata_list_eq_p, (htab_del) 0);
4401 /* The following function starts new automata list and makes it the
4402 current one. */
4403 static void
4404 automata_list_start ()
4406 current_automata_list = NULL;
4409 /* The following function adds AUTOMATON to the current list. */
4410 static void
4411 automata_list_add (automaton)
4412 automaton_t automaton;
4414 automata_list_el_t el;
4416 el = get_free_automata_list_el ();
4417 el->automaton = automaton;
4418 el->next_automata_list_el = current_automata_list;
4419 current_automata_list = el;
4422 /* The following function finishes forming the current list, inserts
4423 it into the table and returns it. */
4424 static automata_list_el_t
4425 automata_list_finish ()
4427 void **entry_ptr;
4429 if (current_automata_list == NULL)
4430 return NULL;
4431 entry_ptr = htab_find_slot (automata_list_table,
4432 (void *) current_automata_list, 1);
4433 if (*entry_ptr == NULL)
4434 *entry_ptr = (void *) current_automata_list;
4435 else
4436 free_automata_list (current_automata_list);
4437 current_automata_list = NULL;
4438 return (automata_list_el_t) *entry_ptr;
4441 /* Finishing work with the abstract data. */
4442 static void
4443 finish_automata_lists ()
4445 htab_delete (automata_list_table);
4450 /* The page contains abstract data for work with exclusion sets (see
4451 exclusion_set in file rtl.def). */
4453 /* The following variable refers to an exclusion set returned by
4454 get_excl_set. This is bit string of length equal to cpu units
4455 number. If exclusion set for given unit contains 1 for a unit,
4456 then simultaneous reservation of the units is prohibited. */
4457 static reserv_sets_t excl_set;
4459 /* The array contains exclusion sets for each unit. */
4460 static reserv_sets_t *unit_excl_set_table;
4462 /* The following function forms the array containing exclusion sets
4463 for each unit. */
4464 static void
4465 initiate_excl_sets ()
4467 decl_t decl;
4468 reserv_sets_t unit_excl_set;
4469 unit_set_el_t el;
4470 int i;
4472 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4473 excl_set = (reserv_sets_t) obstack_base (&irp);
4474 obstack_finish (&irp);
4475 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4476 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4477 obstack_finish (&irp);
4478 /* Evaluate unit exclusion sets. */
4479 for (i = 0; i < description->decls_num; i++)
4481 decl = description->decls [i];
4482 if (decl->mode == dm_unit)
4484 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4485 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4486 obstack_finish (&irp);
4487 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4488 for (el = DECL_UNIT (decl)->excl_list;
4489 el != NULL;
4490 el = el->next_unit_set_el)
4491 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4492 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4497 /* The function sets up and return EXCL_SET which is union of
4498 exclusion sets for each unit in IN_SET. */
4499 static reserv_sets_t
4500 get_excl_set (in_set)
4501 reserv_sets_t in_set;
4503 int excl_char_num;
4504 int chars_num;
4505 int i;
4506 int start_unit_num;
4507 int unit_num;
4509 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4510 memset (excl_set, 0, chars_num);
4511 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4512 if (((unsigned char *) in_set) [excl_char_num])
4513 for (i = CHAR_BIT - 1; i >= 0; i--)
4514 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4516 start_unit_num = excl_char_num * CHAR_BIT + i;
4517 if (start_unit_num >= description->units_num)
4518 return excl_set;
4519 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4521 excl_set [unit_num]
4522 |= unit_excl_set_table [start_unit_num] [unit_num];
4525 return excl_set;
4530 /* The page contains abstract data for work with presence/absence sets
4531 (see presence_set/absence_set in file rtl.def). */
4533 /* The following variables refer to correspondingly a presence and an
4534 absence set returned by get_presence_absence_set. This is bit
4535 string of length equal to cpu units number. */
4536 static reserv_sets_t presence_set, absence_set;
4538 /* The following arrays contain correspondingly presence and absence
4539 sets for each unit. */
4540 static reserv_sets_t *unit_presence_set_table, *unit_absence_set_table;
4542 /* The following function forms the array containing presence and
4543 absence sets for each unit */
4544 static void
4545 initiate_presence_absence_sets ()
4547 decl_t decl;
4548 reserv_sets_t unit_set;
4549 unit_set_el_t el;
4550 int i;
4552 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4553 presence_set = (reserv_sets_t) obstack_base (&irp);
4554 obstack_finish (&irp);
4555 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4556 unit_presence_set_table = (reserv_sets_t *) obstack_base (&irp);
4557 obstack_finish (&irp);
4558 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4559 absence_set = (reserv_sets_t) obstack_base (&irp);
4560 obstack_finish (&irp);
4561 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4562 unit_absence_set_table = (reserv_sets_t *) obstack_base (&irp);
4563 obstack_finish (&irp);
4564 /* Evaluate unit presence/absence sets. */
4565 for (i = 0; i < description->decls_num; i++)
4567 decl = description->decls [i];
4568 if (decl->mode == dm_unit)
4570 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4571 unit_set = (reserv_sets_t) obstack_base (&irp);
4572 obstack_finish (&irp);
4573 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4574 for (el = DECL_UNIT (decl)->presence_list;
4575 el != NULL;
4576 el = el->next_unit_set_el)
4577 SET_BIT (unit_set, el->unit_decl->unit_num);
4578 unit_presence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4580 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4581 unit_set = (reserv_sets_t) obstack_base (&irp);
4582 obstack_finish (&irp);
4583 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4584 for (el = DECL_UNIT (decl)->absence_list;
4585 el != NULL;
4586 el = el->next_unit_set_el)
4587 SET_BIT (unit_set, el->unit_decl->unit_num);
4588 unit_absence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4593 /* The function sets up and return PRESENCE_SET (if PRESENCE_P) or
4594 ABSENCE_SET which is union of corresponding sets for each unit in
4595 IN_SET. */
4596 static reserv_sets_t
4597 get_presence_absence_set (in_set, presence_p)
4598 reserv_sets_t in_set;
4599 int presence_p;
4601 int char_num;
4602 int chars_num;
4603 int i;
4604 int start_unit_num;
4605 int unit_num;
4607 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4608 if (presence_p)
4609 memset (presence_set, 0, chars_num);
4610 else
4611 memset (absence_set, 0, chars_num);
4612 for (char_num = 0; char_num < chars_num; char_num++)
4613 if (((unsigned char *) in_set) [char_num])
4614 for (i = CHAR_BIT - 1; i >= 0; i--)
4615 if ((((unsigned char *) in_set) [char_num] >> i) & 1)
4617 start_unit_num = char_num * CHAR_BIT + i;
4618 if (start_unit_num >= description->units_num)
4619 return (presence_p ? presence_set : absence_set);
4620 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4621 if (presence_p)
4622 presence_set [unit_num]
4623 |= unit_presence_set_table [start_unit_num] [unit_num];
4624 else
4625 absence_set [unit_num]
4626 |= unit_absence_set_table [start_unit_num] [unit_num];
4628 return (presence_p ? presence_set : absence_set);
4633 /* This page contains code for transformation of original reservations
4634 described in .md file. The main goal of transformations is
4635 simplifying reservation and lifting up all `|' on the top of IR
4636 reservation representation. */
4639 /* The following function makes copy of IR representation of
4640 reservation. The function also substitutes all reservations
4641 defined by define_reservation by corresponding value during making
4642 the copy. */
4643 static regexp_t
4644 copy_insn_regexp (regexp)
4645 regexp_t regexp;
4647 regexp_t result;
4648 int i;
4650 if (regexp->mode == rm_reserv)
4651 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4652 else if (regexp->mode == rm_unit)
4653 result = copy_node (regexp, sizeof (struct regexp));
4654 else if (regexp->mode == rm_repeat)
4656 result = copy_node (regexp, sizeof (struct regexp));
4657 REGEXP_REPEAT (result)->regexp
4658 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4660 else if (regexp->mode == rm_sequence)
4662 result = copy_node (regexp,
4663 sizeof (struct regexp) + sizeof (regexp_t)
4664 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4665 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4666 REGEXP_SEQUENCE (result)->regexps [i]
4667 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4669 else if (regexp->mode == rm_allof)
4671 result = copy_node (regexp,
4672 sizeof (struct regexp) + sizeof (regexp_t)
4673 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4674 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4675 REGEXP_ALLOF (result)->regexps [i]
4676 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4678 else if (regexp->mode == rm_oneof)
4680 result = copy_node (regexp,
4681 sizeof (struct regexp) + sizeof (regexp_t)
4682 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4683 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4684 REGEXP_ONEOF (result)->regexps [i]
4685 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4687 else
4689 if (regexp->mode != rm_nothing)
4690 abort ();
4691 result = copy_node (regexp, sizeof (struct regexp));
4693 return result;
4696 /* The following variable is set up 1 if a transformation has been
4697 applied. */
4698 static int regexp_transformed_p;
4700 /* The function makes transformation
4701 A*N -> A, A, ... */
4702 static regexp_t
4703 transform_1 (regexp)
4704 regexp_t regexp;
4706 int i;
4707 int repeat_num;
4708 regexp_t operand;
4709 pos_t pos;
4711 if (regexp->mode == rm_repeat)
4713 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4714 if (repeat_num <= 1)
4715 abort ();
4716 operand = REGEXP_REPEAT (regexp)->regexp;
4717 pos = regexp->mode;
4718 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4719 * (repeat_num - 1));
4720 regexp->mode = rm_sequence;
4721 regexp->pos = pos;
4722 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4723 for (i = 0; i < repeat_num; i++)
4724 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4725 regexp_transformed_p = 1;
4727 return regexp;
4730 /* The function makes transformations
4731 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4732 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4733 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4734 static regexp_t
4735 transform_2 (regexp)
4736 regexp_t regexp;
4738 if (regexp->mode == rm_sequence)
4740 regexp_t sequence = NULL;
4741 regexp_t result;
4742 int sequence_index = 0;
4743 int i, j;
4745 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4746 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4748 sequence_index = i;
4749 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4750 break;
4752 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4754 if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
4755 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4756 abort ();
4757 result = create_node (sizeof (struct regexp)
4758 + sizeof (regexp_t)
4759 * (REGEXP_SEQUENCE (regexp)->regexps_num
4760 + REGEXP_SEQUENCE (sequence)->regexps_num
4761 - 2));
4762 result->mode = rm_sequence;
4763 result->pos = regexp->pos;
4764 REGEXP_SEQUENCE (result)->regexps_num
4765 = (REGEXP_SEQUENCE (regexp)->regexps_num
4766 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4767 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4768 if (i < sequence_index)
4769 REGEXP_SEQUENCE (result)->regexps [i]
4770 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4771 else if (i > sequence_index)
4772 REGEXP_SEQUENCE (result)->regexps
4773 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4774 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4775 else
4776 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4777 REGEXP_SEQUENCE (result)->regexps [i + j]
4778 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4779 regexp_transformed_p = 1;
4780 regexp = result;
4783 else if (regexp->mode == rm_allof)
4785 regexp_t allof = NULL;
4786 regexp_t result;
4787 int allof_index = 0;
4788 int i, j;
4790 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4791 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4793 allof_index = i;
4794 allof = REGEXP_ALLOF (regexp)->regexps [i];
4795 break;
4797 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4799 if (REGEXP_ALLOF (allof)->regexps_num <= 1
4800 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4801 abort ();
4802 result = create_node (sizeof (struct regexp)
4803 + sizeof (regexp_t)
4804 * (REGEXP_ALLOF (regexp)->regexps_num
4805 + REGEXP_ALLOF (allof)->regexps_num - 2));
4806 result->mode = rm_allof;
4807 result->pos = regexp->pos;
4808 REGEXP_ALLOF (result)->regexps_num
4809 = (REGEXP_ALLOF (regexp)->regexps_num
4810 + REGEXP_ALLOF (allof)->regexps_num - 1);
4811 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4812 if (i < allof_index)
4813 REGEXP_ALLOF (result)->regexps [i]
4814 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4815 else if (i > allof_index)
4816 REGEXP_ALLOF (result)->regexps
4817 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4818 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4819 else
4820 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4821 REGEXP_ALLOF (result)->regexps [i + j]
4822 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4823 regexp_transformed_p = 1;
4824 regexp = result;
4827 else if (regexp->mode == rm_oneof)
4829 regexp_t oneof = NULL;
4830 regexp_t result;
4831 int oneof_index = 0;
4832 int i, j;
4834 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4835 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4837 oneof_index = i;
4838 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4839 break;
4841 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4843 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4844 || REGEXP_ONEOF (regexp)->regexps_num <= 1)
4845 abort ();
4846 result = create_node (sizeof (struct regexp)
4847 + sizeof (regexp_t)
4848 * (REGEXP_ONEOF (regexp)->regexps_num
4849 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4850 result->mode = rm_oneof;
4851 result->pos = regexp->pos;
4852 REGEXP_ONEOF (result)->regexps_num
4853 = (REGEXP_ONEOF (regexp)->regexps_num
4854 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4855 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4856 if (i < oneof_index)
4857 REGEXP_ONEOF (result)->regexps [i]
4858 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4859 else if (i > oneof_index)
4860 REGEXP_ONEOF (result)->regexps
4861 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4862 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4863 else
4864 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4865 REGEXP_ONEOF (result)->regexps [i + j]
4866 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4867 regexp_transformed_p = 1;
4868 regexp = result;
4871 return regexp;
4874 /* The function makes transformations
4875 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4876 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4877 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4878 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4879 static regexp_t
4880 transform_3 (regexp)
4881 regexp_t regexp;
4883 if (regexp->mode == rm_sequence)
4885 regexp_t oneof = NULL;
4886 int oneof_index = 0;
4887 regexp_t result;
4888 regexp_t sequence;
4889 int i, j;
4891 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4892 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4894 oneof_index = i;
4895 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4896 break;
4898 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4900 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4901 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4902 abort ();
4903 result = create_node (sizeof (struct regexp)
4904 + sizeof (regexp_t)
4905 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4906 result->mode = rm_oneof;
4907 result->pos = regexp->pos;
4908 REGEXP_ONEOF (result)->regexps_num
4909 = REGEXP_ONEOF (oneof)->regexps_num;
4910 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4912 sequence
4913 = create_node (sizeof (struct regexp)
4914 + sizeof (regexp_t)
4915 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4916 sequence->mode = rm_sequence;
4917 sequence->pos = regexp->pos;
4918 REGEXP_SEQUENCE (sequence)->regexps_num
4919 = REGEXP_SEQUENCE (regexp)->regexps_num;
4920 REGEXP_ONEOF (result)->regexps [i] = sequence;
4921 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4922 if (j != oneof_index)
4923 REGEXP_SEQUENCE (sequence)->regexps [j]
4924 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4925 else
4926 REGEXP_SEQUENCE (sequence)->regexps [j]
4927 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4929 regexp_transformed_p = 1;
4930 regexp = result;
4933 else if (regexp->mode == rm_allof)
4935 regexp_t oneof = NULL, seq;
4936 int oneof_index = 0, max_seq_length, allof_length;
4937 regexp_t result;
4938 regexp_t allof = NULL, allof_op = NULL;
4939 int i, j;
4941 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4942 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4944 oneof_index = i;
4945 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4946 break;
4948 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4950 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4951 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4952 abort ();
4953 result = create_node (sizeof (struct regexp)
4954 + sizeof (regexp_t)
4955 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4956 result->mode = rm_oneof;
4957 result->pos = regexp->pos;
4958 REGEXP_ONEOF (result)->regexps_num
4959 = REGEXP_ONEOF (oneof)->regexps_num;
4960 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4962 allof
4963 = create_node (sizeof (struct regexp)
4964 + sizeof (regexp_t)
4965 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4966 allof->mode = rm_allof;
4967 allof->pos = regexp->pos;
4968 REGEXP_ALLOF (allof)->regexps_num
4969 = REGEXP_ALLOF (regexp)->regexps_num;
4970 REGEXP_ONEOF (result)->regexps [i] = allof;
4971 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4972 if (j != oneof_index)
4973 REGEXP_ALLOF (allof)->regexps [j]
4974 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4975 else
4976 REGEXP_ALLOF (allof)->regexps [j]
4977 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4979 regexp_transformed_p = 1;
4980 regexp = result;
4982 max_seq_length = 0;
4983 if (regexp->mode == rm_allof)
4984 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4986 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
4988 seq = REGEXP_ALLOF (regexp)->regexps [i];
4989 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4990 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4992 else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit)
4994 max_seq_length = 0;
4995 break;
4998 if (max_seq_length != 0)
5000 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5001 abort ();
5002 result = create_node (sizeof (struct regexp)
5003 + sizeof (regexp_t) * (max_seq_length - 1));
5004 result->mode = rm_sequence;
5005 result->pos = regexp->pos;
5006 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5007 for (i = 0; i < max_seq_length; i++)
5009 allof_length = 0;
5010 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5011 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5012 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5013 ->regexps [j])->regexps_num)))
5015 allof_op
5016 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5017 ->regexps [i]);
5018 allof_length++;
5020 else if (i == 0
5021 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5022 == rm_unit))
5024 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5025 allof_length++;
5027 if (allof_length == 1)
5028 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5029 else
5031 allof = create_node (sizeof (struct regexp)
5032 + sizeof (regexp_t)
5033 * (allof_length - 1));
5034 allof->mode = rm_allof;
5035 allof->pos = regexp->pos;
5036 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5037 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5038 allof_length = 0;
5039 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5040 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5041 && (i <
5042 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5043 ->regexps [j])->regexps_num)))
5045 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5046 ->regexps [j])
5047 ->regexps [i]);
5048 REGEXP_ALLOF (allof)->regexps [allof_length]
5049 = allof_op;
5050 allof_length++;
5052 else if (i == 0
5053 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5054 == rm_unit))
5056 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5057 REGEXP_ALLOF (allof)->regexps [allof_length]
5058 = allof_op;
5059 allof_length++;
5063 regexp_transformed_p = 1;
5064 regexp = result;
5067 return regexp;
5070 /* The function traverses IR of reservation and applies transformations
5071 implemented by FUNC. */
5072 static regexp_t
5073 regexp_transform_func (regexp, func)
5074 regexp_t regexp;
5075 regexp_t (*func) PARAMS ((regexp_t regexp));
5077 int i;
5079 if (regexp->mode == rm_sequence)
5080 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5081 REGEXP_SEQUENCE (regexp)->regexps [i]
5082 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5083 else if (regexp->mode == rm_allof)
5084 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5085 REGEXP_ALLOF (regexp)->regexps [i]
5086 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5087 else if (regexp->mode == rm_oneof)
5088 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5089 REGEXP_ONEOF (regexp)->regexps [i]
5090 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5091 else if (regexp->mode == rm_repeat)
5092 REGEXP_REPEAT (regexp)->regexp
5093 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5094 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5095 abort ();
5096 return (*func) (regexp);
5099 /* The function applies all transformations for IR representation of
5100 reservation REGEXP. */
5101 static regexp_t
5102 transform_regexp (regexp)
5103 regexp_t regexp;
5105 regexp = regexp_transform_func (regexp, transform_1);
5108 regexp_transformed_p = 0;
5109 regexp = regexp_transform_func (regexp, transform_2);
5110 regexp = regexp_transform_func (regexp, transform_3);
5112 while (regexp_transformed_p);
5113 return regexp;
5116 /* The function applys all transformations for reservations of all
5117 insn declarations. */
5118 static void
5119 transform_insn_regexps ()
5121 decl_t decl;
5122 int i;
5124 transform_time = create_ticker ();
5125 add_advance_cycle_insn_decl ();
5126 fprintf (stderr, "Reservation transformation...");
5127 fflush (stderr);
5128 for (i = 0; i < description->decls_num; i++)
5130 decl = description->decls [i];
5131 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5132 DECL_INSN_RESERV (decl)->transformed_regexp
5133 = transform_regexp (copy_insn_regexp
5134 (DECL_INSN_RESERV (decl)->regexp));
5136 fprintf (stderr, "done\n");
5137 ticker_off (&transform_time);
5138 fflush (stderr);
5143 /* The following variable is an array indexed by cycle. Each element
5144 contains cyclic list of units which should be in the same cycle. */
5145 static unit_decl_t *the_same_automaton_lists;
5147 /* The function processes all alternative reservations on CYCLE in
5148 given REGEXP to check the UNIT is not reserved on the all
5149 alternatives. If it is true, the unit should be in the same
5150 automaton with other analogous units reserved on CYCLE in given
5151 REGEXP. */
5152 static void
5153 process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
5154 regexp_t unit;
5155 regexp_t regexp;
5156 int cycle;
5158 int i, k;
5159 regexp_t seq, allof;
5160 unit_decl_t unit_decl, last;
5162 if (regexp == NULL || regexp->mode != rm_oneof)
5163 abort ();
5164 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5165 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5167 seq = REGEXP_ONEOF (regexp)->regexps [i];
5168 if (seq->mode == rm_sequence)
5170 if (cycle >= REGEXP_SEQUENCE (seq)->regexps_num)
5171 break;
5172 allof = REGEXP_SEQUENCE (seq)->regexps [cycle];
5173 if (allof->mode == rm_allof)
5175 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5176 if (REGEXP_ALLOF (allof)->regexps [k]->mode == rm_unit
5177 && (REGEXP_UNIT (REGEXP_ALLOF (allof)->regexps [k])
5178 ->unit_decl == unit_decl))
5179 break;
5180 if (k >= REGEXP_ALLOF (allof)->regexps_num)
5181 break;
5183 else if (allof->mode == rm_unit
5184 && REGEXP_UNIT (allof)->unit_decl != unit_decl)
5185 break;
5187 else if (cycle != 0)
5188 break;
5189 else if (seq->mode == rm_allof)
5191 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5192 if (REGEXP_ALLOF (seq)->regexps [k]->mode == rm_unit
5193 && (REGEXP_UNIT (REGEXP_ALLOF (seq)->regexps [k])->unit_decl
5194 == unit_decl))
5195 break;
5196 if (k >= REGEXP_ALLOF (seq)->regexps_num)
5197 break;
5199 else if (seq->mode == rm_unit
5200 && REGEXP_UNIT (seq)->unit_decl != unit_decl)
5201 break;
5203 if (i >= 0)
5205 if (the_same_automaton_lists [cycle] == NULL)
5206 the_same_automaton_lists [cycle] = unit_decl;
5207 else
5209 for (last = the_same_automaton_lists [cycle];;)
5211 if (last == unit_decl)
5212 return;
5213 if (last->the_same_automaton_unit
5214 == the_same_automaton_lists [cycle])
5215 break;
5216 last = last->the_same_automaton_unit;
5218 last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
5219 unit_decl->the_same_automaton_unit
5220 = the_same_automaton_lists [cycle];
5225 /* The function processes given REGEXP to find units which should be
5226 in the same automaton. */
5227 static void
5228 form_the_same_automaton_unit_lists_from_regexp (regexp)
5229 regexp_t regexp;
5231 int i, j, k;
5232 regexp_t seq, allof, unit;
5234 if (regexp == NULL || regexp->mode != rm_oneof)
5235 return;
5236 for (i = 0; i < description->max_insn_reserv_cycles; i++)
5237 the_same_automaton_lists [i] = NULL;
5238 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5240 seq = REGEXP_ONEOF (regexp)->regexps [i];
5241 if (seq->mode == rm_sequence)
5242 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5244 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5245 if (allof->mode == rm_allof)
5246 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5248 unit = REGEXP_ALLOF (allof)->regexps [k];
5249 if (unit->mode == rm_unit)
5250 process_unit_to_form_the_same_automaton_unit_lists
5251 (unit, regexp, j);
5252 else if (unit->mode != rm_nothing)
5253 abort ();
5255 else if (allof->mode == rm_unit)
5256 process_unit_to_form_the_same_automaton_unit_lists
5257 (allof, regexp, j);
5258 else if (allof->mode != rm_nothing)
5259 abort ();
5261 else if (seq->mode == rm_allof)
5262 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5264 unit = REGEXP_ALLOF (seq)->regexps [k];
5265 if (unit->mode == rm_unit)
5266 process_unit_to_form_the_same_automaton_unit_lists
5267 (unit, regexp, 0);
5268 else if (unit->mode != rm_nothing)
5269 abort ();
5271 else if (seq->mode == rm_unit)
5272 process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
5273 else if (seq->mode != rm_nothing)
5274 abort ();
5278 /* The function initializes data to search for units which should be
5279 in the same automaton and call function
5280 `form_the_same_automaton_unit_lists_from_regexp' for each insn
5281 reservation regexp. */
5282 static void
5283 form_the_same_automaton_unit_lists ()
5285 decl_t decl;
5286 int i;
5288 the_same_automaton_lists
5289 = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
5290 * sizeof (unit_decl_t));
5291 for (i = 0; i < description->decls_num; i++)
5293 decl = description->decls [i];
5294 if (decl->mode == dm_unit)
5296 DECL_UNIT (decl)->the_same_automaton_message_reported_p = FALSE;
5297 DECL_UNIT (decl)->the_same_automaton_unit = DECL_UNIT (decl);
5300 for (i = 0; i < description->decls_num; i++)
5302 decl = description->decls [i];
5303 if (decl->mode == dm_insn_reserv)
5304 form_the_same_automaton_unit_lists_from_regexp
5305 (DECL_INSN_RESERV (decl)->transformed_regexp);
5307 free (the_same_automaton_lists);
5310 /* The function finds units which should be in the same automaton and,
5311 if they are not, reports about it. */
5312 static void
5313 check_unit_distributions_to_automata ()
5315 decl_t decl;
5316 unit_decl_t start_unit_decl, unit_decl;
5317 int i;
5319 form_the_same_automaton_unit_lists ();
5320 for (i = 0; i < description->decls_num; i++)
5322 decl = description->decls [i];
5323 if (decl->mode == dm_unit)
5325 start_unit_decl = DECL_UNIT (decl);
5326 if (!start_unit_decl->the_same_automaton_message_reported_p)
5327 for (unit_decl = start_unit_decl->the_same_automaton_unit;
5328 unit_decl != start_unit_decl;
5329 unit_decl = unit_decl->the_same_automaton_unit)
5330 if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
5332 error ("Units `%s' and `%s' should be in the same automaton",
5333 start_unit_decl->name, unit_decl->name);
5334 unit_decl->the_same_automaton_message_reported_p = TRUE;
5342 /* The page contains code for building alt_states (see comments for
5343 IR) describing all possible insns reservations of an automaton. */
5345 /* Current state being formed for which the current alt_state
5346 refers. */
5347 static state_t state_being_formed;
5349 /* Current alt_state being formed. */
5350 static alt_state_t alt_state_being_formed;
5352 /* This recursive function processes `,' and units in reservation
5353 REGEXP for forming alt_states of AUTOMATON. It is believed that
5354 CURR_CYCLE is start cycle of all reservation REGEXP. */
5355 static int
5356 process_seq_for_forming_states (regexp, automaton, curr_cycle)
5357 regexp_t regexp;
5358 automaton_t automaton;
5359 int curr_cycle;
5361 int i;
5363 if (regexp == NULL)
5364 return curr_cycle;
5365 else if (regexp->mode == rm_unit)
5367 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5368 == automaton->automaton_order_num)
5369 set_state_reserv (state_being_formed, curr_cycle,
5370 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5371 return curr_cycle;
5373 else if (regexp->mode == rm_sequence)
5375 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5376 curr_cycle
5377 = process_seq_for_forming_states
5378 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5379 return curr_cycle;
5381 else if (regexp->mode == rm_allof)
5383 int finish_cycle = 0;
5384 int cycle;
5386 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5388 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5389 ->regexps [i],
5390 automaton, curr_cycle);
5391 if (finish_cycle < cycle)
5392 finish_cycle = cycle;
5394 return finish_cycle;
5396 else
5398 if (regexp->mode != rm_nothing)
5399 abort ();
5400 return curr_cycle;
5404 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5405 inserts alt_state into the table. */
5406 static void
5407 finish_forming_alt_state (alt_state, automaton)
5408 alt_state_t alt_state;
5409 automaton_t automaton ATTRIBUTE_UNUSED;
5411 state_t state_in_table;
5412 state_t corresponding_state;
5414 corresponding_state = alt_state->state;
5415 state_in_table = insert_state (corresponding_state);
5416 if (state_in_table != corresponding_state)
5418 free_state (corresponding_state);
5419 alt_state->state = state_in_table;
5423 /* The following variable value is current automaton insn for whose
5424 reservation the alt states are created. */
5425 static ainsn_t curr_ainsn;
5427 /* This recursive function processes `|' in reservation REGEXP for
5428 forming alt_states of AUTOMATON. List of the alt states should
5429 have the same order as in the description. */
5430 static void
5431 process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5432 regexp_t regexp;
5433 automaton_t automaton;
5434 int inside_oneof_p;
5436 int i;
5438 if (regexp->mode != rm_oneof)
5440 alt_state_being_formed = get_free_alt_state ();
5441 state_being_formed = get_free_state (1, automaton);
5442 alt_state_being_formed->state = state_being_formed;
5443 /* We inserts in reverse order but we process alternatives also
5444 in reverse order. So we have the same order of alternative
5445 as in the description. */
5446 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5447 curr_ainsn->alt_states = alt_state_being_formed;
5448 (void) process_seq_for_forming_states (regexp, automaton, 0);
5449 finish_forming_alt_state (alt_state_being_formed, automaton);
5451 else
5453 if (inside_oneof_p)
5454 abort ();
5455 /* We processes it in reverse order to get list with the same
5456 order as in the description. See also the previous
5457 commentary. */
5458 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5459 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5460 automaton, 1);
5464 /* Create nodes alt_state for all AUTOMATON insns. */
5465 static void
5466 create_alt_states (automaton)
5467 automaton_t automaton;
5469 struct insn_reserv_decl *reserv_decl;
5471 for (curr_ainsn = automaton->ainsn_list;
5472 curr_ainsn != NULL;
5473 curr_ainsn = curr_ainsn->next_ainsn)
5475 reserv_decl = curr_ainsn->insn_reserv_decl;
5476 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5478 curr_ainsn->alt_states = NULL;
5479 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5480 automaton, 0);
5481 curr_ainsn->sorted_alt_states
5482 = uniq_sort_alt_states (curr_ainsn->alt_states);
5489 /* The page contains major code for building DFA(s) for fast pipeline
5490 hazards recognition. */
5492 /* The function forms list of ainsns of AUTOMATON with the same
5493 reservation. */
5494 static void
5495 form_ainsn_with_same_reservs (automaton)
5496 automaton_t automaton;
5498 ainsn_t curr_ainsn;
5499 size_t i;
5500 vla_ptr_t first_insns;
5501 vla_ptr_t last_insns;
5503 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5504 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5505 for (curr_ainsn = automaton->ainsn_list;
5506 curr_ainsn != NULL;
5507 curr_ainsn = curr_ainsn->next_ainsn)
5508 if (curr_ainsn->insn_reserv_decl
5509 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5511 curr_ainsn->next_same_reservs_insn = NULL;
5512 curr_ainsn->first_insn_with_same_reservs = 1;
5514 else
5516 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5517 if (alt_states_eq
5518 (curr_ainsn->sorted_alt_states,
5519 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5520 break;
5521 curr_ainsn->next_same_reservs_insn = NULL;
5522 if (i < VLA_PTR_LENGTH (first_insns))
5524 curr_ainsn->first_insn_with_same_reservs = 0;
5525 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5526 = curr_ainsn;
5527 VLA_PTR (last_insns, i) = curr_ainsn;
5529 else
5531 VLA_PTR_ADD (first_insns, curr_ainsn);
5532 VLA_PTR_ADD (last_insns, curr_ainsn);
5533 curr_ainsn->first_insn_with_same_reservs = 1;
5536 VLA_PTR_DELETE (first_insns);
5537 VLA_PTR_DELETE (last_insns);
5540 /* The following function creates all states of nondeterministic (if
5541 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5542 static void
5543 make_automaton (automaton)
5544 automaton_t automaton;
5546 ainsn_t ainsn;
5547 struct insn_reserv_decl *insn_reserv_decl;
5548 alt_state_t alt_state;
5549 state_t state;
5550 state_t start_state;
5551 state_t state2;
5552 ainsn_t advance_cycle_ainsn;
5553 arc_t added_arc;
5554 vla_ptr_t state_stack;
5556 VLA_PTR_CREATE (state_stack, 150, "state stack");
5557 /* Create the start state (empty state). */
5558 start_state = insert_state (get_free_state (1, automaton));
5559 automaton->start_state = start_state;
5560 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5561 VLA_PTR_ADD (state_stack, start_state);
5562 while (VLA_PTR_LENGTH (state_stack) != 0)
5564 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5565 VLA_PTR_SHORTEN (state_stack, 1);
5566 advance_cycle_ainsn = NULL;
5567 for (ainsn = automaton->ainsn_list;
5568 ainsn != NULL;
5569 ainsn = ainsn->next_ainsn)
5570 if (ainsn->first_insn_with_same_reservs)
5572 insn_reserv_decl = ainsn->insn_reserv_decl;
5573 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5575 /* We process alt_states in the same order as they are
5576 present in the description. */
5577 added_arc = NULL;
5578 for (alt_state = ainsn->alt_states;
5579 alt_state != NULL;
5580 alt_state = alt_state->next_alt_state)
5582 state2 = alt_state->state;
5583 if (!intersected_state_reservs_p (state, state2))
5585 state2 = states_union (state, state2);
5586 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5588 state2->it_was_placed_in_stack_for_NDFA_forming
5589 = 1;
5590 VLA_PTR_ADD (state_stack, state2);
5592 added_arc = add_arc (state, state2, ainsn, 1);
5593 if (!ndfa_flag)
5594 break;
5597 if (!ndfa_flag && added_arc != NULL)
5599 added_arc->state_alts = 0;
5600 for (alt_state = ainsn->alt_states;
5601 alt_state != NULL;
5602 alt_state = alt_state->next_alt_state)
5604 state2 = alt_state->state;
5605 if (!intersected_state_reservs_p (state, state2))
5606 added_arc->state_alts++;
5610 else
5611 advance_cycle_ainsn = ainsn;
5613 /* Add transition to advance cycle. */
5614 state2 = state_shift (state);
5615 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5617 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5618 VLA_PTR_ADD (state_stack, state2);
5620 if (advance_cycle_ainsn == NULL)
5621 abort ();
5622 add_arc (state, state2, advance_cycle_ainsn, 1);
5624 VLA_PTR_DELETE (state_stack);
5627 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5628 static void
5629 form_arcs_marked_by_insn (state)
5630 state_t state;
5632 decl_t decl;
5633 arc_t arc;
5634 int i;
5636 for (i = 0; i < description->decls_num; i++)
5638 decl = description->decls [i];
5639 if (decl->mode == dm_insn_reserv)
5640 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5642 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5644 if (arc->insn == NULL)
5645 abort ();
5646 arc->next_arc_marked_by_insn
5647 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5648 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5652 /* The function creates composed state (see comments for IR) from
5653 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5654 same insn. If the composed state is not in STATE_STACK yet, it is
5655 popped to STATE_STACK. */
5656 static void
5657 create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5658 state_t original_state;
5659 arc_t arcs_marked_by_insn;
5660 vla_ptr_t *state_stack;
5662 state_t state;
5663 alt_state_t curr_alt_state;
5664 alt_state_t new_alt_state;
5665 arc_t curr_arc;
5666 arc_t next_arc;
5667 state_t state_in_table;
5668 state_t temp_state;
5669 alt_state_t canonical_alt_states_list;
5670 int alts_number;
5672 if (arcs_marked_by_insn == NULL)
5673 return;
5674 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5675 state = arcs_marked_by_insn->to_state;
5676 else
5678 if (!ndfa_flag)
5679 abort ();
5680 /* Create composed state. */
5681 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5682 curr_alt_state = NULL;
5683 for (curr_arc = arcs_marked_by_insn;
5684 curr_arc != NULL;
5685 curr_arc = curr_arc->next_arc_marked_by_insn)
5687 new_alt_state = get_free_alt_state ();
5688 new_alt_state->next_alt_state = curr_alt_state;
5689 new_alt_state->state = curr_arc->to_state;
5690 if (curr_arc->to_state->component_states != NULL)
5691 abort ();
5692 curr_alt_state = new_alt_state;
5694 /* There are not identical sets in the alt state list. */
5695 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5696 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5698 temp_state = state;
5699 state = canonical_alt_states_list->state;
5700 free_state (temp_state);
5702 else
5704 state->component_states = canonical_alt_states_list;
5705 state_in_table = insert_state (state);
5706 if (state_in_table != state)
5708 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5709 abort ();
5710 free_state (state);
5711 state = state_in_table;
5713 else
5715 if (state->it_was_placed_in_stack_for_DFA_forming)
5716 abort ();
5717 for (curr_alt_state = state->component_states;
5718 curr_alt_state != NULL;
5719 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5720 for (curr_arc = first_out_arc (curr_alt_state->state);
5721 curr_arc != NULL;
5722 curr_arc = next_out_arc (curr_arc))
5723 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5725 arcs_marked_by_insn->to_state = state;
5726 for (alts_number = 0,
5727 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5728 curr_arc != NULL;
5729 curr_arc = next_arc)
5731 next_arc = curr_arc->next_arc_marked_by_insn;
5732 remove_arc (original_state, curr_arc);
5733 alts_number++;
5735 arcs_marked_by_insn->state_alts = alts_number;
5738 if (!state->it_was_placed_in_stack_for_DFA_forming)
5740 state->it_was_placed_in_stack_for_DFA_forming = 1;
5741 VLA_PTR_ADD (*state_stack, state);
5745 /* The function transforms nondeterministic AUTOMATON into
5746 deterministic. */
5747 static void
5748 NDFA_to_DFA (automaton)
5749 automaton_t automaton;
5751 state_t start_state;
5752 state_t state;
5753 decl_t decl;
5754 vla_ptr_t state_stack;
5755 int i;
5757 VLA_PTR_CREATE (state_stack, 150, "state stack");
5758 /* Create the start state (empty state). */
5759 start_state = automaton->start_state;
5760 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5761 VLA_PTR_ADD (state_stack, start_state);
5762 while (VLA_PTR_LENGTH (state_stack) != 0)
5764 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5765 VLA_PTR_SHORTEN (state_stack, 1);
5766 form_arcs_marked_by_insn (state);
5767 for (i = 0; i < description->decls_num; i++)
5769 decl = description->decls [i];
5770 if (decl->mode == dm_insn_reserv)
5771 create_composed_state
5772 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5773 &state_stack);
5776 VLA_PTR_DELETE (state_stack);
5779 /* The following variable value is current number (1, 2, ...) of passing
5780 graph of states. */
5781 static int curr_state_graph_pass_num;
5783 /* This recursive function passes all states achieved from START_STATE
5784 and applies APPLIED_FUNC to them. */
5785 static void
5786 pass_state_graph (start_state, applied_func)
5787 state_t start_state;
5788 void (*applied_func) PARAMS ((state_t state));
5790 arc_t arc;
5792 if (start_state->pass_num == curr_state_graph_pass_num)
5793 return;
5794 start_state->pass_num = curr_state_graph_pass_num;
5795 (*applied_func) (start_state);
5796 for (arc = first_out_arc (start_state);
5797 arc != NULL;
5798 arc = next_out_arc (arc))
5799 pass_state_graph (arc->to_state, applied_func);
5802 /* This recursive function passes all states of AUTOMATON and applies
5803 APPLIED_FUNC to them. */
5804 static void
5805 pass_states (automaton, applied_func)
5806 automaton_t automaton;
5807 void (*applied_func) PARAMS ((state_t state));
5809 curr_state_graph_pass_num++;
5810 pass_state_graph (automaton->start_state, applied_func);
5813 /* The function initializes code for passing of all states. */
5814 static void
5815 initiate_pass_states ()
5817 curr_state_graph_pass_num = 0;
5820 /* The following vla is used for storing pointers to all achieved
5821 states. */
5822 static vla_ptr_t all_achieved_states;
5824 /* This function is called by function pass_states to add an achieved
5825 STATE. */
5826 static void
5827 add_achieved_state (state)
5828 state_t state;
5830 VLA_PTR_ADD (all_achieved_states, state);
5833 /* The function sets up equivalence numbers of insns which mark all
5834 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5835 nonzero value) or by equiv_class_num_2 of the destination state.
5836 The function returns number of out arcs of STATE. */
5837 static int
5838 set_out_arc_insns_equiv_num (state, odd_iteration_flag)
5839 state_t state;
5840 int odd_iteration_flag;
5842 int state_out_arcs_num;
5843 arc_t arc;
5845 state_out_arcs_num = 0;
5846 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5848 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
5849 || arc->insn->insn_reserv_decl->state_alts != 0)
5850 abort ();
5851 state_out_arcs_num++;
5852 arc->insn->insn_reserv_decl->equiv_class_num
5853 = (odd_iteration_flag
5854 ? arc->to_state->equiv_class_num_1
5855 : arc->to_state->equiv_class_num_2);
5856 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
5857 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
5858 || arc->insn->insn_reserv_decl->state_alts <= 0)
5859 abort ();
5861 return state_out_arcs_num;
5864 /* The function clears equivalence numbers and alt_states in all insns
5865 which mark all out arcs of STATE. */
5866 static void
5867 clear_arc_insns_equiv_num (state)
5868 state_t state;
5870 arc_t arc;
5872 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5874 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5875 arc->insn->insn_reserv_decl->state_alts = 0;
5879 /* The function copies pointers to equivalent states from vla FROM
5880 into vla TO. */
5881 static void
5882 copy_equiv_class (to, from)
5883 vla_ptr_t *to;
5884 const vla_ptr_t *from;
5886 state_t *class_ptr;
5888 VLA_PTR_NULLIFY (*to);
5889 for (class_ptr = VLA_PTR_BEGIN (*from);
5890 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
5891 class_ptr++)
5892 VLA_PTR_ADD (*to, *class_ptr);
5895 /* The function returns nonzero value if STATE is not equivalent to
5896 another state from the same current partition on equivalence
5897 classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of
5898 output arcs. Iteration of making equivalence partition is defined
5899 by ODD_ITERATION_FLAG. */
5900 static int
5901 state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag)
5902 state_t state;
5903 int original_state_out_arcs_num;
5904 int odd_iteration_flag;
5906 arc_t arc;
5907 int state_out_arcs_num;
5909 state_out_arcs_num = 0;
5910 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5912 state_out_arcs_num++;
5913 if ((odd_iteration_flag
5914 ? arc->to_state->equiv_class_num_1
5915 : arc->to_state->equiv_class_num_2)
5916 != arc->insn->insn_reserv_decl->equiv_class_num
5917 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
5918 return 1;
5920 return state_out_arcs_num != original_state_out_arcs_num;
5923 /* The function makes initial partition of STATES on equivalent
5924 classes. */
5925 static state_t
5926 init_equiv_class (states, states_num)
5927 state_t *states;
5928 int states_num;
5930 state_t *state_ptr;
5931 state_t result_equiv_class;
5933 result_equiv_class = NULL;
5934 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
5936 (*state_ptr)->equiv_class_num_1 = 1;
5937 (*state_ptr)->next_equiv_class_state = result_equiv_class;
5938 result_equiv_class = *state_ptr;
5940 return result_equiv_class;
5943 /* The function processes equivalence class given by its pointer
5944 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
5945 are not equivalent states, the function partitions the class
5946 removing nonequivalent states and placing them in
5947 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5948 assigns it to the state equivalence number. If the class has been
5949 partitioned, the function returns nonzero value. */
5950 static int
5951 partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5952 next_iteration_classes, new_equiv_class_num_ptr)
5953 state_t *equiv_class_ptr;
5954 int odd_iteration_flag;
5955 vla_ptr_t *next_iteration_classes;
5956 int *new_equiv_class_num_ptr;
5958 state_t new_equiv_class;
5959 int partition_p;
5960 state_t first_state;
5961 state_t curr_state;
5962 state_t prev_state;
5963 state_t next_state;
5964 int out_arcs_num;
5966 partition_p = 0;
5967 if (*equiv_class_ptr == NULL)
5968 abort ();
5969 for (first_state = *equiv_class_ptr;
5970 first_state != NULL;
5971 first_state = new_equiv_class)
5973 new_equiv_class = NULL;
5974 if (first_state->next_equiv_class_state != NULL)
5976 /* There are more one states in the class equivalence. */
5977 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
5978 odd_iteration_flag);
5979 for (prev_state = first_state,
5980 curr_state = first_state->next_equiv_class_state;
5981 curr_state != NULL;
5982 curr_state = next_state)
5984 next_state = curr_state->next_equiv_class_state;
5985 if (state_is_differed (curr_state, out_arcs_num,
5986 odd_iteration_flag))
5988 /* Remove curr state from the class equivalence. */
5989 prev_state->next_equiv_class_state = next_state;
5990 /* Add curr state to the new class equivalence. */
5991 curr_state->next_equiv_class_state = new_equiv_class;
5992 if (new_equiv_class == NULL)
5993 (*new_equiv_class_num_ptr)++;
5994 if (odd_iteration_flag)
5995 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5996 else
5997 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5998 new_equiv_class = curr_state;
5999 partition_p = 1;
6001 else
6002 prev_state = curr_state;
6004 clear_arc_insns_equiv_num (first_state);
6006 if (new_equiv_class != NULL)
6007 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
6009 return partition_p;
6012 /* The function finds equivalent states of AUTOMATON. */
6013 static void
6014 evaluate_equiv_classes (automaton, equiv_classes)
6015 automaton_t automaton;
6016 vla_ptr_t *equiv_classes;
6018 state_t new_equiv_class;
6019 int new_equiv_class_num;
6020 int odd_iteration_flag;
6021 int finish_flag;
6022 vla_ptr_t next_iteration_classes;
6023 state_t *equiv_class_ptr;
6024 state_t *state_ptr;
6026 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6027 pass_states (automaton, add_achieved_state);
6028 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6029 VLA_PTR_LENGTH (all_achieved_states));
6030 odd_iteration_flag = 0;
6031 new_equiv_class_num = 1;
6032 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6033 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6036 odd_iteration_flag = !odd_iteration_flag;
6037 finish_flag = 1;
6038 copy_equiv_class (equiv_classes, &next_iteration_classes);
6039 /* Transfer equiv numbers for the next iteration. */
6040 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6041 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6042 state_ptr++)
6043 if (odd_iteration_flag)
6044 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6045 else
6046 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6047 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6048 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6049 equiv_class_ptr++)
6050 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6051 &next_iteration_classes,
6052 &new_equiv_class_num))
6053 finish_flag = 0;
6055 while (!finish_flag);
6056 VLA_PTR_DELETE (next_iteration_classes);
6057 VLA_PTR_DELETE (all_achieved_states);
6060 /* The function merges equivalent states of AUTOMATON. */
6061 static void
6062 merge_states (automaton, equiv_classes)
6063 automaton_t automaton;
6064 vla_ptr_t *equiv_classes;
6066 state_t *equiv_class_ptr;
6067 state_t curr_state;
6068 state_t new_state;
6069 state_t first_class_state;
6070 alt_state_t alt_states;
6071 alt_state_t new_alt_state;
6072 arc_t curr_arc;
6073 arc_t next_arc;
6075 /* Create states corresponding to equivalence classes containing two
6076 or more states. */
6077 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6078 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6079 equiv_class_ptr++)
6080 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6082 /* There are more one states in the class equivalence. */
6083 /* Create new compound state. */
6084 new_state = get_free_state (0, automaton);
6085 alt_states = NULL;
6086 first_class_state = *equiv_class_ptr;
6087 for (curr_state = first_class_state;
6088 curr_state != NULL;
6089 curr_state = curr_state->next_equiv_class_state)
6091 curr_state->equiv_class_state = new_state;
6092 new_alt_state = get_free_alt_state ();
6093 new_alt_state->state = curr_state;
6094 new_alt_state->next_sorted_alt_state = alt_states;
6095 alt_states = new_alt_state;
6097 new_state->component_states = alt_states;
6099 else
6100 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6101 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6102 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6103 equiv_class_ptr++)
6104 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6106 first_class_state = *equiv_class_ptr;
6107 /* Create new arcs output from the state corresponding to
6108 equiv class. */
6109 for (curr_arc = first_out_arc (first_class_state);
6110 curr_arc != NULL;
6111 curr_arc = next_out_arc (curr_arc))
6112 add_arc (first_class_state->equiv_class_state,
6113 curr_arc->to_state->equiv_class_state,
6114 curr_arc->insn, curr_arc->state_alts);
6115 /* Delete output arcs from states of given class equivalence. */
6116 for (curr_state = first_class_state;
6117 curr_state != NULL;
6118 curr_state = curr_state->next_equiv_class_state)
6120 if (automaton->start_state == curr_state)
6121 automaton->start_state = curr_state->equiv_class_state;
6122 /* Delete the state and its output arcs. */
6123 for (curr_arc = first_out_arc (curr_state);
6124 curr_arc != NULL;
6125 curr_arc = next_arc)
6127 next_arc = next_out_arc (curr_arc);
6128 free_arc (curr_arc);
6132 else
6134 /* Change `to_state' of arcs output from the state of given
6135 equivalence class. */
6136 for (curr_arc = first_out_arc (*equiv_class_ptr);
6137 curr_arc != NULL;
6138 curr_arc = next_out_arc (curr_arc))
6139 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6143 /* The function sets up new_cycle_p for states if there is arc to the
6144 state marked by advance_cycle_insn_decl. */
6145 static void
6146 set_new_cycle_flags (state)
6147 state_t state;
6149 arc_t arc;
6151 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6152 if (arc->insn->insn_reserv_decl
6153 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6154 arc->to_state->new_cycle_p = 1;
6157 /* The top level function for minimization of deterministic
6158 AUTOMATON. */
6159 static void
6160 minimize_DFA (automaton)
6161 automaton_t automaton;
6163 vla_ptr_t equiv_classes;
6165 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6166 evaluate_equiv_classes (automaton, &equiv_classes);
6167 merge_states (automaton, &equiv_classes);
6168 pass_states (automaton, set_new_cycle_flags);
6169 VLA_PTR_DELETE (equiv_classes);
6172 /* Values of two variables are counted number of states and arcs in an
6173 automaton. */
6174 static int curr_counted_states_num;
6175 static int curr_counted_arcs_num;
6177 /* The function is called by function `pass_states' to count states
6178 and arcs of an automaton. */
6179 static void
6180 incr_states_and_arcs_nums (state)
6181 state_t state;
6183 arc_t arc;
6185 curr_counted_states_num++;
6186 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6187 curr_counted_arcs_num++;
6190 /* The function counts states and arcs of AUTOMATON. */
6191 static void
6192 count_states_and_arcs (automaton, states_num, arcs_num)
6193 automaton_t automaton;
6194 int *states_num;
6195 int *arcs_num;
6197 curr_counted_states_num = 0;
6198 curr_counted_arcs_num = 0;
6199 pass_states (automaton, incr_states_and_arcs_nums);
6200 *states_num = curr_counted_states_num;
6201 *arcs_num = curr_counted_arcs_num;
6204 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6205 recognition after checking and simplifying IR of the
6206 description. */
6207 static void
6208 build_automaton (automaton)
6209 automaton_t automaton;
6211 int states_num;
6212 int arcs_num;
6214 ticker_on (&NDFA_time);
6215 make_automaton (automaton);
6216 ticker_off (&NDFA_time);
6217 count_states_and_arcs (automaton, &states_num, &arcs_num);
6218 automaton->NDFA_states_num = states_num;
6219 automaton->NDFA_arcs_num = arcs_num;
6220 ticker_on (&NDFA_to_DFA_time);
6221 NDFA_to_DFA (automaton);
6222 ticker_off (&NDFA_to_DFA_time);
6223 count_states_and_arcs (automaton, &states_num, &arcs_num);
6224 automaton->DFA_states_num = states_num;
6225 automaton->DFA_arcs_num = arcs_num;
6226 if (!no_minimization_flag)
6228 ticker_on (&minimize_time);
6229 minimize_DFA (automaton);
6230 ticker_off (&minimize_time);
6231 count_states_and_arcs (automaton, &states_num, &arcs_num);
6232 automaton->minimal_DFA_states_num = states_num;
6233 automaton->minimal_DFA_arcs_num = arcs_num;
6239 /* The page contains code for enumeration of all states of an automaton. */
6241 /* Variable used for enumeration of all states of an automaton. Its
6242 value is current number of automaton states. */
6243 static int curr_state_order_num;
6245 /* The function is called by function `pass_states' for enumerating
6246 states. */
6247 static void
6248 set_order_state_num (state)
6249 state_t state;
6251 state->order_state_num = curr_state_order_num;
6252 curr_state_order_num++;
6255 /* The function enumerates all states of AUTOMATON. */
6256 static void
6257 enumerate_states (automaton)
6258 automaton_t automaton;
6260 curr_state_order_num = 0;
6261 pass_states (automaton, set_order_state_num);
6262 automaton->achieved_states_num = curr_state_order_num;
6267 /* The page contains code for finding equivalent automaton insns
6268 (ainsns). */
6270 /* The function inserts AINSN into cyclic list
6271 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6272 static ainsn_t
6273 insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6274 ainsn_t ainsn;
6275 ainsn_t cyclic_equiv_class_insn_list;
6277 if (cyclic_equiv_class_insn_list == NULL)
6278 ainsn->next_equiv_class_insn = ainsn;
6279 else
6281 ainsn->next_equiv_class_insn
6282 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6283 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6285 return ainsn;
6288 /* The function deletes equiv_class_insn into cyclic list of
6289 equivalent ainsns. */
6290 static void
6291 delete_ainsn_from_equiv_class (equiv_class_insn)
6292 ainsn_t equiv_class_insn;
6294 ainsn_t curr_equiv_class_insn;
6295 ainsn_t prev_equiv_class_insn;
6297 prev_equiv_class_insn = equiv_class_insn;
6298 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6299 curr_equiv_class_insn != equiv_class_insn;
6300 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6301 prev_equiv_class_insn = curr_equiv_class_insn;
6302 if (prev_equiv_class_insn != equiv_class_insn)
6303 prev_equiv_class_insn->next_equiv_class_insn
6304 = equiv_class_insn->next_equiv_class_insn;
6307 /* The function processes AINSN of a state in order to find equivalent
6308 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6309 state. */
6310 static void
6311 process_insn_equiv_class (ainsn, insn_arcs_array)
6312 ainsn_t ainsn;
6313 arc_t *insn_arcs_array;
6315 ainsn_t next_insn;
6316 ainsn_t curr_insn;
6317 ainsn_t cyclic_insn_list;
6318 arc_t arc;
6320 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6321 abort ();
6322 curr_insn = ainsn;
6323 /* New class of ainsns which are not equivalent to given ainsn. */
6324 cyclic_insn_list = NULL;
6327 next_insn = curr_insn->next_equiv_class_insn;
6328 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6329 if (arc == NULL
6330 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6331 != arc->to_state))
6333 delete_ainsn_from_equiv_class (curr_insn);
6334 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6335 cyclic_insn_list);
6337 curr_insn = next_insn;
6339 while (curr_insn != ainsn);
6342 /* The function processes STATE in order to find equivalent ainsns. */
6343 static void
6344 process_state_for_insn_equiv_partition (state)
6345 state_t state;
6347 arc_t arc;
6348 arc_t *insn_arcs_array;
6349 int i;
6350 vla_ptr_t insn_arcs_vect;
6352 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6353 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6354 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6355 /* Process insns of the arcs. */
6356 for (i = 0; i < description->insns_num; i++)
6357 insn_arcs_array [i] = NULL;
6358 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6359 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6360 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6361 process_insn_equiv_class (arc->insn, insn_arcs_array);
6362 VLA_PTR_DELETE (insn_arcs_vect);
6365 /* The function searches for equivalent ainsns of AUTOMATON. */
6366 static void
6367 set_insn_equiv_classes (automaton)
6368 automaton_t automaton;
6370 ainsn_t ainsn;
6371 ainsn_t first_insn;
6372 ainsn_t curr_insn;
6373 ainsn_t cyclic_insn_list;
6374 ainsn_t insn_with_same_reservs;
6375 int equiv_classes_num;
6377 /* All insns are included in one equivalence class. */
6378 cyclic_insn_list = NULL;
6379 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6380 if (ainsn->first_insn_with_same_reservs)
6381 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6382 cyclic_insn_list);
6383 /* Process insns in order to make equivalence partition. */
6384 pass_states (automaton, process_state_for_insn_equiv_partition);
6385 /* Enumerate equiv classes. */
6386 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6387 /* Set undefined value. */
6388 ainsn->insn_equiv_class_num = -1;
6389 equiv_classes_num = 0;
6390 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6391 if (ainsn->insn_equiv_class_num < 0)
6393 first_insn = ainsn;
6394 if (!first_insn->first_insn_with_same_reservs)
6395 abort ();
6396 first_insn->first_ainsn_with_given_equialence_num = 1;
6397 curr_insn = first_insn;
6400 for (insn_with_same_reservs = curr_insn;
6401 insn_with_same_reservs != NULL;
6402 insn_with_same_reservs
6403 = insn_with_same_reservs->next_same_reservs_insn)
6404 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6405 curr_insn = curr_insn->next_equiv_class_insn;
6407 while (curr_insn != first_insn);
6408 equiv_classes_num++;
6410 automaton->insn_equiv_classes_num = equiv_classes_num;
6415 /* This page contains code for creating DFA(s) and calls functions
6416 building them. */
6419 /* The following value is used to prevent floating point overflow for
6420 estimating an automaton bound. The value should be less DBL_MAX on
6421 the host machine. We use here approximate minimum of maximal
6422 double floating point value required by ANSI C standard. It
6423 will work for non ANSI sun compiler too. */
6425 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6427 /* The function estimate size of the single DFA used by PHR (pipeline
6428 hazards recognizer). */
6429 static double
6430 estimate_one_automaton_bound ()
6432 decl_t decl;
6433 double one_automaton_estimation_bound;
6434 double root_value;
6435 int i;
6437 one_automaton_estimation_bound = 1.0;
6438 for (i = 0; i < description->decls_num; i++)
6440 decl = description->decls [i];
6441 if (decl->mode == dm_unit)
6443 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num + 1.0)
6444 / automata_num);
6445 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6446 > one_automaton_estimation_bound)
6447 one_automaton_estimation_bound *= root_value;
6450 return one_automaton_estimation_bound;
6453 /* The function compares unit declarations according to their maximal
6454 cycle in reservations. */
6455 static int
6456 compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6457 const void *unit_decl_1;
6458 const void *unit_decl_2;
6460 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6461 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6462 return 1;
6463 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6464 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6465 return 0;
6466 else
6467 return -1;
6470 /* The function makes heuristic assigning automata to units. Actually
6471 efficacy of the algorithm has been checked yet??? */
6472 static void
6473 units_to_automata_heuristic_distr ()
6475 double estimation_bound;
6476 decl_t decl;
6477 decl_t *unit_decl_ptr;
6478 int automaton_num;
6479 int rest_units_num;
6480 double bound_value;
6481 vla_ptr_t unit_decls;
6482 int i;
6484 if (description->units_num == 0)
6485 return;
6486 estimation_bound = estimate_one_automaton_bound ();
6487 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6488 for (i = 0; i < description->decls_num; i++)
6490 decl = description->decls [i];
6491 if (decl->mode == dm_unit)
6492 VLA_PTR_ADD (unit_decls, decl);
6494 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6495 sizeof (decl_t), compare_max_occ_cycle_nums);
6496 automaton_num = 0;
6497 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6498 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6499 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6500 for (unit_decl_ptr++;
6501 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6502 unit_decl_ptr++)
6504 rest_units_num
6505 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6506 if (automata_num - automaton_num - 1 > rest_units_num)
6507 abort ();
6508 if (automaton_num < automata_num - 1
6509 && ((automata_num - automaton_num - 1 == rest_units_num)
6510 || (bound_value
6511 > (estimation_bound
6512 / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6514 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6515 automaton_num++;
6517 else
6518 bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6519 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6521 if (automaton_num != automata_num - 1)
6522 abort ();
6523 VLA_PTR_DELETE (unit_decls);
6526 /* The functions creates automaton insns for each automata. Automaton
6527 insn is simply insn for given automaton which makes reservation
6528 only of units of the automaton. */
6529 static ainsn_t
6530 create_ainsns ()
6532 decl_t decl;
6533 ainsn_t first_ainsn;
6534 ainsn_t curr_ainsn;
6535 ainsn_t prev_ainsn;
6536 int i;
6538 first_ainsn = NULL;
6539 prev_ainsn = NULL;
6540 for (i = 0; i < description->decls_num; i++)
6542 decl = description->decls [i];
6543 if (decl->mode == dm_insn_reserv)
6545 curr_ainsn = create_node (sizeof (struct ainsn));
6546 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6547 curr_ainsn->important_p = FALSE;
6548 curr_ainsn->next_ainsn = NULL;
6549 if (prev_ainsn == NULL)
6550 first_ainsn = curr_ainsn;
6551 else
6552 prev_ainsn->next_ainsn = curr_ainsn;
6553 prev_ainsn = curr_ainsn;
6556 return first_ainsn;
6559 /* The function assigns automata to units according to constructions
6560 `define_automaton' in the description. */
6561 static void
6562 units_to_automata_distr ()
6564 decl_t decl;
6565 int i;
6567 for (i = 0; i < description->decls_num; i++)
6569 decl = description->decls [i];
6570 if (decl->mode == dm_unit)
6572 if (DECL_UNIT (decl)->automaton_decl == NULL
6573 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6574 == NULL))
6575 /* Distribute to the first automaton. */
6576 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6577 else
6578 DECL_UNIT (decl)->corresponding_automaton_num
6579 = (DECL_UNIT (decl)->automaton_decl
6580 ->corresponding_automaton->automaton_order_num);
6585 /* The function creates DFA(s) for fast pipeline hazards recognition
6586 after checking and simplifying IR of the description. */
6587 static void
6588 create_automata ()
6590 automaton_t curr_automaton;
6591 automaton_t prev_automaton;
6592 decl_t decl;
6593 int curr_automaton_num;
6594 int i;
6596 if (automata_num != 0)
6598 units_to_automata_heuristic_distr ();
6599 for (prev_automaton = NULL, curr_automaton_num = 0;
6600 curr_automaton_num < automata_num;
6601 curr_automaton_num++, prev_automaton = curr_automaton)
6603 curr_automaton = create_node (sizeof (struct automaton));
6604 curr_automaton->ainsn_list = create_ainsns ();
6605 curr_automaton->corresponding_automaton_decl = NULL;
6606 curr_automaton->next_automaton = NULL;
6607 curr_automaton->automaton_order_num = curr_automaton_num;
6608 if (prev_automaton == NULL)
6609 description->first_automaton = curr_automaton;
6610 else
6611 prev_automaton->next_automaton = curr_automaton;
6614 else
6616 curr_automaton_num = 0;
6617 prev_automaton = NULL;
6618 for (i = 0; i < description->decls_num; i++)
6620 decl = description->decls [i];
6621 if (decl->mode == dm_automaton
6622 && DECL_AUTOMATON (decl)->automaton_is_used)
6624 curr_automaton = create_node (sizeof (struct automaton));
6625 curr_automaton->ainsn_list = create_ainsns ();
6626 curr_automaton->corresponding_automaton_decl
6627 = DECL_AUTOMATON (decl);
6628 curr_automaton->next_automaton = NULL;
6629 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6630 curr_automaton->automaton_order_num = curr_automaton_num;
6631 if (prev_automaton == NULL)
6632 description->first_automaton = curr_automaton;
6633 else
6634 prev_automaton->next_automaton = curr_automaton;
6635 curr_automaton_num++;
6636 prev_automaton = curr_automaton;
6639 if (curr_automaton_num == 0)
6641 curr_automaton = create_node (sizeof (struct automaton));
6642 curr_automaton->ainsn_list = create_ainsns ();
6643 curr_automaton->corresponding_automaton_decl = NULL;
6644 curr_automaton->next_automaton = NULL;
6645 description->first_automaton = curr_automaton;
6647 units_to_automata_distr ();
6649 NDFA_time = create_ticker ();
6650 ticker_off (&NDFA_time);
6651 NDFA_to_DFA_time = create_ticker ();
6652 ticker_off (&NDFA_to_DFA_time);
6653 minimize_time = create_ticker ();
6654 ticker_off (&minimize_time);
6655 equiv_time = create_ticker ();
6656 ticker_off (&equiv_time);
6657 for (curr_automaton = description->first_automaton;
6658 curr_automaton != NULL;
6659 curr_automaton = curr_automaton->next_automaton)
6661 if (curr_automaton->corresponding_automaton_decl == NULL)
6662 fprintf (stderr, "Create anonymous automaton ...");
6663 else
6664 fprintf (stderr, "Create automaton `%s'...",
6665 curr_automaton->corresponding_automaton_decl->name);
6666 create_alt_states (curr_automaton);
6667 form_ainsn_with_same_reservs (curr_automaton);
6668 build_automaton (curr_automaton);
6669 enumerate_states (curr_automaton);
6670 ticker_on (&equiv_time);
6671 set_insn_equiv_classes (curr_automaton);
6672 ticker_off (&equiv_time);
6673 fprintf (stderr, "done\n");
6679 /* This page contains code for forming string representation of
6680 regexp. The representation is formed on IR obstack. So you should
6681 not work with IR obstack between regexp_representation and
6682 finish_regexp_representation calls. */
6684 /* This recursive function forms string representation of regexp
6685 (without tailing '\0'). */
6686 static void
6687 form_regexp (regexp)
6688 regexp_t regexp;
6690 int i;
6692 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6694 const char *name = (regexp->mode == rm_unit
6695 ? REGEXP_UNIT (regexp)->name
6696 : REGEXP_RESERV (regexp)->name);
6698 obstack_grow (&irp, name, strlen (name));
6700 else if (regexp->mode == rm_sequence)
6701 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6703 if (i != 0)
6704 obstack_1grow (&irp, ',');
6705 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6707 else if (regexp->mode == rm_allof)
6709 obstack_1grow (&irp, '(');
6710 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6712 if (i != 0)
6713 obstack_1grow (&irp, '+');
6714 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6715 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6716 obstack_1grow (&irp, '(');
6717 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6718 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6719 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6720 obstack_1grow (&irp, ')');
6722 obstack_1grow (&irp, ')');
6724 else if (regexp->mode == rm_oneof)
6725 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6727 if (i != 0)
6728 obstack_1grow (&irp, '|');
6729 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6730 obstack_1grow (&irp, '(');
6731 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6732 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6733 obstack_1grow (&irp, ')');
6735 else if (regexp->mode == rm_repeat)
6737 char digits [30];
6739 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6740 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6741 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6742 obstack_1grow (&irp, '(');
6743 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6744 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6745 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6746 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6747 obstack_1grow (&irp, ')');
6748 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6749 obstack_grow (&irp, digits, strlen (digits));
6751 else if (regexp->mode == rm_nothing)
6752 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6753 else
6754 abort ();
6757 /* The function returns string representation of REGEXP on IR
6758 obstack. */
6759 static const char *
6760 regexp_representation (regexp)
6761 regexp_t regexp;
6763 form_regexp (regexp);
6764 obstack_1grow (&irp, '\0');
6765 return obstack_base (&irp);
6768 /* The function frees memory allocated for last formed string
6769 representation of regexp. */
6770 static void
6771 finish_regexp_representation ()
6773 int length = obstack_object_size (&irp);
6775 obstack_blank_fast (&irp, -length);
6780 /* This page contains code for output PHR (pipeline hazards recognizer). */
6782 /* The function outputs minimal C type which is sufficient for
6783 representation numbers in range min_range_value and
6784 max_range_value. Because host machine and build machine may be
6785 different, we use here minimal values required by ANSI C standard
6786 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6787 approximation. */
6789 static void
6790 output_range_type (f, min_range_value, max_range_value)
6791 FILE *f;
6792 long int min_range_value;
6793 long int max_range_value;
6795 if (min_range_value >= 0 && max_range_value <= 255)
6796 fprintf (f, "unsigned char");
6797 else if (min_range_value >= -127 && max_range_value <= 127)
6798 fprintf (f, "signed char");
6799 else if (min_range_value >= 0 && max_range_value <= 65535)
6800 fprintf (f, "unsigned short");
6801 else if (min_range_value >= -32767 && max_range_value <= 32767)
6802 fprintf (f, "short");
6803 else
6804 fprintf (f, "int");
6807 /* The following macro value is used as value of member
6808 `longest_path_length' of state when we are processing path and the
6809 state on the path. */
6811 #define ON_THE_PATH -2
6813 /* The following recursive function searches for the length of the
6814 longest path starting from STATE which does not contain cycles and
6815 `cycle advance' arcs. */
6817 static int
6818 longest_path_length (state)
6819 state_t state;
6821 arc_t arc;
6822 int length, result;
6824 if (state->longest_path_length == ON_THE_PATH)
6825 /* We don't expect the path cycle here. Our graph may contain
6826 only cycles with one state on the path not containing `cycle
6827 advance' arcs -- see comment below. */
6828 abort ();
6829 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6830 /* We alreday visited the state. */
6831 return state->longest_path_length;
6833 result = 0;
6834 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6835 /* Ignore cycles containing one state and `cycle advance' arcs. */
6836 if (arc->to_state != state
6837 && (arc->insn->insn_reserv_decl
6838 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6840 length = longest_path_length (arc->to_state);
6841 if (length > result)
6842 result = length;
6844 state->longest_path_length = result + 1;
6845 return result;
6848 /* The following variable value is value of the corresponding global
6849 variable in the automaton based pipeline interface. */
6851 static int max_dfa_issue_rate;
6853 /* The following function processes the longest path length staring
6854 from STATE to find MAX_DFA_ISSUE_RATE. */
6856 static void
6857 process_state_longest_path_length (state)
6858 state_t state;
6860 int value;
6862 value = longest_path_length (state);
6863 if (value > max_dfa_issue_rate)
6864 max_dfa_issue_rate = value;
6867 /* The following macro value is name of the corresponding global
6868 variable in the automaton based pipeline interface. */
6870 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
6872 /* The following function calculates value of the corresponding
6873 global variable and outputs its declaration. */
6875 static void
6876 output_dfa_max_issue_rate ()
6878 automaton_t automaton;
6880 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
6881 abort ();
6882 max_dfa_issue_rate = 0;
6883 for (automaton = description->first_automaton;
6884 automaton != NULL;
6885 automaton = automaton->next_automaton)
6886 pass_states (automaton, process_state_longest_path_length);
6887 fprintf (output_file, "\nint %s = %d;\n",
6888 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
6891 /* The function outputs all initialization values of VECT with length
6892 vect_length. */
6893 static void
6894 output_vect (vect, vect_length)
6895 vect_el_t *vect;
6896 int vect_length;
6898 int els_on_line;
6900 els_on_line = 1;
6901 if (vect_length == 0)
6902 fprintf (output_file,
6903 "0 /* This is dummy el because the vect is empty */");
6904 else
6908 fprintf (output_file, "%5ld", (long) *vect);
6909 vect_length--;
6910 if (els_on_line == 10)
6912 els_on_line = 0;
6913 fprintf (output_file, ",\n");
6915 else if (vect_length != 0)
6916 fprintf (output_file, ", ");
6917 els_on_line++;
6918 vect++;
6920 while (vect_length != 0);
6924 /* The following is name of the structure which represents DFA(s) for
6925 PHR. */
6926 #define CHIP_NAME "DFA_chip"
6928 /* The following is name of member which represents state of a DFA for
6929 PHR. */
6930 static void
6931 output_chip_member_name (f, automaton)
6932 FILE *f;
6933 automaton_t automaton;
6935 if (automaton->corresponding_automaton_decl == NULL)
6936 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6937 else
6938 fprintf (f, "%s_automaton_state",
6939 automaton->corresponding_automaton_decl->name);
6942 /* The following is name of temporary variable which stores state of a
6943 DFA for PHR. */
6944 static void
6945 output_temp_chip_member_name (f, automaton)
6946 FILE *f;
6947 automaton_t automaton;
6949 fprintf (f, "_");
6950 output_chip_member_name (f, automaton);
6953 /* This is name of macro value which is code of pseudo_insn
6954 representing advancing cpu cycle. Its value is used as internal
6955 code unknown insn. */
6956 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6958 /* Output name of translate vector for given automaton. */
6959 static void
6960 output_translate_vect_name (f, automaton)
6961 FILE *f;
6962 automaton_t automaton;
6964 if (automaton->corresponding_automaton_decl == NULL)
6965 fprintf (f, "translate_%d", automaton->automaton_order_num);
6966 else
6967 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6970 /* Output name for simple transition table representation. */
6971 static void
6972 output_trans_full_vect_name (f, automaton)
6973 FILE *f;
6974 automaton_t automaton;
6976 if (automaton->corresponding_automaton_decl == NULL)
6977 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6978 else
6979 fprintf (f, "%s_transitions",
6980 automaton->corresponding_automaton_decl->name);
6983 /* Output name of comb vector of the transition table for given
6984 automaton. */
6985 static void
6986 output_trans_comb_vect_name (f, automaton)
6987 FILE *f;
6988 automaton_t automaton;
6990 if (automaton->corresponding_automaton_decl == NULL)
6991 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6992 else
6993 fprintf (f, "%s_transitions",
6994 automaton->corresponding_automaton_decl->name);
6997 /* Output name of check vector of the transition table for given
6998 automaton. */
6999 static void
7000 output_trans_check_vect_name (f, automaton)
7001 FILE *f;
7002 automaton_t automaton;
7004 if (automaton->corresponding_automaton_decl == NULL)
7005 fprintf (f, "check_%d", automaton->automaton_order_num);
7006 else
7007 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7010 /* Output name of base vector of the transition table for given
7011 automaton. */
7012 static void
7013 output_trans_base_vect_name (f, automaton)
7014 FILE *f;
7015 automaton_t automaton;
7017 if (automaton->corresponding_automaton_decl == NULL)
7018 fprintf (f, "base_%d", automaton->automaton_order_num);
7019 else
7020 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7023 /* Output name for simple alternatives number representation. */
7024 static void
7025 output_state_alts_full_vect_name (f, automaton)
7026 FILE *f;
7027 automaton_t automaton;
7029 if (automaton->corresponding_automaton_decl == NULL)
7030 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7031 else
7032 fprintf (f, "%s_state_alts",
7033 automaton->corresponding_automaton_decl->name);
7036 /* Output name of comb vector of the alternatives number table for given
7037 automaton. */
7038 static void
7039 output_state_alts_comb_vect_name (f, automaton)
7040 FILE *f;
7041 automaton_t automaton;
7043 if (automaton->corresponding_automaton_decl == NULL)
7044 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7045 else
7046 fprintf (f, "%s_state_alts",
7047 automaton->corresponding_automaton_decl->name);
7050 /* Output name of check vector of the alternatives number table for given
7051 automaton. */
7052 static void
7053 output_state_alts_check_vect_name (f, automaton)
7054 FILE *f;
7055 automaton_t automaton;
7057 if (automaton->corresponding_automaton_decl == NULL)
7058 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7059 else
7060 fprintf (f, "%s_check_state_alts",
7061 automaton->corresponding_automaton_decl->name);
7064 /* Output name of base vector of the alternatives number table for given
7065 automaton. */
7066 static void
7067 output_state_alts_base_vect_name (f, automaton)
7068 FILE *f;
7069 automaton_t automaton;
7071 if (automaton->corresponding_automaton_decl == NULL)
7072 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7073 else
7074 fprintf (f, "%s_base_state_alts",
7075 automaton->corresponding_automaton_decl->name);
7078 /* Output name of simple min issue delay table representation. */
7079 static void
7080 output_min_issue_delay_vect_name (f, automaton)
7081 FILE *f;
7082 automaton_t automaton;
7084 if (automaton->corresponding_automaton_decl == NULL)
7085 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7086 else
7087 fprintf (f, "%s_min_issue_delay",
7088 automaton->corresponding_automaton_decl->name);
7091 /* Output name of deadlock vector for given automaton. */
7092 static void
7093 output_dead_lock_vect_name (f, automaton)
7094 FILE *f;
7095 automaton_t automaton;
7097 if (automaton->corresponding_automaton_decl == NULL)
7098 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7099 else
7100 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7103 /* Output name of reserved units table for AUTOMATON into file F. */
7104 static void
7105 output_reserved_units_table_name (f, automaton)
7106 FILE *f;
7107 automaton_t automaton;
7109 if (automaton->corresponding_automaton_decl == NULL)
7110 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7111 else
7112 fprintf (f, "%s_reserved_units",
7113 automaton->corresponding_automaton_decl->name);
7116 /* Name of the PHR interface macro. */
7117 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7119 /* Name of the PHR interface macro. */
7120 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7122 /* Names of an internal functions: */
7123 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7125 /* This is external type of DFA(s) state. */
7126 #define STATE_TYPE_NAME "state_t"
7128 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7130 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7132 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7134 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7136 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7138 /* Name of cache of insn dfa codes. */
7139 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7141 /* Name of length of cache of insn dfa codes. */
7142 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7144 /* Names of the PHR interface functions: */
7145 #define SIZE_FUNC_NAME "state_size"
7147 #define TRANSITION_FUNC_NAME "state_transition"
7149 #define STATE_ALTS_FUNC_NAME "state_alts"
7151 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7153 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7155 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7157 #define RESET_FUNC_NAME "state_reset"
7159 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7161 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7163 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7165 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7167 #define DFA_START_FUNC_NAME "dfa_start"
7169 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7171 /* Names of parameters of the PHR interface functions. */
7172 #define STATE_NAME "state"
7174 #define INSN_PARAMETER_NAME "insn"
7176 #define INSN2_PARAMETER_NAME "insn2"
7178 #define CHIP_PARAMETER_NAME "chip"
7180 #define FILE_PARAMETER_NAME "f"
7182 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7184 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7186 /* Names of the variables whose values are internal insn code of rtx
7187 insn. */
7188 #define INTERNAL_INSN_CODE_NAME "insn_code"
7190 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7192 /* Names of temporary variables in some functions. */
7193 #define TEMPORARY_VARIABLE_NAME "temp"
7195 #define I_VARIABLE_NAME "i"
7197 /* Name of result variable in some functions. */
7198 #define RESULT_VARIABLE_NAME "res"
7200 /* Name of function (attribute) to translate insn into number of insn
7201 alternatives reservation. */
7202 #define INSN_ALTS_FUNC_NAME "insn_alts"
7204 /* Name of function (attribute) to translate insn into internal insn
7205 code. */
7206 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7208 /* Name of function (attribute) to translate insn into internal insn
7209 code with caching. */
7210 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7212 /* Name of function (attribute) to translate insn into internal insn
7213 code. */
7214 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7216 /* Name of function (attribute) to translate insn into internal insn
7217 code. */
7218 #define BYPASS_P_FUNC_NAME "bypass_p"
7220 /* Output C type which is used for representation of codes of states
7221 of AUTOMATON. */
7222 static void
7223 output_state_member_type (f, automaton)
7224 FILE *f;
7225 automaton_t automaton;
7227 output_range_type (f, 0, automaton->achieved_states_num);
7230 /* Output definition of the structure representing current DFA(s)
7231 state(s). */
7232 static void
7233 output_chip_definitions ()
7235 automaton_t automaton;
7237 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7238 for (automaton = description->first_automaton;
7239 automaton != NULL;
7240 automaton = automaton->next_automaton)
7242 fprintf (output_file, " ");
7243 output_state_member_type (output_file, automaton);
7244 fprintf (output_file, " ");
7245 output_chip_member_name (output_file, automaton);
7246 fprintf (output_file, ";\n");
7248 fprintf (output_file, "};\n\n");
7249 #if 0
7250 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7251 #endif
7255 /* The function outputs translate vector of internal insn code into
7256 insn equivalence class number. The equivalence class number is
7257 used to access to table and vectors representing DFA(s). */
7258 static void
7259 output_translate_vect (automaton)
7260 automaton_t automaton;
7262 ainsn_t ainsn;
7263 int insn_value;
7264 vla_hwint_t translate_vect;
7266 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7267 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7268 for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
7269 /* Undefined value */
7270 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7271 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7272 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7273 = ainsn->insn_equiv_class_num;
7274 fprintf (output_file,
7275 "/* Vector translating external insn codes to internal ones.*/\n");
7276 fprintf (output_file, "static const ");
7277 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7278 fprintf (output_file, " ");
7279 output_translate_vect_name (output_file, automaton);
7280 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7281 output_vect (VLA_HWINT_BEGIN (translate_vect),
7282 VLA_HWINT_LENGTH (translate_vect));
7283 fprintf (output_file, "};\n\n");
7284 VLA_HWINT_DELETE (translate_vect);
7287 /* The value in a table state x ainsn -> something which represents
7288 undefined value. */
7289 static int undefined_vect_el_value;
7291 /* The following function returns nonzero value if the best
7292 representation of the table is comb vector. */
7293 static int
7294 comb_vect_p (tab)
7295 state_ainsn_table_t tab;
7297 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7298 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7301 /* The following function creates new table for AUTOMATON. */
7302 static state_ainsn_table_t
7303 create_state_ainsn_table (automaton)
7304 automaton_t automaton;
7306 state_ainsn_table_t tab;
7307 int full_vect_length;
7308 int i;
7310 tab = create_node (sizeof (struct state_ainsn_table));
7311 tab->automaton = automaton;
7312 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7313 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7314 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7315 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7316 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7317 full_vect_length = (automaton->insn_equiv_classes_num
7318 * automaton->achieved_states_num);
7319 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7320 for (i = 0; i < full_vect_length; i++)
7321 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7322 tab->min_base_vect_el_value = 0;
7323 tab->max_base_vect_el_value = 0;
7324 tab->min_comb_vect_el_value = 0;
7325 tab->max_comb_vect_el_value = 0;
7326 return tab;
7329 /* The following function outputs the best C representation of the
7330 table TAB of given TABLE_NAME. */
7331 static void
7332 output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7333 output_comb_vect_name_func,
7334 output_check_vect_name_func,
7335 output_base_vect_name_func)
7336 state_ainsn_table_t tab;
7337 char *table_name;
7338 void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7339 void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7340 void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7341 void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7343 if (!comb_vect_p (tab))
7345 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7346 fprintf (output_file, "static const ");
7347 output_range_type (output_file, tab->min_comb_vect_el_value,
7348 tab->max_comb_vect_el_value);
7349 fprintf (output_file, " ");
7350 (*output_full_vect_name_func) (output_file, tab->automaton);
7351 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7352 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7353 VLA_HWINT_LENGTH (tab->full_vect));
7354 fprintf (output_file, "};\n\n");
7356 else
7358 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7359 fprintf (output_file, "static const ");
7360 output_range_type (output_file, tab->min_comb_vect_el_value,
7361 tab->max_comb_vect_el_value);
7362 fprintf (output_file, " ");
7363 (*output_comb_vect_name_func) (output_file, tab->automaton);
7364 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7365 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7366 VLA_HWINT_LENGTH (tab->comb_vect));
7367 fprintf (output_file, "};\n\n");
7368 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7369 fprintf (output_file, "static const ");
7370 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7371 fprintf (output_file, " ");
7372 (*output_check_vect_name_func) (output_file, tab->automaton);
7373 fprintf (output_file, "[] = {\n");
7374 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7375 VLA_HWINT_LENGTH (tab->check_vect));
7376 fprintf (output_file, "};\n\n");
7377 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7378 fprintf (output_file, "static const ");
7379 output_range_type (output_file, tab->min_base_vect_el_value,
7380 tab->max_base_vect_el_value);
7381 fprintf (output_file, " ");
7382 (*output_base_vect_name_func) (output_file, tab->automaton);
7383 fprintf (output_file, "[] = {\n");
7384 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7385 VLA_HWINT_LENGTH (tab->base_vect));
7386 fprintf (output_file, "};\n\n");
7390 /* The following function adds vector with length VECT_LENGTH and
7391 elements pointed by VECT to table TAB as its line with number
7392 VECT_NUM. */
7393 static void
7394 add_vect (tab, vect_num, vect, vect_length)
7395 state_ainsn_table_t tab;
7396 int vect_num;
7397 vect_el_t *vect;
7398 int vect_length;
7400 int real_vect_length;
7401 vect_el_t *comb_vect_start;
7402 vect_el_t *check_vect_start;
7403 int comb_vect_index;
7404 int comb_vect_els_num;
7405 int vect_index;
7406 int first_unempty_vect_index;
7407 int additional_els_num;
7408 int no_state_value;
7409 vect_el_t vect_el;
7410 int i;
7412 if (vect_length == 0)
7413 abort ();
7414 real_vect_length = tab->automaton->insn_equiv_classes_num;
7415 if (vect [vect_length - 1] == undefined_vect_el_value)
7416 abort ();
7417 /* Form full vector in the table: */
7418 for (i = 0; i < vect_length; i++)
7419 VLA_HWINT (tab->full_vect,
7420 i + tab->automaton->insn_equiv_classes_num * vect_num)
7421 = vect [i];
7422 /* Form comb vector in the table: */
7423 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7424 abort ();
7425 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7426 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7427 for (first_unempty_vect_index = 0;
7428 first_unempty_vect_index < vect_length;
7429 first_unempty_vect_index++)
7430 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7431 break;
7432 /* Search for the place in comb vect for the inserted vect. */
7433 for (comb_vect_index = 0;
7434 comb_vect_index < comb_vect_els_num;
7435 comb_vect_index++)
7437 for (vect_index = first_unempty_vect_index;
7438 vect_index < vect_length
7439 && vect_index + comb_vect_index < comb_vect_els_num;
7440 vect_index++)
7441 if (vect [vect_index] != undefined_vect_el_value
7442 && (comb_vect_start [vect_index + comb_vect_index]
7443 != undefined_vect_el_value))
7444 break;
7445 if (vect_index >= vect_length
7446 || vect_index + comb_vect_index >= comb_vect_els_num)
7447 break;
7449 /* Slot was found. */
7450 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7451 if (additional_els_num < 0)
7452 additional_els_num = 0;
7453 /* Expand comb and check vectors. */
7454 vect_el = undefined_vect_el_value;
7455 no_state_value = tab->automaton->achieved_states_num;
7456 while (additional_els_num > 0)
7458 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7459 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7460 additional_els_num--;
7462 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7463 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7464 if (VLA_HWINT_LENGTH (tab->comb_vect)
7465 < (size_t) (comb_vect_index + real_vect_length))
7466 abort ();
7467 /* Fill comb and check vectors. */
7468 for (vect_index = 0; vect_index < vect_length; vect_index++)
7469 if (vect [vect_index] != undefined_vect_el_value)
7471 if (comb_vect_start [comb_vect_index + vect_index]
7472 != undefined_vect_el_value)
7473 abort ();
7474 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7475 if (vect [vect_index] < 0)
7476 abort ();
7477 if (tab->max_comb_vect_el_value < vect [vect_index])
7478 tab->max_comb_vect_el_value = vect [vect_index];
7479 if (tab->min_comb_vect_el_value > vect [vect_index])
7480 tab->min_comb_vect_el_value = vect [vect_index];
7481 check_vect_start [comb_vect_index + vect_index] = vect_num;
7483 if (tab->max_base_vect_el_value < comb_vect_index)
7484 tab->max_base_vect_el_value = comb_vect_index;
7485 if (tab->min_base_vect_el_value > comb_vect_index)
7486 tab->min_base_vect_el_value = comb_vect_index;
7487 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7490 /* Return number of out arcs of STATE. */
7491 static int
7492 out_state_arcs_num (state)
7493 state_t state;
7495 int result;
7496 arc_t arc;
7498 result = 0;
7499 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7501 if (arc->insn == NULL)
7502 abort ();
7503 if (arc->insn->first_ainsn_with_given_equialence_num)
7504 result++;
7506 return result;
7509 /* Compare number of possible transitions from the states. */
7510 static int
7511 compare_transition_els_num (state_ptr_1, state_ptr_2)
7512 const void *state_ptr_1;
7513 const void *state_ptr_2;
7515 int transition_els_num_1;
7516 int transition_els_num_2;
7518 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7519 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7520 if (transition_els_num_1 < transition_els_num_2)
7521 return 1;
7522 else if (transition_els_num_1 == transition_els_num_2)
7523 return 0;
7524 else
7525 return -1;
7528 /* The function adds element EL_VALUE to vector VECT for a table state
7529 x AINSN. */
7530 static void
7531 add_vect_el (vect, ainsn, el_value)
7532 vla_hwint_t *vect;
7533 ainsn_t ainsn;
7534 int el_value;
7536 int equiv_class_num;
7537 int vect_index;
7539 if (ainsn == NULL)
7540 abort ();
7541 equiv_class_num = ainsn->insn_equiv_class_num;
7542 for (vect_index = VLA_HWINT_LENGTH (*vect);
7543 vect_index <= equiv_class_num;
7544 vect_index++)
7545 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7546 VLA_HWINT (*vect, equiv_class_num) = el_value;
7549 /* This is for forming vector of states of an automaton. */
7550 static vla_ptr_t output_states_vect;
7552 /* The function is called by function pass_states. The function adds
7553 STATE to `output_states_vect'. */
7554 static void
7555 add_states_vect_el (state)
7556 state_t state;
7558 VLA_PTR_ADD (output_states_vect, state);
7561 /* Form and output vectors (comb, check, base or full vector)
7562 representing transition table of AUTOMATON. */
7563 static void
7564 output_trans_table (automaton)
7565 automaton_t automaton;
7567 state_t *state_ptr;
7568 arc_t arc;
7569 vla_hwint_t transition_vect;
7571 undefined_vect_el_value = automaton->achieved_states_num;
7572 automaton->trans_table = create_state_ainsn_table (automaton);
7573 /* Create vect of pointers to states ordered by num of transitions
7574 from the state (state with the maximum num is the first). */
7575 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7576 pass_states (automaton, add_states_vect_el);
7577 qsort (VLA_PTR_BEGIN (output_states_vect),
7578 VLA_PTR_LENGTH (output_states_vect),
7579 sizeof (state_t), compare_transition_els_num);
7580 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7581 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7582 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7583 state_ptr++)
7585 VLA_HWINT_NULLIFY (transition_vect);
7586 for (arc = first_out_arc (*state_ptr);
7587 arc != NULL;
7588 arc = next_out_arc (arc))
7590 if (arc->insn == NULL)
7591 abort ();
7592 if (arc->insn->first_ainsn_with_given_equialence_num)
7593 add_vect_el (&transition_vect, arc->insn,
7594 arc->to_state->order_state_num);
7596 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7597 VLA_HWINT_BEGIN (transition_vect),
7598 VLA_HWINT_LENGTH (transition_vect));
7600 output_state_ainsn_table
7601 (automaton->trans_table, (char *) "state transitions",
7602 output_trans_full_vect_name, output_trans_comb_vect_name,
7603 output_trans_check_vect_name, output_trans_base_vect_name);
7604 VLA_PTR_DELETE (output_states_vect);
7605 VLA_HWINT_DELETE (transition_vect);
7608 /* Form and output vectors (comb, check, base or simple vect)
7609 representing alts number table of AUTOMATON. The table is state x
7610 ainsn -> number of possible alternative reservations by the
7611 ainsn. */
7612 static void
7613 output_state_alts_table (automaton)
7614 automaton_t automaton;
7616 state_t *state_ptr;
7617 arc_t arc;
7618 vla_hwint_t state_alts_vect;
7620 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7621 automaton->state_alts_table = create_state_ainsn_table (automaton);
7622 /* Create vect of pointers to states ordered by num of transitions
7623 from the state (state with the maximum num is the first). */
7624 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7625 pass_states (automaton, add_states_vect_el);
7626 qsort (VLA_PTR_BEGIN (output_states_vect),
7627 VLA_PTR_LENGTH (output_states_vect),
7628 sizeof (state_t), compare_transition_els_num);
7629 /* Create base, comb, and check vectors. */
7630 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7631 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7632 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7633 state_ptr++)
7635 VLA_HWINT_NULLIFY (state_alts_vect);
7636 for (arc = first_out_arc (*state_ptr);
7637 arc != NULL;
7638 arc = next_out_arc (arc))
7640 if (arc->insn == NULL)
7641 abort ();
7642 if (arc->insn->first_ainsn_with_given_equialence_num)
7643 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7645 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7646 VLA_HWINT_BEGIN (state_alts_vect),
7647 VLA_HWINT_LENGTH (state_alts_vect));
7649 output_state_ainsn_table
7650 (automaton->state_alts_table, (char *) "state insn alternatives",
7651 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7652 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7653 VLA_PTR_DELETE (output_states_vect);
7654 VLA_HWINT_DELETE (state_alts_vect);
7657 /* The current number of passing states to find minimal issue delay
7658 value for an ainsn and state. */
7659 static int curr_state_pass_num;
7662 /* This recursive function passes states to find minimal issue delay
7663 value for AINSN. The state being visited is STATE. The function
7664 returns minimal issue delay value for AINSN in STATE or -1 if we
7665 enter into a loop. */
7666 static int
7667 min_issue_delay_pass_states (state, ainsn)
7668 state_t state;
7669 ainsn_t ainsn;
7671 arc_t arc;
7672 int min_insn_issue_delay, insn_issue_delay;
7674 if (state->state_pass_num == curr_state_pass_num
7675 || state->min_insn_issue_delay != -1)
7676 /* We've entered into a loop or already have the correct value for
7677 given state and ainsn. */
7678 return state->min_insn_issue_delay;
7679 state->state_pass_num = curr_state_pass_num;
7680 min_insn_issue_delay = -1;
7681 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7682 if (arc->insn == ainsn)
7684 min_insn_issue_delay = 0;
7685 break;
7687 else
7689 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7690 if (insn_issue_delay != -1)
7692 if (arc->insn->insn_reserv_decl
7693 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7694 insn_issue_delay++;
7695 if (min_insn_issue_delay == -1
7696 || min_insn_issue_delay > insn_issue_delay)
7698 min_insn_issue_delay = insn_issue_delay;
7699 if (insn_issue_delay == 0)
7700 break;
7704 return min_insn_issue_delay;
7707 /* The function searches minimal issue delay value for AINSN in STATE.
7708 The function can return negative value if we can not issue AINSN. We
7709 will report about it later. */
7710 static int
7711 min_issue_delay (state, ainsn)
7712 state_t state;
7713 ainsn_t ainsn;
7715 curr_state_pass_num++;
7716 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7717 return state->min_insn_issue_delay;
7720 /* The function initiates code for finding minimal issue delay values.
7721 It should be called only once. */
7722 static void
7723 initiate_min_issue_delay_pass_states ()
7725 curr_state_pass_num = 0;
7728 /* Form and output vectors representing minimal issue delay table of
7729 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7730 the ainsn. */
7731 static void
7732 output_min_issue_delay_table (automaton)
7733 automaton_t automaton;
7735 vla_hwint_t min_issue_delay_vect;
7736 vla_hwint_t compressed_min_issue_delay_vect;
7737 vect_el_t min_delay;
7738 ainsn_t ainsn;
7739 state_t *state_ptr;
7740 int i;
7742 /* Create vect of pointers to states ordered by num of transitions
7743 from the state (state with the maximum num is the first). */
7744 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7745 pass_states (automaton, add_states_vect_el);
7746 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7747 VLA_HWINT_EXPAND (min_issue_delay_vect,
7748 VLA_HWINT_LENGTH (output_states_vect)
7749 * automaton->insn_equiv_classes_num);
7750 for (i = 0;
7751 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7752 * automaton->insn_equiv_classes_num);
7753 i++)
7754 VLA_HWINT (min_issue_delay_vect, i) = 0;
7755 automaton->max_min_delay = 0;
7756 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7757 if (ainsn->first_ainsn_with_given_equialence_num)
7759 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7760 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7761 state_ptr++)
7762 (*state_ptr)->min_insn_issue_delay = -1;
7763 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7764 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7765 state_ptr++)
7767 min_delay = min_issue_delay (*state_ptr, ainsn);
7768 if (automaton->max_min_delay < min_delay)
7769 automaton->max_min_delay = min_delay;
7770 VLA_HWINT (min_issue_delay_vect,
7771 (*state_ptr)->order_state_num
7772 * automaton->insn_equiv_classes_num
7773 + ainsn->insn_equiv_class_num) = min_delay;
7776 fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
7777 fprintf (output_file, "static const ");
7778 output_range_type (output_file, 0, automaton->max_min_delay);
7779 fprintf (output_file, " ");
7780 output_min_issue_delay_vect_name (output_file, automaton);
7781 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7782 /* Compress the vector */
7783 if (automaton->max_min_delay < 2)
7784 automaton->min_issue_delay_table_compression_factor = 8;
7785 else if (automaton->max_min_delay < 4)
7786 automaton->min_issue_delay_table_compression_factor = 4;
7787 else if (automaton->max_min_delay < 16)
7788 automaton->min_issue_delay_table_compression_factor = 2;
7789 else
7790 automaton->min_issue_delay_table_compression_factor = 1;
7791 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7792 "compressed min issue delay vector");
7793 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7794 (VLA_HWINT_LENGTH (min_issue_delay_vect)
7795 + automaton->min_issue_delay_table_compression_factor
7796 - 1)
7797 / automaton->min_issue_delay_table_compression_factor);
7798 for (i = 0;
7799 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7800 i++)
7801 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7802 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7803 VLA_HWINT (compressed_min_issue_delay_vect,
7804 i / automaton->min_issue_delay_table_compression_factor)
7805 |= (VLA_HWINT (min_issue_delay_vect, i)
7806 << (8 - (i % automaton->min_issue_delay_table_compression_factor
7807 + 1)
7808 * (8 / automaton->min_issue_delay_table_compression_factor)));
7809 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7810 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7811 fprintf (output_file, "};\n\n");
7812 VLA_PTR_DELETE (output_states_vect);
7813 VLA_HWINT_DELETE (min_issue_delay_vect);
7814 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7817 #ifndef NDEBUG
7818 /* Number of states which contains transition only by advancing cpu
7819 cycle. */
7820 static int locked_states_num;
7821 #endif
7823 /* Form and output vector representing the locked states of
7824 AUTOMATON. */
7825 static void
7826 output_dead_lock_vect (automaton)
7827 automaton_t automaton;
7829 state_t *state_ptr;
7830 arc_t arc;
7831 vla_hwint_t dead_lock_vect;
7833 /* Create vect of pointers to states ordered by num of
7834 transitions from the state (state with the maximum num is the
7835 first). */
7836 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7837 pass_states (automaton, add_states_vect_el);
7838 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7839 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7840 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7841 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7842 state_ptr++)
7844 arc = first_out_arc (*state_ptr);
7845 if (arc == NULL)
7846 abort ();
7847 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
7848 = (next_out_arc (arc) == NULL
7849 && (arc->insn->insn_reserv_decl
7850 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
7851 #ifndef NDEBUG
7852 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
7853 locked_states_num++;
7854 #endif
7856 fprintf (output_file, "/* Vector for locked state flags. */\n");
7857 fprintf (output_file, "static const ");
7858 output_range_type (output_file, 0, 1);
7859 fprintf (output_file, " ");
7860 output_dead_lock_vect_name (output_file, automaton);
7861 fprintf (output_file, "[] = {\n");
7862 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
7863 VLA_HWINT_LENGTH (dead_lock_vect));
7864 fprintf (output_file, "};\n\n");
7865 VLA_HWINT_DELETE (dead_lock_vect);
7866 VLA_PTR_DELETE (output_states_vect);
7869 /* Form and output vector representing reserved units of the states of
7870 AUTOMATON. */
7871 static void
7872 output_reserved_units_table (automaton)
7873 automaton_t automaton;
7875 state_t *curr_state_ptr;
7876 vla_hwint_t reserved_units_table;
7877 size_t state_byte_size;
7878 int i;
7880 /* Create vect of pointers to states. */
7881 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7882 pass_states (automaton, add_states_vect_el);
7883 /* Create vector. */
7884 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
7885 state_byte_size = (description->query_units_num + 7) / 8;
7886 VLA_HWINT_EXPAND (reserved_units_table,
7887 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7888 for (i = 0;
7889 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7890 i++)
7891 VLA_HWINT (reserved_units_table, i) = 0;
7892 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
7893 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7894 curr_state_ptr++)
7896 for (i = 0; i < description->units_num; i++)
7897 if (units_array [i]->query_p)
7899 if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i))
7900 VLA_HWINT (reserved_units_table,
7901 (*curr_state_ptr)->order_state_num * state_byte_size
7902 + units_array [i]->query_num / 8)
7903 += (1 << (units_array [i]->query_num % 8));
7906 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7907 fprintf (output_file, "static const ");
7908 output_range_type (output_file, 0, 255);
7909 fprintf (output_file, " ");
7910 output_reserved_units_table_name (output_file, automaton);
7911 fprintf (output_file, "[] = {\n");
7912 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
7913 VLA_HWINT_LENGTH (reserved_units_table));
7914 fprintf (output_file, "};\n\n");
7915 VLA_HWINT_DELETE (reserved_units_table);
7916 VLA_PTR_DELETE (output_states_vect);
7919 /* The function outputs all tables representing DFA(s) used for fast
7920 pipeline hazards recognition. */
7921 static void
7922 output_tables ()
7924 automaton_t automaton;
7926 #ifndef NDEBUG
7927 locked_states_num = 0;
7928 #endif
7929 initiate_min_issue_delay_pass_states ();
7930 for (automaton = description->first_automaton;
7931 automaton != NULL;
7932 automaton = automaton->next_automaton)
7934 output_translate_vect (automaton);
7935 output_trans_table (automaton);
7936 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
7937 output_state_alts_table (automaton);
7938 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7939 AUTOMATON_STATE_ALTS_MACRO_NAME);
7940 output_min_issue_delay_table (automaton);
7941 output_dead_lock_vect (automaton);
7942 if (no_minimization_flag)
7944 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
7945 output_reserved_units_table (automaton);
7946 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7947 CPU_UNITS_QUERY_MACRO_NAME);
7950 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7951 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7954 /* The function outputs definition and value of PHR interface variable
7955 `max_insn_queue_index'. Its value is not less than maximal queue
7956 length needed for the insn scheduler. */
7957 static void
7958 output_max_insn_queue_index_def ()
7960 int i, max, latency;
7961 decl_t decl;
7963 max = description->max_insn_reserv_cycles;
7964 for (i = 0; i < description->decls_num; i++)
7966 decl = description->decls [i];
7967 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7969 latency = DECL_INSN_RESERV (decl)->default_latency;
7970 if (latency > max)
7971 max = latency;
7973 else if (decl->mode == dm_bypass)
7975 latency = DECL_BYPASS (decl)->latency;
7976 if (latency > max)
7977 max = latency;
7980 for (i = 0; (1 << i) <= max; i++)
7982 if (i < 0)
7983 abort ();
7984 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
7988 /* The function outputs switch cases for insn reseravtions using
7989 function *output_automata_list_code. */
7990 static void
7991 output_insn_code_cases (output_automata_list_code)
7992 void (*output_automata_list_code) PARAMS ((automata_list_el_t));
7994 decl_t decl, decl2;
7995 int i, j;
7997 for (i = 0; i < description->decls_num; i++)
7999 decl = description->decls [i];
8000 if (decl->mode == dm_insn_reserv)
8001 DECL_INSN_RESERV (decl)->processed_p = FALSE;
8003 for (i = 0; i < description->decls_num; i++)
8005 decl = description->decls [i];
8006 if (decl->mode == dm_insn_reserv
8007 && !DECL_INSN_RESERV (decl)->processed_p)
8009 for (j = i; j < description->decls_num; j++)
8011 decl2 = description->decls [j];
8012 if (decl2->mode == dm_insn_reserv
8013 && (DECL_INSN_RESERV (decl2)->important_automata_list
8014 == DECL_INSN_RESERV (decl)->important_automata_list))
8016 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8017 fprintf (output_file, " case %d: /* %s */\n",
8018 DECL_INSN_RESERV (decl2)->insn_num,
8019 DECL_INSN_RESERV (decl2)->name);
8022 (*output_automata_list_code)
8023 (DECL_INSN_RESERV (decl)->important_automata_list);
8029 /* The function outputs a code for evaluation of a minimal delay of
8030 issue of insns which have reservations in given AUTOMATA_LIST. */
8031 static void
8032 output_automata_list_min_issue_delay_code (automata_list)
8033 automata_list_el_t automata_list;
8035 automata_list_el_t el;
8036 automaton_t automaton;
8038 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8040 automaton = el->automaton;
8041 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8042 output_min_issue_delay_vect_name (output_file, automaton);
8043 fprintf (output_file,
8044 (automaton->min_issue_delay_table_compression_factor != 1
8045 ? " [(" : " ["));
8046 output_translate_vect_name (output_file, automaton);
8047 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8048 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8049 output_chip_member_name (output_file, automaton);
8050 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8051 if (automaton->min_issue_delay_table_compression_factor == 1)
8052 fprintf (output_file, "];\n");
8053 else
8055 fprintf (output_file, ") / %d];\n",
8056 automaton->min_issue_delay_table_compression_factor);
8057 fprintf (output_file, " %s = (%s >> (8 - (",
8058 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8059 output_translate_vect_name (output_file, automaton);
8060 fprintf
8061 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8062 INTERNAL_INSN_CODE_NAME,
8063 automaton->min_issue_delay_table_compression_factor,
8064 8 / automaton->min_issue_delay_table_compression_factor,
8065 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8066 - 1);
8068 if (el == automata_list)
8069 fprintf (output_file, " %s = %s;\n",
8070 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8071 else
8073 fprintf (output_file, " if (%s > %s)\n",
8074 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8075 fprintf (output_file, " %s = %s;\n",
8076 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8079 fprintf (output_file, " break;\n\n");
8082 /* Output function `internal_min_issue_delay'. */
8083 static void
8084 output_internal_min_issue_delay_func ()
8086 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8087 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
8088 fprintf (output_file,
8089 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8090 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8091 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8092 CHIP_PARAMETER_NAME);
8093 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8094 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8095 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8096 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8097 fprintf (output_file,
8098 "\n default:\n %s = -1;\n break;\n }\n",
8099 RESULT_VARIABLE_NAME);
8100 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8101 fprintf (output_file, "}\n\n");
8104 /* The function outputs a code changing state after issue of insns
8105 which have reservations in given AUTOMATA_LIST. */
8106 static void
8107 output_automata_list_transition_code (automata_list)
8108 automata_list_el_t automata_list;
8110 automata_list_el_t el, next_el;
8112 fprintf (output_file, " {\n");
8113 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8114 for (el = automata_list;; el = next_el)
8116 next_el = el->next_automata_list_el;
8117 if (next_el == NULL)
8118 break;
8119 fprintf (output_file, " ");
8120 output_state_member_type (output_file, el->automaton);
8121 fprintf (output_file, " ");
8122 output_temp_chip_member_name (output_file, el->automaton);
8123 fprintf (output_file, ";\n");
8125 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8126 if (comb_vect_p (el->automaton->trans_table))
8128 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8129 output_trans_base_vect_name (output_file, el->automaton);
8130 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8131 output_chip_member_name (output_file, el->automaton);
8132 fprintf (output_file, "] + ");
8133 output_translate_vect_name (output_file, el->automaton);
8134 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8135 fprintf (output_file, " if (");
8136 output_trans_check_vect_name (output_file, el->automaton);
8137 fprintf (output_file, " [%s] != %s->",
8138 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8139 output_chip_member_name (output_file, el->automaton);
8140 fprintf (output_file, ")\n");
8141 fprintf (output_file, " return %s (%s, %s);\n",
8142 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8143 CHIP_PARAMETER_NAME);
8144 fprintf (output_file, " else\n");
8145 fprintf (output_file, " ");
8146 if (el->next_automata_list_el != NULL)
8147 output_temp_chip_member_name (output_file, el->automaton);
8148 else
8150 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8151 output_chip_member_name (output_file, el->automaton);
8153 fprintf (output_file, " = ");
8154 output_trans_comb_vect_name (output_file, el->automaton);
8155 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8157 else
8159 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8160 output_trans_full_vect_name (output_file, el->automaton);
8161 fprintf (output_file, " [");
8162 output_translate_vect_name (output_file, el->automaton);
8163 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8164 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8165 output_chip_member_name (output_file, el->automaton);
8166 fprintf (output_file, " * %d];\n",
8167 el->automaton->insn_equiv_classes_num);
8168 fprintf (output_file, " if (%s >= %d)\n",
8169 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8170 fprintf (output_file, " return %s (%s, %s);\n",
8171 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8172 CHIP_PARAMETER_NAME);
8173 fprintf (output_file, " else\n ");
8174 if (el->next_automata_list_el != NULL)
8175 output_temp_chip_member_name (output_file, el->automaton);
8176 else
8178 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8179 output_chip_member_name (output_file, el->automaton);
8181 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8183 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8184 for (el = automata_list;; el = next_el)
8186 next_el = el->next_automata_list_el;
8187 if (next_el == NULL)
8188 break;
8189 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8190 output_chip_member_name (output_file, el->automaton);
8191 fprintf (output_file, " = ");
8192 output_temp_chip_member_name (output_file, el->automaton);
8193 fprintf (output_file, ";\n");
8195 fprintf (output_file, " return -1;\n");
8196 fprintf (output_file, " }\n");
8199 /* Output function `internal_state_transition'. */
8200 static void
8201 output_internal_trans_func ()
8203 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8204 INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
8205 fprintf (output_file,
8206 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8207 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8208 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
8209 CHIP_NAME, CHIP_PARAMETER_NAME);
8210 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8211 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8212 output_insn_code_cases (output_automata_list_transition_code);
8213 fprintf (output_file, "\n default:\n return -1;\n }\n");
8214 fprintf (output_file, "}\n\n");
8217 /* Output code
8219 if (insn != 0)
8221 insn_code = dfa_insn_code (insn);
8222 if (insn_code > DFA__ADVANCE_CYCLE)
8223 return code;
8225 else
8226 insn_code = DFA__ADVANCE_CYCLE;
8228 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8229 code denotes CODE. */
8230 static void
8231 output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
8232 const char *insn_name;
8233 const char *insn_code_name;
8234 int code;
8236 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8237 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8238 DFA_INSN_CODE_FUNC_NAME, insn_name);
8239 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8240 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8241 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8242 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8246 /* The function outputs function `dfa_insn_code'. */
8247 static void
8248 output_dfa_insn_code_func ()
8250 fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n");
8251 fprintf (output_file, "static int %s PARAMS ((rtx));\n",
8252 DFA_INSN_CODE_FUNC_NAME);
8253 fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
8254 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
8255 fprintf (output_file, "{\n int %s;\n int %s;\n\n",
8256 INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
8257 fprintf (output_file, " if (INSN_UID (%s) >= %s)\n {\n",
8258 INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8259 fprintf (output_file, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
8260 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8261 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
8262 fprintf (output_file, " %s = xrealloc (%s, %s * sizeof (int));\n",
8263 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8264 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8265 fprintf (output_file,
8266 " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
8267 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8268 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8269 TEMPORARY_VARIABLE_NAME);
8270 fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
8271 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8272 INSN_PARAMETER_NAME);
8273 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8274 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8275 fprintf (output_file, " %s [INSN_UID (%s)] = %s;\n",
8276 DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME,
8277 INTERNAL_INSN_CODE_NAME);
8278 fprintf (output_file, " }\n return %s;\n}\n\n",
8279 INTERNAL_INSN_CODE_NAME);
8282 /* The function outputs PHR interface function `state_transition'. */
8283 static void
8284 output_trans_func ()
8286 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8287 TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8288 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8289 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8290 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8291 INTERNAL_INSN_CODE_NAME, -1);
8292 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8293 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8296 /* The function outputs a code for evaluation of alternative states
8297 number for insns which have reservations in given AUTOMATA_LIST. */
8298 static void
8299 output_automata_list_state_alts_code (automata_list)
8300 automata_list_el_t automata_list;
8302 automata_list_el_t el;
8303 automaton_t automaton;
8305 fprintf (output_file, " {\n");
8306 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8307 if (comb_vect_p (el->automaton->state_alts_table))
8309 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8310 break;
8312 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8314 automaton = el->automaton;
8315 if (comb_vect_p (automaton->state_alts_table))
8317 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8318 output_state_alts_base_vect_name (output_file, automaton);
8319 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8320 output_chip_member_name (output_file, automaton);
8321 fprintf (output_file, "] + ");
8322 output_translate_vect_name (output_file, automaton);
8323 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8324 fprintf (output_file, " if (");
8325 output_state_alts_check_vect_name (output_file, automaton);
8326 fprintf (output_file, " [%s] != %s->",
8327 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8328 output_chip_member_name (output_file, automaton);
8329 fprintf (output_file, ")\n");
8330 fprintf (output_file, " return 0;\n");
8331 fprintf (output_file, " else\n");
8332 fprintf (output_file,
8333 (el == automata_list
8334 ? " %s = " : " %s += "),
8335 RESULT_VARIABLE_NAME);
8336 output_state_alts_comb_vect_name (output_file, automaton);
8337 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8339 else
8341 fprintf (output_file,
8342 (el == automata_list
8343 ? "\n %s = " : " %s += "),
8344 RESULT_VARIABLE_NAME);
8345 output_state_alts_full_vect_name (output_file, automaton);
8346 fprintf (output_file, " [");
8347 output_translate_vect_name (output_file, automaton);
8348 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8349 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8350 output_chip_member_name (output_file, automaton);
8351 fprintf (output_file, " * %d];\n",
8352 automaton->insn_equiv_classes_num);
8355 fprintf (output_file, " break;\n }\n\n");
8358 /* Output function `internal_state_alts'. */
8359 static void
8360 output_internal_state_alts_func ()
8362 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8363 INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8364 fprintf (output_file,
8365 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8366 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8367 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8368 CHIP_PARAMETER_NAME);
8369 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8370 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8371 output_insn_code_cases (output_automata_list_state_alts_code);
8372 fprintf (output_file,
8373 "\n default:\n %s = 0;\n break;\n }\n",
8374 RESULT_VARIABLE_NAME);
8375 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8376 fprintf (output_file, "}\n\n");
8379 /* The function outputs PHR interface function `state_alts'. */
8380 static void
8381 output_state_alts_func ()
8383 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8384 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8385 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8386 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8387 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8388 INTERNAL_INSN_CODE_NAME, 0);
8389 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8390 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8393 /* Output function `min_issue_delay'. */
8394 static void
8395 output_min_issue_delay_func ()
8397 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8398 MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8399 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8400 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8401 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8402 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8403 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8404 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8405 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8406 fprintf (output_file, " }\n else\n %s = %s;\n",
8407 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8408 fprintf (output_file, "\n return %s (%s, %s);\n",
8409 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8410 STATE_NAME);
8411 fprintf (output_file, "}\n\n");
8414 /* Output function `internal_dead_lock'. */
8415 static void
8416 output_internal_dead_lock_func ()
8418 automaton_t automaton;
8420 fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8421 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8422 fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8423 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8424 CHIP_PARAMETER_NAME);
8425 fprintf (output_file, "{\n");
8426 for (automaton = description->first_automaton;
8427 automaton != NULL;
8428 automaton = automaton->next_automaton)
8430 fprintf (output_file, " if (");
8431 output_dead_lock_vect_name (output_file, automaton);
8432 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8433 output_chip_member_name (output_file, automaton);
8434 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8436 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8439 /* The function outputs PHR interface function `state_dead_lock_p'. */
8440 static void
8441 output_dead_lock_func ()
8443 fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8444 DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8445 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8446 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8449 /* Output function `internal_reset'. */
8450 static void
8451 output_internal_reset_func ()
8453 fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8454 INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8455 fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8456 INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8457 CHIP_NAME, CHIP_PARAMETER_NAME);
8458 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8459 CHIP_PARAMETER_NAME, CHIP_NAME);
8462 /* The function outputs PHR interface function `state_size'. */
8463 static void
8464 output_size_func ()
8466 fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8467 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8470 /* The function outputs PHR interface function `state_reset'. */
8471 static void
8472 output_reset_func ()
8474 fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8475 RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8476 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8477 STATE_NAME);
8480 /* Output function `min_insn_conflict_delay'. */
8481 static void
8482 output_min_insn_conflict_delay_func ()
8484 fprintf (output_file,
8485 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8486 MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8487 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8488 STATE_TYPE_NAME, STATE_NAME,
8489 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8490 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8491 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8492 INTERNAL_INSN2_CODE_NAME);
8493 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8494 INTERNAL_INSN_CODE_NAME, 0);
8495 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8496 INTERNAL_INSN2_CODE_NAME, 0);
8497 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8498 CHIP_NAME, STATE_NAME, CHIP_NAME);
8499 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8500 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8501 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8502 fprintf (output_file, " return %s (%s, &%s);\n",
8503 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8504 CHIP_NAME);
8505 fprintf (output_file, "}\n\n");
8508 /* Output function `internal_insn_latency'. */
8509 static void
8510 output_internal_insn_latency_func ()
8512 decl_t decl;
8513 struct bypass_decl *bypass;
8514 int i;
8516 fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8517 INTERNAL_INSN_LATENCY_FUNC_NAME);
8518 fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8519 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8520 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8521 INSN2_PARAMETER_NAME);
8522 fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
8523 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8524 fprintf (output_file,
8525 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
8526 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8527 fprintf (output_file, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8528 for (i = 0; i < description->decls_num; i++)
8530 decl = description->decls [i];
8531 if (decl->mode == dm_insn_reserv)
8533 fprintf (output_file, " case %d:\n",
8534 DECL_INSN_RESERV (decl)->insn_num);
8535 if (DECL_INSN_RESERV (decl)->bypass_list == NULL)
8536 fprintf (output_file, " return (%s != %s ? %d : 0);\n",
8537 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8538 DECL_INSN_RESERV (decl)->default_latency);
8539 else
8541 fprintf (output_file, " switch (%s)\n {\n",
8542 INTERNAL_INSN2_CODE_NAME);
8543 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8544 bypass != NULL;
8545 bypass = bypass->next)
8547 fprintf (output_file, " case %d:\n",
8548 bypass->in_insn_reserv->insn_num);
8549 if (bypass->bypass_guard_name == NULL)
8550 fprintf (output_file, " return %d;\n",
8551 bypass->latency);
8552 else
8553 fprintf (output_file,
8554 " return (%s (%s, %s) ? %d : %d);\n",
8555 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8556 INSN2_PARAMETER_NAME, bypass->latency,
8557 DECL_INSN_RESERV (decl)->default_latency);
8559 fprintf (output_file, " default:\n");
8560 fprintf (output_file,
8561 " return (%s != %s ? %d : 0);\n }\n",
8562 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8563 DECL_INSN_RESERV (decl)->default_latency);
8568 fprintf (output_file, " default:\n return 0;\n }\n}\n\n");
8571 /* The function outputs PHR interface function `insn_latency'. */
8572 static void
8573 output_insn_latency_func ()
8575 fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
8576 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8577 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8578 fprintf (output_file, "{\n int %s, %s;\n",
8579 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8580 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8581 INTERNAL_INSN_CODE_NAME, 0);
8582 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8583 INTERNAL_INSN2_CODE_NAME, 0);
8584 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8585 INTERNAL_INSN_LATENCY_FUNC_NAME,
8586 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8587 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8590 /* The function outputs PHR interface function `print_reservation'. */
8591 static void
8592 output_print_reservation_func ()
8594 decl_t decl;
8595 int i;
8597 fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
8598 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8599 INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
8600 INSN_PARAMETER_NAME);
8601 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8602 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8603 fprintf (output_file, " %s = %s (%s);\n",
8604 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8605 INSN_PARAMETER_NAME);
8606 fprintf (output_file, " if (%s > %s)\n",
8607 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8608 fprintf (output_file, " {\n fprintf (%s, \"%s\");\n",
8609 FILE_PARAMETER_NAME, NOTHING_NAME);
8610 fprintf (output_file, " return;\n }\n");
8611 fprintf (output_file, " }\n else\n");
8612 fprintf (output_file,
8613 " {\n fprintf (%s, \"%s\");\n return;\n }\n",
8614 FILE_PARAMETER_NAME, NOTHING_NAME);
8615 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8616 for (i = 0; i < description->decls_num; i++)
8618 decl = description->decls [i];
8619 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8621 fprintf (output_file,
8622 " case %d:\n", DECL_INSN_RESERV (decl)->insn_num);
8623 fprintf (output_file,
8624 " fprintf (%s, \"%s\");\n break;\n",
8625 FILE_PARAMETER_NAME,
8626 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8627 finish_regexp_representation ();
8630 fprintf (output_file, " default:\n fprintf (%s, \"%s\");\n }\n",
8631 FILE_PARAMETER_NAME, NOTHING_NAME);
8632 fprintf (output_file, "}\n\n");
8635 /* The following function is used to sort unit declaration by their
8636 names. */
8637 static int
8638 units_cmp (unit1, unit2)
8639 const void *unit1, *unit2;
8641 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8642 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8644 return strcmp (u1->name, u2->name);
8647 /* The following macro value is name of struct containing unit name
8648 and unit code. */
8649 #define NAME_CODE_STRUCT_NAME "name_code"
8651 /* The following macro value is name of table of struct name_code. */
8652 #define NAME_CODE_TABLE_NAME "name_code_table"
8654 /* The following macro values are member names for struct name_code. */
8655 #define NAME_MEMBER_NAME "name"
8656 #define CODE_MEMBER_NAME "code"
8658 /* The following macro values are local variable names for function
8659 `get_cpu_unit_code'. */
8660 #define CMP_VARIABLE_NAME "cmp"
8661 #define LOW_VARIABLE_NAME "l"
8662 #define MIDDLE_VARIABLE_NAME "m"
8663 #define HIGH_VARIABLE_NAME "h"
8665 /* The following function outputs function to obtain internal cpu unit
8666 code by the cpu unit name. */
8667 static void
8668 output_get_cpu_unit_code_func ()
8670 int i;
8671 unit_decl_t *units;
8673 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8674 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8675 CPU_UNIT_NAME_PARAMETER_NAME);
8676 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8677 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8678 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8679 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8680 fprintf (output_file, " static struct %s %s [] =\n {\n",
8681 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8682 units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
8683 * description->units_num);
8684 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8685 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8686 for (i = 0; i < description->units_num; i++)
8687 if (units [i]->query_p)
8688 fprintf (output_file, " {\"%s\", %d},\n",
8689 units[i]->name, units[i]->query_num);
8690 fprintf (output_file, " };\n\n");
8691 fprintf (output_file, " /* The following is binary search: */\n");
8692 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8693 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8694 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8695 fprintf (output_file, " while (%s <= %s)\n {\n",
8696 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8697 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8698 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8699 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8700 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8701 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8702 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8703 fprintf (output_file, " %s = %s - 1;\n",
8704 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8705 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8706 fprintf (output_file, " %s = %s + 1;\n",
8707 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8708 fprintf (output_file, " else\n");
8709 fprintf (output_file, " return %s [%s].%s;\n }\n",
8710 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8711 fprintf (output_file, " return -1;\n}\n\n");
8712 free (units);
8715 /* The following function outputs function to check reservation of cpu
8716 unit (its internal code will be passed as the function argument) in
8717 given cpu state. */
8718 static void
8719 output_cpu_unit_reservation_p ()
8721 automaton_t automaton;
8723 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8724 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8725 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8726 CPU_CODE_PARAMETER_NAME);
8727 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8728 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8729 description->query_units_num);
8730 for (automaton = description->first_automaton;
8731 automaton != NULL;
8732 automaton = automaton->next_automaton)
8734 fprintf (output_file, " if ((");
8735 output_reserved_units_table_name (output_file, automaton);
8736 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8737 output_chip_member_name (output_file, automaton);
8738 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8739 (description->query_units_num + 7) / 8,
8740 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8741 fprintf (output_file, " return 1;\n");
8743 fprintf (output_file, " return 0;\n}\n\n");
8746 /* The function outputs PHR interface function `dfa_start'. */
8747 static void
8748 output_dfa_start_func ()
8750 fprintf (output_file,
8751 "void\n%s ()\n{\n int %s;\n\n %s = get_max_uid ();\n",
8752 DFA_START_FUNC_NAME, I_VARIABLE_NAME,
8753 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8754 fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
8755 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8756 fprintf (output_file,
8757 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8758 I_VARIABLE_NAME, I_VARIABLE_NAME,
8759 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8760 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8763 /* The function outputs PHR interface function `dfa_finish'. */
8764 static void
8765 output_dfa_finish_func ()
8767 fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
8768 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8773 /* The page contains code for output description file (readable
8774 representation of original description and generated DFA(s). */
8776 /* The function outputs string representation of IR reservation. */
8777 static void
8778 output_regexp (regexp)
8779 regexp_t regexp;
8781 fprintf (output_description_file, "%s", regexp_representation (regexp));
8782 finish_regexp_representation ();
8785 /* Output names of units in LIST separated by comma. */
8786 static void
8787 output_unit_set_el_list (list)
8788 unit_set_el_t list;
8790 unit_set_el_t el;
8792 for (el = list; el != NULL; el = el->next_unit_set_el)
8794 if (el != list)
8795 fprintf (output_description_file, ",");
8796 fprintf (output_description_file, "%s", el->unit_decl->name);
8800 /* The function outputs string representation of IR define_reservation
8801 and define_insn_reservation. */
8802 static void
8803 output_description ()
8805 decl_t decl;
8806 int i;
8808 for (i = 0; i < description->decls_num; i++)
8810 decl = description->decls [i];
8811 if (decl->mode == dm_unit)
8813 if (DECL_UNIT (decl)->excl_list != NULL)
8815 fprintf (output_description_file, "unit %s exlusion_set: ",
8816 DECL_UNIT (decl)->name);
8817 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8818 fprintf (output_description_file, "\n");
8820 if (DECL_UNIT (decl)->presence_list != NULL)
8822 fprintf (output_description_file, "unit %s presence_set: ",
8823 DECL_UNIT (decl)->name);
8824 output_unit_set_el_list (DECL_UNIT (decl)->presence_list);
8825 fprintf (output_description_file, "\n");
8827 if (DECL_UNIT (decl)->absence_list != NULL)
8829 fprintf (output_description_file, "unit %s absence_set: ",
8830 DECL_UNIT (decl)->name);
8831 output_unit_set_el_list (DECL_UNIT (decl)->absence_list);
8832 fprintf (output_description_file, "\n");
8836 fprintf (output_description_file, "\n");
8837 for (i = 0; i < description->decls_num; i++)
8839 decl = description->decls [i];
8840 if (decl->mode == dm_reserv)
8842 fprintf (output_description_file, "reservation ");
8843 fprintf (output_description_file, DECL_RESERV (decl)->name);
8844 fprintf (output_description_file, ": ");
8845 output_regexp (DECL_RESERV (decl)->regexp);
8846 fprintf (output_description_file, "\n");
8848 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8850 fprintf (output_description_file, "insn reservation %s ",
8851 DECL_INSN_RESERV (decl)->name);
8852 print_rtl (output_description_file,
8853 DECL_INSN_RESERV (decl)->condexp);
8854 fprintf (output_description_file, ": ");
8855 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8856 fprintf (output_description_file, "\n");
8858 else if (decl->mode == dm_bypass)
8859 fprintf (output_description_file, "bypass %d %s %s\n",
8860 DECL_BYPASS (decl)->latency,
8861 DECL_BYPASS (decl)->out_insn_name,
8862 DECL_BYPASS (decl)->in_insn_name);
8864 fprintf (output_description_file, "\n\f\n");
8867 /* The function outputs name of AUTOMATON. */
8868 static void
8869 output_automaton_name (f, automaton)
8870 FILE *f;
8871 automaton_t automaton;
8873 if (automaton->corresponding_automaton_decl == NULL)
8874 fprintf (f, "#%d", automaton->automaton_order_num);
8875 else
8876 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8879 /* Maximal length of line for pretty printing into description
8880 file. */
8881 #define MAX_LINE_LENGTH 70
8883 /* The function outputs units name belonging to AUTOMATON. */
8884 static void
8885 output_automaton_units (automaton)
8886 automaton_t automaton;
8888 decl_t decl;
8889 char *name;
8890 int curr_line_length;
8891 int there_is_an_automaton_unit;
8892 int i;
8894 fprintf (output_description_file, "\n Coresponding units:\n");
8895 fprintf (output_description_file, " ");
8896 curr_line_length = 4;
8897 there_is_an_automaton_unit = 0;
8898 for (i = 0; i < description->decls_num; i++)
8900 decl = description->decls [i];
8901 if (decl->mode == dm_unit
8902 && (DECL_UNIT (decl)->corresponding_automaton_num
8903 == automaton->automaton_order_num))
8905 there_is_an_automaton_unit = 1;
8906 name = DECL_UNIT (decl)->name;
8907 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8909 curr_line_length = strlen (name) + 4;
8910 fprintf (output_description_file, "\n ");
8912 else
8914 curr_line_length += strlen (name) + 1;
8915 fprintf (output_description_file, " ");
8917 fprintf (output_description_file, name);
8920 if (!there_is_an_automaton_unit)
8921 fprintf (output_description_file, "<None>");
8922 fprintf (output_description_file, "\n\n");
8925 /* The following variable is used for forming array of all possible cpu unit
8926 reservations described by the current DFA state. */
8927 static vla_ptr_t state_reservs;
8929 /* The function forms `state_reservs' for STATE. */
8930 static void
8931 add_state_reservs (state)
8932 state_t state;
8934 alt_state_t curr_alt_state;
8935 reserv_sets_t reservs;
8937 if (state->component_states != NULL)
8938 for (curr_alt_state = state->component_states;
8939 curr_alt_state != NULL;
8940 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8941 add_state_reservs (curr_alt_state->state);
8942 else
8944 reservs = state->reservs;
8945 VLA_PTR_ADD (state_reservs, reservs);
8949 /* The function outputs readable representation of all out arcs of
8950 STATE. */
8951 static void
8952 output_state_arcs (state)
8953 state_t state;
8955 arc_t arc;
8956 ainsn_t ainsn;
8957 char *insn_name;
8958 int curr_line_length;
8960 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8962 ainsn = arc->insn;
8963 if (!ainsn->first_insn_with_same_reservs)
8964 abort ();
8965 fprintf (output_description_file, " ");
8966 curr_line_length = 7;
8967 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8970 insn_name = ainsn->insn_reserv_decl->name;
8971 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8973 if (ainsn != arc->insn)
8975 fprintf (output_description_file, ",\n ");
8976 curr_line_length = strlen (insn_name) + 6;
8978 else
8979 curr_line_length += strlen (insn_name);
8981 else
8983 curr_line_length += strlen (insn_name);
8984 if (ainsn != arc->insn)
8986 curr_line_length += 2;
8987 fprintf (output_description_file, ", ");
8990 fprintf (output_description_file, insn_name);
8991 ainsn = ainsn->next_same_reservs_insn;
8993 while (ainsn != NULL);
8994 fprintf (output_description_file, " %d (%d)\n",
8995 arc->to_state->order_state_num, arc->state_alts);
8997 fprintf (output_description_file, "\n");
9000 /* The following function is used for sorting possible cpu unit
9001 reservation of a DFA state. */
9002 static int
9003 state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
9004 const void *reservs_ptr_1;
9005 const void *reservs_ptr_2;
9007 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9008 *(reserv_sets_t *) reservs_ptr_2);
9011 /* The following function is used for sorting possible cpu unit
9012 reservation of a DFA state. */
9013 static void
9014 remove_state_duplicate_reservs ()
9016 reserv_sets_t *reservs_ptr;
9017 reserv_sets_t *last_formed_reservs_ptr;
9019 last_formed_reservs_ptr = NULL;
9020 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9021 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9022 reservs_ptr++)
9023 if (last_formed_reservs_ptr == NULL)
9024 last_formed_reservs_ptr = reservs_ptr;
9025 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9027 ++last_formed_reservs_ptr;
9028 *last_formed_reservs_ptr = *reservs_ptr;
9030 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9033 /* The following function output readable representation of DFA(s)
9034 state used for fast recognition of pipeline hazards. State is
9035 described by possible (current and scheduled) cpu unit
9036 reservations. */
9037 static void
9038 output_state (state)
9039 state_t state;
9041 reserv_sets_t *reservs_ptr;
9043 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9044 fprintf (output_description_file, " State #%d", state->order_state_num);
9045 fprintf (output_description_file,
9046 state->new_cycle_p ? " (new cycle)\n" : "\n");
9047 add_state_reservs (state);
9048 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9049 sizeof (reserv_sets_t), state_reservs_cmp);
9050 remove_state_duplicate_reservs ();
9051 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9052 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9053 reservs_ptr++)
9055 fprintf (output_description_file, " ");
9056 output_reserv_sets (output_description_file, *reservs_ptr);
9057 fprintf (output_description_file, "\n");
9059 fprintf (output_description_file, "\n");
9060 output_state_arcs (state);
9061 VLA_PTR_DELETE (state_reservs);
9064 /* The following function output readable representation of
9065 DFAs used for fast recognition of pipeline hazards. */
9066 static void
9067 output_automaton_descriptions ()
9069 automaton_t automaton;
9071 for (automaton = description->first_automaton;
9072 automaton != NULL;
9073 automaton = automaton->next_automaton)
9075 fprintf (output_description_file, "\nAutomaton ");
9076 output_automaton_name (output_description_file, automaton);
9077 fprintf (output_description_file, "\n");
9078 output_automaton_units (automaton);
9079 pass_states (automaton, output_state);
9085 /* The page contains top level function for generation DFA(s) used for
9086 PHR. */
9088 /* The function outputs statistics about work of different phases of
9089 DFA generator. */
9090 static void
9091 output_statistics (f)
9092 FILE *f;
9094 automaton_t automaton;
9095 #ifndef NDEBUG
9096 int transition_comb_vect_els = 0;
9097 int transition_full_vect_els = 0;
9098 int state_alts_comb_vect_els = 0;
9099 int state_alts_full_vect_els = 0;
9100 int min_issue_delay_vect_els = 0;
9101 #endif
9103 for (automaton = description->first_automaton;
9104 automaton != NULL;
9105 automaton = automaton->next_automaton)
9107 fprintf (f, "\nAutomaton ");
9108 output_automaton_name (f, automaton);
9109 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9110 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9111 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9112 automaton->DFA_states_num, automaton->DFA_arcs_num);
9113 if (!no_minimization_flag)
9114 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9115 automaton->minimal_DFA_states_num,
9116 automaton->minimal_DFA_arcs_num);
9117 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9118 description->insns_num, automaton->insn_equiv_classes_num);
9119 #ifndef NDEBUG
9120 fprintf
9121 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9122 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9123 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9124 (comb_vect_p (automaton->trans_table)
9125 ? "use comb vect" : "use simple vect"));
9126 fprintf
9127 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9128 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9129 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9130 (comb_vect_p (automaton->state_alts_table)
9131 ? "use comb vect" : "use simple vect"));
9132 fprintf
9133 (f, "%5ld min delay table els, compression factor %d\n",
9134 (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num,
9135 automaton->min_issue_delay_table_compression_factor);
9136 transition_comb_vect_els
9137 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9138 transition_full_vect_els
9139 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9140 state_alts_comb_vect_els
9141 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9142 state_alts_full_vect_els
9143 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9144 min_issue_delay_vect_els
9145 += automaton->DFA_states_num * automaton->insn_equiv_classes_num;
9146 #endif
9148 #ifndef NDEBUG
9149 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9150 allocated_states_num, allocated_arcs_num);
9151 fprintf (f, "%5d all allocated alternative states\n",
9152 allocated_alt_states_num);
9153 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9154 transition_comb_vect_els, transition_full_vect_els);
9155 fprintf
9156 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9157 state_alts_comb_vect_els, state_alts_full_vect_els);
9158 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9159 fprintf (f, "%5d locked states num\n", locked_states_num);
9160 #endif
9163 /* The function output times of work of different phases of DFA
9164 generator. */
9165 static void
9166 output_time_statistics (f)
9167 FILE *f;
9169 fprintf (f, "\n transformation: ");
9170 print_active_time (f, transform_time);
9171 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9172 print_active_time (f, NDFA_time);
9173 if (ndfa_flag)
9175 fprintf (f, ", NDFA -> DFA: ");
9176 print_active_time (f, NDFA_to_DFA_time);
9178 fprintf (f, "\n DFA minimization: ");
9179 print_active_time (f, minimize_time);
9180 fprintf (f, ", making insn equivalence: ");
9181 print_active_time (f, equiv_time);
9182 fprintf (f, "\n all automaton generation: ");
9183 print_active_time (f, automaton_generation_time);
9184 fprintf (f, ", output: ");
9185 print_active_time (f, output_time);
9186 fprintf (f, "\n");
9189 /* The function generates DFA (deterministic finite state automaton)
9190 for fast recognition of pipeline hazards. No errors during
9191 checking must be fixed before this function call. */
9192 static void
9193 generate ()
9195 automata_num = split_argument;
9196 if (description->units_num < automata_num)
9197 automata_num = description->units_num;
9198 initiate_states ();
9199 initiate_arcs ();
9200 initiate_automata_lists ();
9201 initiate_pass_states ();
9202 initiate_excl_sets ();
9203 initiate_presence_absence_sets ();
9204 automaton_generation_time = create_ticker ();
9205 create_automata ();
9206 ticker_off (&automaton_generation_time);
9211 /* The following function creates insn attribute whose values are
9212 number alternatives in insn reservations. */
9213 static void
9214 make_insn_alts_attr ()
9216 int i, insn_num;
9217 decl_t decl;
9218 rtx condexp;
9220 condexp = rtx_alloc (COND);
9221 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9222 XEXP (condexp, 1) = make_numeric_value (0);
9223 for (i = insn_num = 0; i < description->decls_num; i++)
9225 decl = description->decls [i];
9226 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9228 XVECEXP (condexp, 0, 2 * insn_num)
9229 = DECL_INSN_RESERV (decl)->condexp;
9230 XVECEXP (condexp, 0, 2 * insn_num + 1)
9231 = make_numeric_value
9232 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9233 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9234 ->transformed_regexp)->regexps_num);
9235 insn_num++;
9238 if (description->insns_num != insn_num + 1)
9239 abort ();
9240 make_internal_attr (attr_printf (sizeof ("*")
9241 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9242 "*%s", INSN_ALTS_FUNC_NAME),
9243 condexp, 0);
9248 /* The following function creates attribute which is order number of
9249 insn in pipeline hazard description translator. */
9250 static void
9251 make_internal_dfa_insn_code_attr ()
9253 int i, insn_num;
9254 decl_t decl;
9255 rtx condexp;
9257 condexp = rtx_alloc (COND);
9258 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9259 XEXP (condexp, 1)
9260 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9261 ->insn_num + 1);
9262 for (i = insn_num = 0; i < description->decls_num; i++)
9264 decl = description->decls [i];
9265 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9267 XVECEXP (condexp, 0, 2 * insn_num)
9268 = DECL_INSN_RESERV (decl)->condexp;
9269 XVECEXP (condexp, 0, 2 * insn_num + 1)
9270 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9271 insn_num++;
9274 if (description->insns_num != insn_num + 1)
9275 abort ();
9276 make_internal_attr
9277 (attr_printf (sizeof ("*")
9278 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9279 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9280 condexp, 0);
9285 /* The following function creates attribute which order number of insn
9286 in pipeline hazard description translator. */
9287 static void
9288 make_default_insn_latency_attr ()
9290 int i, insn_num;
9291 decl_t decl;
9292 rtx condexp;
9294 condexp = rtx_alloc (COND);
9295 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9296 XEXP (condexp, 1) = make_numeric_value (0);
9297 for (i = insn_num = 0; i < description->decls_num; i++)
9299 decl = description->decls [i];
9300 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9302 XVECEXP (condexp, 0, 2 * insn_num)
9303 = DECL_INSN_RESERV (decl)->condexp;
9304 XVECEXP (condexp, 0, 2 * insn_num + 1)
9305 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9306 insn_num++;
9309 if (description->insns_num != insn_num + 1)
9310 abort ();
9311 make_internal_attr (attr_printf (sizeof ("*")
9312 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9313 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9314 condexp, 0);
9319 /* The following function creates attribute which returns 1 if given
9320 output insn has bypassing and 0 otherwise. */
9321 static void
9322 make_bypass_attr ()
9324 int i, bypass_insn;
9325 int bypass_insns_num = 0;
9326 decl_t decl;
9327 rtx result_rtx;
9329 for (i = 0; i < description->decls_num; i++)
9331 decl = description->decls [i];
9332 if (decl->mode == dm_insn_reserv
9333 && DECL_INSN_RESERV (decl)->condexp != NULL
9334 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9335 bypass_insns_num++;
9337 if (bypass_insns_num == 0)
9338 result_rtx = make_numeric_value (0);
9339 else
9341 result_rtx = rtx_alloc (COND);
9342 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9343 XEXP (result_rtx, 1) = make_numeric_value (0);
9345 for (i = bypass_insn = 0; i < description->decls_num; i++)
9347 decl = description->decls [i];
9348 if (decl->mode == dm_insn_reserv
9349 && DECL_INSN_RESERV (decl)->condexp != NULL
9350 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9352 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9353 = DECL_INSN_RESERV (decl)->condexp;
9354 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9355 = make_numeric_value (1);
9356 bypass_insn++;
9360 make_internal_attr (attr_printf (sizeof ("*")
9361 + strlen (BYPASS_P_FUNC_NAME) + 1,
9362 "*%s", BYPASS_P_FUNC_NAME),
9363 result_rtx, 0);
9368 /* This page mainly contains top level functions of pipeline hazards
9369 description translator. */
9371 /* The following macro value is suffix of name of description file of
9372 pipeline hazards description translator. */
9373 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9375 /* The function returns suffix of given file name. The returned
9376 string can not be changed. */
9377 static const char *
9378 file_name_suffix (file_name)
9379 const char *file_name;
9381 const char *last_period;
9383 for (last_period = NULL; *file_name != '\0'; file_name++)
9384 if (*file_name == '.')
9385 last_period = file_name;
9386 return (last_period == NULL ? file_name : last_period);
9389 /* The function returns base name of given file name, i.e. pointer to
9390 first char after last `/' (or `\' for WIN32) in given file name,
9391 given file name itself if the directory name is absent. The
9392 returned string can not be changed. */
9393 static const char *
9394 base_file_name (file_name)
9395 const char *file_name;
9397 int directory_name_length;
9399 directory_name_length = strlen (file_name);
9400 #ifdef WIN32
9401 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9402 && file_name[directory_name_length] != '\\')
9403 #else
9404 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9405 #endif
9406 directory_name_length--;
9407 return file_name + directory_name_length + 1;
9410 /* The following is top level function to initialize the work of
9411 pipeline hazards description translator. */
9412 void
9413 initiate_automaton_gen (argc, argv)
9414 int argc;
9415 char **argv;
9417 const char *base_name;
9418 int i;
9420 ndfa_flag = 0;
9421 split_argument = 0; /* default value */
9422 no_minimization_flag = 0;
9423 time_flag = 0;
9424 v_flag = 0;
9425 w_flag = 0;
9426 for (i = 2; i < argc; i++)
9427 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9428 no_minimization_flag = 1;
9429 else if (strcmp (argv [i], TIME_OPTION) == 0)
9430 time_flag = 1;
9431 else if (strcmp (argv [i], V_OPTION) == 0)
9432 v_flag = 1;
9433 else if (strcmp (argv [i], W_OPTION) == 0)
9434 w_flag = 1;
9435 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9436 ndfa_flag = 1;
9437 else if (strcmp (argv [i], "-split") == 0)
9439 if (i + 1 >= argc)
9440 fatal ("-split has no argument.");
9441 fatal ("option `-split' has not been implemented yet\n");
9442 /* split_argument = atoi (argument_vect [i + 1]); */
9444 VLA_PTR_CREATE (decls, 150, "decls");
9445 /* Initialize IR storage. */
9446 obstack_init (&irp);
9447 initiate_automaton_decl_table ();
9448 initiate_insn_decl_table ();
9449 initiate_decl_table ();
9450 output_file = stdout;
9451 output_description_file = NULL;
9452 base_name = base_file_name (argv[1]);
9453 obstack_grow (&irp, base_name,
9454 strlen (base_name) - strlen (file_name_suffix (base_name)));
9455 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9456 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9457 obstack_1grow (&irp, '\0');
9458 output_description_file_name = obstack_base (&irp);
9459 obstack_finish (&irp);
9462 /* The following function checks existence at least one arc marked by
9463 each insn. */
9464 static void
9465 check_automata_insn_issues ()
9467 automaton_t automaton;
9468 ainsn_t ainsn, reserv_ainsn;
9470 for (automaton = description->first_automaton;
9471 automaton != NULL;
9472 automaton = automaton->next_automaton)
9474 for (ainsn = automaton->ainsn_list;
9475 ainsn != NULL;
9476 ainsn = ainsn->next_ainsn)
9477 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9479 for (reserv_ainsn = ainsn;
9480 reserv_ainsn != NULL;
9481 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9482 if (automaton->corresponding_automaton_decl != NULL)
9484 if (!w_flag)
9485 error ("Automaton `%s': Insn `%s' will never be issued",
9486 automaton->corresponding_automaton_decl->name,
9487 reserv_ainsn->insn_reserv_decl->name);
9488 else
9489 warning
9490 ("Automaton `%s': Insn `%s' will never be issued",
9491 automaton->corresponding_automaton_decl->name,
9492 reserv_ainsn->insn_reserv_decl->name);
9494 else
9496 if (!w_flag)
9497 error ("Insn `%s' will never be issued",
9498 reserv_ainsn->insn_reserv_decl->name);
9499 else
9500 warning ("Insn `%s' will never be issued",
9501 reserv_ainsn->insn_reserv_decl->name);
9507 /* The following vla is used for storing pointers to all achieved
9508 states. */
9509 static vla_ptr_t automaton_states;
9511 /* This function is called by function pass_states to add an achieved
9512 STATE. */
9513 static void
9514 add_automaton_state (state)
9515 state_t state;
9517 VLA_PTR_ADD (automaton_states, state);
9520 /* The following function forms list of important automata (whose
9521 states may be changed after the insn issue) for each insn. */
9522 static void
9523 form_important_insn_automata_lists ()
9525 automaton_t automaton;
9526 state_t *state_ptr;
9527 decl_t decl;
9528 ainsn_t ainsn;
9529 arc_t arc;
9530 int i;
9532 VLA_PTR_CREATE (automaton_states, 1500,
9533 "automaton states for forming important insn automata sets");
9534 /* Mark important ainsns. */
9535 for (automaton = description->first_automaton;
9536 automaton != NULL;
9537 automaton = automaton->next_automaton)
9539 VLA_PTR_NULLIFY (automaton_states);
9540 pass_states (automaton, add_automaton_state);
9541 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9542 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9543 state_ptr++)
9545 for (arc = first_out_arc (*state_ptr);
9546 arc != NULL;
9547 arc = next_out_arc (arc))
9548 if (arc->to_state != *state_ptr)
9550 if (!arc->insn->first_insn_with_same_reservs)
9551 abort ();
9552 for (ainsn = arc->insn;
9553 ainsn != NULL;
9554 ainsn = ainsn->next_same_reservs_insn)
9555 ainsn->important_p = TRUE;
9559 VLA_PTR_DELETE (automaton_states);
9560 /* Create automata sets for the insns. */
9561 for (i = 0; i < description->decls_num; i++)
9563 decl = description->decls [i];
9564 if (decl->mode == dm_insn_reserv)
9566 automata_list_start ();
9567 for (automaton = description->first_automaton;
9568 automaton != NULL;
9569 automaton = automaton->next_automaton)
9570 for (ainsn = automaton->ainsn_list;
9571 ainsn != NULL;
9572 ainsn = ainsn->next_ainsn)
9573 if (ainsn->important_p
9574 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9576 automata_list_add (automaton);
9577 break;
9579 DECL_INSN_RESERV (decl)->important_automata_list
9580 = automata_list_finish ();
9586 /* The following is top level function to generate automat(a,on) for
9587 fast recognition of pipeline hazards. */
9588 void
9589 expand_automata ()
9591 int i;
9593 description = create_node (sizeof (struct description)
9594 /* One entry for cycle advancing insn. */
9595 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9596 description->decls_num = VLA_PTR_LENGTH (decls);
9597 description->query_units_num = 0;
9598 for (i = 0; i < description->decls_num; i++)
9600 description->decls [i] = VLA_PTR (decls, i);
9601 if (description->decls [i]->mode == dm_unit
9602 && DECL_UNIT (description->decls [i])->query_p)
9603 DECL_UNIT (description->decls [i])->query_num
9604 = description->query_units_num++;
9606 all_time = create_ticker ();
9607 check_time = create_ticker ();
9608 fprintf (stderr, "Check description...");
9609 fflush (stderr);
9610 check_all_description ();
9611 fprintf (stderr, "done\n");
9612 ticker_off (&check_time);
9613 generation_time = create_ticker ();
9614 if (!have_error)
9616 transform_insn_regexps ();
9617 check_unit_distributions_to_automata ();
9619 if (!have_error)
9621 generate ();
9622 check_automata_insn_issues ();
9624 if (!have_error)
9626 form_important_insn_automata_lists ();
9627 fprintf (stderr, "Generation of attributes...");
9628 fflush (stderr);
9629 make_internal_dfa_insn_code_attr ();
9630 make_insn_alts_attr ();
9631 make_default_insn_latency_attr ();
9632 make_bypass_attr ();
9633 fprintf (stderr, "done\n");
9635 ticker_off (&generation_time);
9636 ticker_off (&all_time);
9637 fprintf (stderr, "All other genattrtab stuff...");
9638 fflush (stderr);
9641 /* The following is top level function to output PHR and to finish
9642 work with pipeline description translator. */
9643 void
9644 write_automata ()
9646 fprintf (stderr, "done\n");
9647 if (have_error)
9648 fatal ("Errors in DFA description");
9649 ticker_on (&all_time);
9650 output_time = create_ticker ();
9651 fprintf (stderr, "Forming and outputing automata tables...");
9652 fflush (stderr);
9653 output_dfa_max_issue_rate ();
9654 output_tables ();
9655 fprintf (stderr, "done\n");
9656 fprintf (stderr, "Output functions to work with automata...");
9657 fflush (stderr);
9658 output_chip_definitions ();
9659 output_max_insn_queue_index_def ();
9660 output_internal_min_issue_delay_func ();
9661 output_internal_trans_func ();
9662 /* Cache of insn dfa codes: */
9663 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9664 fprintf (output_file, "\nstatic int %s;\n\n",
9665 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9666 output_dfa_insn_code_func ();
9667 output_trans_func ();
9668 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9669 output_internal_state_alts_func ();
9670 output_state_alts_func ();
9671 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9672 AUTOMATON_STATE_ALTS_MACRO_NAME);
9673 output_min_issue_delay_func ();
9674 output_internal_dead_lock_func ();
9675 output_dead_lock_func ();
9676 output_size_func ();
9677 output_internal_reset_func ();
9678 output_reset_func ();
9679 output_min_insn_conflict_delay_func ();
9680 output_internal_insn_latency_func ();
9681 output_insn_latency_func ();
9682 output_print_reservation_func ();
9683 if (no_minimization_flag)
9685 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9686 output_get_cpu_unit_code_func ();
9687 output_cpu_unit_reservation_p ();
9688 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9689 CPU_UNITS_QUERY_MACRO_NAME);
9691 output_dfa_start_func ();
9692 output_dfa_finish_func ();
9693 fprintf (stderr, "done\n");
9694 if (v_flag)
9696 output_description_file = fopen (output_description_file_name, "w");
9697 if (output_description_file == NULL)
9699 perror (output_description_file_name);
9700 exit (FATAL_EXIT_CODE);
9702 fprintf (stderr, "Output automata description...");
9703 fflush (stderr);
9704 output_description ();
9705 output_automaton_descriptions ();
9706 fprintf (stderr, "done\n");
9707 output_statistics (output_description_file);
9709 output_statistics (stderr);
9710 ticker_off (&output_time);
9711 output_time_statistics (stderr);
9712 finish_states ();
9713 finish_arcs ();
9714 finish_automata_lists ();
9715 if (time_flag)
9717 fprintf (stderr, "Summary:\n");
9718 fprintf (stderr, " check time ");
9719 print_active_time (stderr, check_time);
9720 fprintf (stderr, ", generation time ");
9721 print_active_time (stderr, generation_time);
9722 fprintf (stderr, ", all time ");
9723 print_active_time (stderr, all_time);
9724 fprintf (stderr, "\n");
9726 /* Finish all work. */
9727 if (output_description_file != NULL)
9729 fflush (output_description_file);
9730 if (ferror (stdout) != 0)
9731 fatal ("Error in writing DFA description file %s",
9732 output_description_file_name);
9733 fclose (output_description_file);
9735 finish_automaton_decl_table ();
9736 finish_insn_decl_table ();
9737 finish_decl_table ();
9738 obstack_free (&irp, NULL);
9739 if (have_error && output_description_file != NULL)
9740 remove (output_description_file_name);