* config/rs6000/rs6000.c (spe_init_builtins,
[official-gcc.git] / gcc / genautomata.c
blob08f81734574877b5715ebdff8849197727eb453f
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 nondeterministicly 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 "hconfig.h"
104 #include "system.h"
105 #include "rtl.h"
106 #include "obstack.h"
107 #include "errors.h"
109 #include <math.h>
110 #include "hashtab.h"
111 #include "varray.h"
113 #ifndef CHAR_BIT
114 #define CHAR_BIT 8
115 #endif
117 #include "genattrtab.h"
119 /* Positions in machine description file. Now they are not used. But
120 they could be used in the future for better diagnostic messages. */
121 typedef int pos_t;
123 /* The following is element of vector of current (and planned in the
124 future) functional unit reservations. */
125 typedef unsigned HOST_WIDE_INT set_el_t;
127 /* Reservations of function units are represented by value of the following
128 type. */
129 typedef set_el_t *reserv_sets_t;
131 /* The following structure represents variable length array (vla) of
132 pointers and HOST WIDE INTs. We could be use only varray. But we
133 add new lay because we add elements very frequently and this could
134 stress OS allocator when varray is used only. */
135 typedef struct {
136 size_t length; /* current size of vla. */
137 varray_type varray; /* container for vla. */
138 } vla_ptr_t;
140 typedef vla_ptr_t vla_hwint_t;
142 /* The following structure describes a ticker. */
143 struct ticker
145 /* The following member value is time of the ticker creation with
146 taking into account time when the ticker is off. Active time of
147 the ticker is current time minus the value. */
148 int modified_creation_time;
149 /* The following member value is time (incremented by one) when the
150 ticker was off. Zero value means that now the ticker is on. */
151 int incremented_off_time;
154 /* The ticker is represented by the following type. */
155 typedef struct ticker ticker_t;
157 /* The following type describes elements of output vectors. */
158 typedef HOST_WIDE_INT vect_el_t;
160 /* Forward declaration of structures of internal representation of
161 pipeline description based on NDFA. */
163 struct unit_decl;
164 struct bypass_decl;
165 struct result_decl;
166 struct automaton_decl;
167 struct unit_rel_decl;
168 struct reserv_decl;
169 struct insn_reserv_decl;
170 struct decl;
171 struct unit_regexp;
172 struct result_regexp;
173 struct reserv_regexp;
174 struct nothing_regexp;
175 struct sequence_regexp;
176 struct repeat_regexp;
177 struct allof_regexp;
178 struct oneof_regexp;
179 struct regexp;
180 struct description;
181 struct unit_set_el;
182 struct state;
183 struct alt_state;
184 struct arc;
185 struct ainsn;
186 struct automaton;
187 struct state_ainsn_table;
189 /* The following typedefs are for brevity. */
190 typedef struct unit_decl *unit_decl_t;
191 typedef struct decl *decl_t;
192 typedef struct regexp *regexp_t;
193 typedef struct unit_set_el *unit_set_el_t;
194 typedef struct alt_state *alt_state_t;
195 typedef struct state *state_t;
196 typedef struct arc *arc_t;
197 typedef struct ainsn *ainsn_t;
198 typedef struct automaton *automaton_t;
199 typedef struct automata_list_el *automata_list_el_t;
200 typedef struct state_ainsn_table *state_ainsn_table_t;
203 /* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
204 gen_bypass, gen_excl_set, gen_presence_set, gen_absence_set,
205 gen_automaton, gen_automata_option, gen_reserv, gen_insn_reserv,
206 initiate_automaton_gen, expand_automata, write_automata are
207 described on the file top because the functions are called from
208 function `main'. */
210 static void *create_node PARAMS ((size_t));
211 static void *copy_node PARAMS ((const void *, size_t));
212 static char *check_name PARAMS ((char *, pos_t));
213 static char *next_sep_el PARAMS ((char **, int, int));
214 static int n_sep_els PARAMS ((char *, int, int));
215 static char **get_str_vect PARAMS ((char *, int *, int, int));
216 static regexp_t gen_regexp_el PARAMS ((char *));
217 static regexp_t gen_regexp_repeat PARAMS ((char *));
218 static regexp_t gen_regexp_allof PARAMS ((char *));
219 static regexp_t gen_regexp_oneof PARAMS ((char *));
220 static regexp_t gen_regexp_sequence PARAMS ((char *));
221 static regexp_t gen_regexp PARAMS ((char *));
223 static unsigned string_hash PARAMS ((const char *));
224 static unsigned automaton_decl_hash PARAMS ((const void *));
225 static int automaton_decl_eq_p PARAMS ((const void *,
226 const void *));
227 static decl_t insert_automaton_decl PARAMS ((decl_t));
228 static decl_t find_automaton_decl PARAMS ((char *));
229 static void initiate_automaton_decl_table PARAMS ((void));
230 static void finish_automaton_decl_table PARAMS ((void));
232 static unsigned insn_decl_hash PARAMS ((const void *));
233 static int insn_decl_eq_p PARAMS ((const void *,
234 const void *));
235 static decl_t insert_insn_decl PARAMS ((decl_t));
236 static decl_t find_insn_decl PARAMS ((char *));
237 static void initiate_insn_decl_table PARAMS ((void));
238 static void finish_insn_decl_table PARAMS ((void));
240 static unsigned decl_hash PARAMS ((const void *));
241 static int decl_eq_p PARAMS ((const void *,
242 const void *));
243 static decl_t insert_decl PARAMS ((decl_t));
244 static decl_t find_decl PARAMS ((char *));
245 static void initiate_decl_table PARAMS ((void));
246 static void finish_decl_table PARAMS ((void));
248 static unit_set_el_t process_excls PARAMS ((char **, int, pos_t));
249 static void add_excls PARAMS ((unit_set_el_t, unit_set_el_t,
250 pos_t));
251 static unit_set_el_t process_presence_absence
252 PARAMS ((char **, int, pos_t, int));
253 static void add_presence_absence PARAMS ((unit_set_el_t, unit_set_el_t,
254 pos_t, int));
255 static void process_decls PARAMS ((void));
256 static struct bypass_decl *find_bypass PARAMS ((struct bypass_decl *,
257 struct insn_reserv_decl *));
258 static void check_automaton_usage PARAMS ((void));
259 static regexp_t process_regexp PARAMS ((regexp_t));
260 static void process_regexp_decls PARAMS ((void));
261 static void check_usage PARAMS ((void));
262 static int loop_in_regexp PARAMS ((regexp_t, decl_t));
263 static void check_loops_in_regexps PARAMS ((void));
264 static int process_regexp_cycles PARAMS ((regexp_t, int));
265 static void evaluate_max_reserv_cycles PARAMS ((void));
266 static void check_all_description PARAMS ((void));
268 static ticker_t create_ticker PARAMS ((void));
269 static void ticker_off PARAMS ((ticker_t *));
270 static void ticker_on PARAMS ((ticker_t *));
271 static int active_time PARAMS ((ticker_t));
272 static void print_active_time PARAMS ((FILE *, ticker_t));
274 static void add_advance_cycle_insn_decl PARAMS ((void));
276 static alt_state_t get_free_alt_state PARAMS ((void));
277 static void free_alt_state PARAMS ((alt_state_t));
278 static void free_alt_states PARAMS ((alt_state_t));
279 static int alt_state_cmp PARAMS ((const void *alt_state_ptr_1,
280 const void *alt_state_ptr_2));
281 static alt_state_t uniq_sort_alt_states PARAMS ((alt_state_t));
282 static int alt_states_eq PARAMS ((alt_state_t, alt_state_t));
283 static void initiate_alt_states PARAMS ((void));
284 static void finish_alt_states PARAMS ((void));
286 static reserv_sets_t alloc_empty_reserv_sets PARAMS ((void));
287 static unsigned reserv_sets_hash_value PARAMS ((reserv_sets_t));
288 static int reserv_sets_cmp PARAMS ((reserv_sets_t, reserv_sets_t));
289 static int reserv_sets_eq PARAMS ((reserv_sets_t, reserv_sets_t));
290 static void set_unit_reserv PARAMS ((reserv_sets_t, int, int));
291 static int test_unit_reserv PARAMS ((reserv_sets_t, int, int));
292 static int it_is_empty_reserv_sets PARAMS ((reserv_sets_t))
293 ATTRIBUTE_UNUSED;
294 static int reserv_sets_are_intersected PARAMS ((reserv_sets_t, reserv_sets_t));
295 static void reserv_sets_shift PARAMS ((reserv_sets_t, reserv_sets_t));
296 static void reserv_sets_or PARAMS ((reserv_sets_t, reserv_sets_t,
297 reserv_sets_t));
298 static void reserv_sets_and PARAMS ((reserv_sets_t, reserv_sets_t,
299 reserv_sets_t))
300 ATTRIBUTE_UNUSED;
301 static void output_cycle_reservs PARAMS ((FILE *, reserv_sets_t,
302 int, int));
303 static void output_reserv_sets PARAMS ((FILE *, reserv_sets_t));
304 static state_t get_free_state PARAMS ((int, automaton_t));
305 static void free_state PARAMS ((state_t));
306 static unsigned state_hash PARAMS ((const void *));
307 static int state_eq_p PARAMS ((const void *, const void *));
308 static state_t insert_state PARAMS ((state_t));
309 static void set_state_reserv PARAMS ((state_t, int, int));
310 static int intersected_state_reservs_p PARAMS ((state_t, state_t));
311 static state_t states_union PARAMS ((state_t, state_t));
312 static state_t state_shift PARAMS ((state_t));
313 static void initiate_states PARAMS ((void));
314 static void finish_states PARAMS ((void));
316 static void free_arc PARAMS ((arc_t));
317 static void remove_arc PARAMS ((state_t, arc_t));
318 static arc_t find_arc PARAMS ((state_t, state_t, ainsn_t));
319 static arc_t add_arc PARAMS ((state_t, state_t, ainsn_t, int));
320 static arc_t first_out_arc PARAMS ((state_t));
321 static arc_t next_out_arc PARAMS ((arc_t));
322 static void initiate_arcs PARAMS ((void));
323 static void finish_arcs PARAMS ((void));
325 static automata_list_el_t get_free_automata_list_el PARAMS ((void));
326 static void free_automata_list_el PARAMS ((automata_list_el_t));
327 static void free_automata_list PARAMS ((automata_list_el_t));
328 static unsigned automata_list_hash PARAMS ((const void *));
329 static int automata_list_eq_p PARAMS ((const void *, const void *));
330 static void initiate_automata_lists PARAMS ((void));
331 static void automata_list_start PARAMS ((void));
332 static void automata_list_add PARAMS ((automaton_t));
333 static automata_list_el_t automata_list_finish PARAMS ((void));
334 static void finish_automata_lists PARAMS ((void));
336 static void initiate_excl_sets PARAMS ((void));
337 static reserv_sets_t get_excl_set PARAMS ((reserv_sets_t));
339 static void initiate_presence_absence_sets PARAMS ((void));
340 static reserv_sets_t get_presence_absence_set PARAMS ((reserv_sets_t, int));
342 static regexp_t copy_insn_regexp PARAMS ((regexp_t));
343 static regexp_t transform_1 PARAMS ((regexp_t));
344 static regexp_t transform_2 PARAMS ((regexp_t));
345 static regexp_t transform_3 PARAMS ((regexp_t));
346 static regexp_t regexp_transform_func
347 PARAMS ((regexp_t, regexp_t (*) (regexp_t)));
348 static regexp_t transform_regexp PARAMS ((regexp_t));
349 static void transform_insn_regexps PARAMS ((void));
351 static void process_unit_to_form_the_same_automaton_unit_lists
352 PARAMS ((regexp_t, regexp_t, int));
353 static void form_the_same_automaton_unit_lists_from_regexp PARAMS ((regexp_t));
354 static void form_the_same_automaton_unit_lists PARAMS ((void));
355 static void check_unit_distributions_to_automata PARAMS ((void));
357 static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t,
358 int));
359 static void finish_forming_alt_state PARAMS ((alt_state_t,
360 automaton_t));
361 static void process_alts_for_forming_states PARAMS ((regexp_t,
362 automaton_t, int));
363 static void create_alt_states PARAMS ((automaton_t));
365 static void form_ainsn_with_same_reservs PARAMS ((automaton_t));
367 static void make_automaton PARAMS ((automaton_t));
368 static void form_arcs_marked_by_insn PARAMS ((state_t));
369 static void create_composed_state PARAMS ((state_t, arc_t, vla_ptr_t *));
370 static void NDFA_to_DFA PARAMS ((automaton_t));
371 static void pass_state_graph PARAMS ((state_t, void (*) (state_t)));
372 static void pass_states PARAMS ((automaton_t,
373 void (*) (state_t)));
374 static void initiate_pass_states PARAMS ((void));
375 static void add_achieved_state PARAMS ((state_t));
376 static int set_out_arc_insns_equiv_num PARAMS ((state_t, int));
377 static void clear_arc_insns_equiv_num PARAMS ((state_t));
378 static void copy_equiv_class PARAMS ((vla_ptr_t *to,
379 const vla_ptr_t *from));
380 static int state_is_differed PARAMS ((state_t, int, int));
381 static state_t init_equiv_class PARAMS ((state_t *states, int));
382 static int partition_equiv_class PARAMS ((state_t *, int,
383 vla_ptr_t *, int *));
384 static void evaluate_equiv_classes PARAMS ((automaton_t, vla_ptr_t *));
385 static void merge_states PARAMS ((automaton_t, vla_ptr_t *));
386 static void set_new_cycle_flags PARAMS ((state_t));
387 static void minimize_DFA PARAMS ((automaton_t));
388 static void incr_states_and_arcs_nums PARAMS ((state_t));
389 static void count_states_and_arcs PARAMS ((automaton_t, int *, int *));
390 static void build_automaton PARAMS ((automaton_t));
392 static void set_order_state_num PARAMS ((state_t));
393 static void enumerate_states PARAMS ((automaton_t));
395 static ainsn_t insert_ainsn_into_equiv_class PARAMS ((ainsn_t, ainsn_t));
396 static void delete_ainsn_from_equiv_class PARAMS ((ainsn_t));
397 static void process_insn_equiv_class PARAMS ((ainsn_t, arc_t *));
398 static void process_state_for_insn_equiv_partition PARAMS ((state_t));
399 static void set_insn_equiv_classes PARAMS ((automaton_t));
401 static double estimate_one_automaton_bound PARAMS ((void));
402 static int compare_max_occ_cycle_nums PARAMS ((const void *,
403 const void *));
404 static void units_to_automata_heuristic_distr PARAMS ((void));
405 static ainsn_t create_ainsns PARAMS ((void));
406 static void units_to_automata_distr PARAMS ((void));
407 static void create_automata PARAMS ((void));
409 static void form_regexp PARAMS ((regexp_t));
410 static const char *regexp_representation PARAMS ((regexp_t));
411 static void finish_regexp_representation PARAMS ((void));
413 static void output_range_type PARAMS ((FILE *, long int, long int));
414 static int longest_path_length PARAMS ((state_t));
415 static void process_state_longest_path_length PARAMS ((state_t));
416 static void output_dfa_max_issue_rate PARAMS ((void));
417 static void output_vect PARAMS ((vect_el_t *, int));
418 static void output_chip_member_name PARAMS ((FILE *, automaton_t));
419 static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t));
420 static void output_translate_vect_name PARAMS ((FILE *, automaton_t));
421 static void output_trans_full_vect_name PARAMS ((FILE *, automaton_t));
422 static void output_trans_comb_vect_name PARAMS ((FILE *, automaton_t));
423 static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t));
424 static void output_trans_base_vect_name PARAMS ((FILE *, automaton_t));
425 static void output_state_alts_full_vect_name PARAMS ((FILE *, automaton_t));
426 static void output_state_alts_comb_vect_name PARAMS ((FILE *, automaton_t));
427 static void output_state_alts_check_vect_name PARAMS ((FILE *, automaton_t));
428 static void output_state_alts_base_vect_name PARAMS ((FILE *, automaton_t));
429 static void output_min_issue_delay_vect_name PARAMS ((FILE *, automaton_t));
430 static void output_dead_lock_vect_name PARAMS ((FILE *, automaton_t));
431 static void output_reserved_units_table_name PARAMS ((FILE *, automaton_t));
432 static void output_state_member_type PARAMS ((FILE *, automaton_t));
433 static void output_chip_definitions PARAMS ((void));
434 static void output_translate_vect PARAMS ((automaton_t));
435 static int comb_vect_p PARAMS ((state_ainsn_table_t));
436 static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t));
437 static void output_state_ainsn_table
438 PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
439 void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
440 void (*) (FILE *, automaton_t)));
441 static void add_vect PARAMS ((state_ainsn_table_t,
442 int, vect_el_t *, int));
443 static int out_state_arcs_num PARAMS ((state_t));
444 static int compare_transition_els_num PARAMS ((const void *, const void *));
445 static void add_vect_el PARAMS ((vla_hwint_t *,
446 ainsn_t, int));
447 static void add_states_vect_el PARAMS ((state_t));
448 static void output_trans_table PARAMS ((automaton_t));
449 static void output_state_alts_table PARAMS ((automaton_t));
450 static int min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
451 static int min_issue_delay PARAMS ((state_t, ainsn_t));
452 static void initiate_min_issue_delay_pass_states PARAMS ((void));
453 static void output_min_issue_delay_table PARAMS ((automaton_t));
454 static void output_dead_lock_vect PARAMS ((automaton_t));
455 static void output_reserved_units_table PARAMS ((automaton_t));
456 static void output_tables PARAMS ((void));
457 static void output_max_insn_queue_index_def PARAMS ((void));
458 static void output_insn_code_cases PARAMS ((void (*) (automata_list_el_t)));
459 static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
460 static void output_internal_min_issue_delay_func PARAMS ((void));
461 static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
462 static void output_internal_trans_func PARAMS ((void));
463 static void output_internal_insn_code_evaluation PARAMS ((const char *,
464 const char *, int));
465 static void output_dfa_insn_code_func PARAMS ((void));
466 static void output_trans_func PARAMS ((void));
467 static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
468 static void output_internal_state_alts_func PARAMS ((void));
469 static void output_state_alts_func PARAMS ((void));
470 static void output_min_issue_delay_func PARAMS ((void));
471 static void output_internal_dead_lock_func PARAMS ((void));
472 static void output_dead_lock_func PARAMS ((void));
473 static void output_internal_reset_func PARAMS ((void));
474 static void output_size_func PARAMS ((void));
475 static void output_reset_func PARAMS ((void));
476 static void output_min_insn_conflict_delay_func PARAMS ((void));
477 static void output_internal_insn_latency_func PARAMS ((void));
478 static void output_insn_latency_func PARAMS ((void));
479 static void output_print_reservation_func PARAMS ((void));
480 static int units_cmp PARAMS ((const void *,
481 const void *));
482 static void output_get_cpu_unit_code_func PARAMS ((void));
483 static void output_cpu_unit_reservation_p PARAMS ((void));
484 static void output_dfa_start_func PARAMS ((void));
485 static void output_dfa_finish_func PARAMS ((void));
487 static void output_regexp PARAMS ((regexp_t ));
488 static void output_unit_set_el_list PARAMS ((unit_set_el_t));
489 static void output_description PARAMS ((void));
490 static void output_automaton_name PARAMS ((FILE *, automaton_t));
491 static void output_automaton_units PARAMS ((automaton_t));
492 static void add_state_reservs PARAMS ((state_t));
493 static void output_state_arcs PARAMS ((state_t));
494 static int state_reservs_cmp PARAMS ((const void *,
495 const void *));
496 static void remove_state_duplicate_reservs PARAMS ((void));
497 static void output_state PARAMS ((state_t));
498 static void output_automaton_descriptions PARAMS ((void));
499 static void output_statistics PARAMS ((FILE *));
500 static void output_time_statistics PARAMS ((FILE *));
501 static void generate PARAMS ((void));
503 static void make_insn_alts_attr PARAMS ((void));
504 static void make_internal_dfa_insn_code_attr PARAMS ((void));
505 static void make_default_insn_latency_attr PARAMS ((void));
506 static void make_bypass_attr PARAMS ((void));
507 static const char *file_name_suffix PARAMS ((const char *));
508 static const char *base_file_name PARAMS ((const char *));
509 static void check_automata_insn_issues PARAMS ((void));
510 static void add_automaton_state PARAMS ((state_t));
511 static void form_important_insn_automata_lists PARAMS ((void));
513 /* Undefined position. */
514 static pos_t no_pos = 0;
516 /* All IR is stored in the following obstack. */
517 static struct obstack irp;
521 /* This page contains code for work with variable length array (vla)
522 of pointers. We could be use only varray. But we add new lay
523 because we add elements very frequently and this could stress OS
524 allocator when varray is used only. */
526 /* Start work with vla. */
527 #define VLA_PTR_CREATE(vla, allocated_length, name) \
528 do \
530 vla_ptr_t *const vla_ptr = &(vla); \
532 VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\
533 vla_ptr->length = 0; \
535 while (0)
537 /* Finish work with the vla. */
538 #define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
540 /* Return start address of the vla. */
541 #define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
543 /* Address of the last element of the vla. Do not use side effects in
544 the macro argument. */
545 #define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \
546 (vla).length - 1))
547 /* Nullify the vla. */
548 #define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
550 /* Shorten the vla on given number bytes. */
551 #define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
553 /* Expand the vla on N elements. The values of new elements are
554 undefined. */
555 #define VLA_PTR_EXPAND(vla, n) \
556 do { \
557 vla_ptr_t *const expand_vla_ptr = &(vla); \
558 const size_t new_length = (n) + expand_vla_ptr->length; \
560 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
561 VARRAY_GROW (expand_vla_ptr->varray, \
562 (new_length - expand_vla_ptr->length < 128 \
563 ? expand_vla_ptr->length + 128 : new_length)); \
564 expand_vla_ptr->length = new_length; \
565 } while (0)
567 /* Add element to the end of the vla. */
568 #define VLA_PTR_ADD(vla, ptr) \
569 do { \
570 vla_ptr_t *const vla_ptr = &(vla); \
572 VLA_PTR_EXPAND (*vla_ptr, 1); \
573 VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\
574 } while (0)
576 /* Length of the vla in elements. */
577 #define VLA_PTR_LENGTH(vla) ((vla).length)
579 /* N-th element of the vla. */
580 #define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
583 /* The following macros are analogous to the previous ones but for
584 VLAs of HOST WIDE INTs. */
586 #define VLA_HWINT_CREATE(vla, allocated_length, name) \
587 do { \
588 vla_hwint_t *const vla_ptr = &(vla); \
590 VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name); \
591 vla_ptr->length = 0; \
592 } while (0)
594 #define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
596 #define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
598 #define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
600 #define VLA_HWINT_EXPAND(vla, n) \
601 do { \
602 vla_hwint_t *const expand_vla_ptr = &(vla); \
603 const size_t new_length = (n) + expand_vla_ptr->length; \
605 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
606 VARRAY_GROW (expand_vla_ptr->varray, \
607 (new_length - expand_vla_ptr->length < 128 \
608 ? expand_vla_ptr->length + 128 : new_length)); \
609 expand_vla_ptr->length = new_length; \
610 } while (0)
612 #define VLA_HWINT_ADD(vla, ptr) \
613 do { \
614 vla_hwint_t *const vla_ptr = &(vla); \
616 VLA_HWINT_EXPAND (*vla_ptr, 1); \
617 VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr); \
618 } while (0)
620 #define VLA_HWINT_LENGTH(vla) ((vla).length)
622 #define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
626 /* Options with the following names can be set up in automata_option
627 construction. Because the strings occur more one time we use the
628 macros. */
630 #define NO_MINIMIZATION_OPTION "-no-minimization"
632 #define TIME_OPTION "-time"
634 #define V_OPTION "-v"
636 #define W_OPTION "-w"
638 #define NDFA_OPTION "-ndfa"
640 /* The following flags are set up by function `initiate_automaton_gen'. */
642 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
643 static int ndfa_flag;
645 /* Do not make minimization of DFA (`-no-minimization'). */
646 static int no_minimization_flag;
648 /* Value of this variable is number of automata being generated. The
649 actual number of automata may be less this value if there is not
650 sufficient number of units. This value is defined by argument of
651 option `-split' or by constructions automaton if the value is zero
652 (it is default value of the argument). */
653 static int split_argument;
655 /* Flag of output time statistics (`-time'). */
656 static int time_flag;
658 /* Flag of creation of description file which contains description of
659 result automaton and statistics information (`-v'). */
660 static int v_flag;
662 /* Flag of generating warning instead of error for non-critical errors
663 (`-w'). */
664 static int w_flag;
667 /* Output file for pipeline hazard recognizer (PHR) being generated.
668 The value is NULL if the file is not defined. */
669 static FILE *output_file;
671 /* Description file of PHR. The value is NULL if the file is not
672 created. */
673 static FILE *output_description_file;
675 /* PHR description file name. */
676 static char *output_description_file_name;
678 /* Value of the following variable is node representing description
679 being processed. This is start point of IR. */
680 static struct description *description;
684 /* This page contains description of IR structure (nodes). */
686 enum decl_mode
688 dm_unit,
689 dm_bypass,
690 dm_automaton,
691 dm_excl,
692 dm_presence,
693 dm_absence,
694 dm_reserv,
695 dm_insn_reserv
698 /* This describes define_cpu_unit and define_query_cpu_unit (see file
699 rtl.def). */
700 struct unit_decl
702 char *name;
703 /* NULL if the automaton name is absent. */
704 char *automaton_name;
705 /* If the following value is not zero, the cpu unit reservation is
706 described in define_query_cpu_unit. */
707 char query_p;
709 /* The following fields are defined by checker. */
711 /* The following field value is nonzero if the unit is used in an
712 regexp. */
713 char unit_is_used;
715 /* The following field value is used to form cyclic lists of units
716 which should be in the same automaton because the unit is
717 reserved not on all alternatives of a regexp on a cycle. */
718 unit_decl_t the_same_automaton_unit;
719 /* The following field is TRUE if we already reported that the unit
720 is not in the same automaton. */
721 int the_same_automaton_message_reported_p;
723 /* The following field value is order number (0, 1, ...) of given
724 unit. */
725 int unit_num;
726 /* The following field value is corresponding declaration of
727 automaton which was given in description. If the field value is
728 NULL then automaton in the unit declaration was absent. */
729 struct automaton_decl *automaton_decl;
730 /* The following field value is maximal cycle number (1, ...) on
731 which given unit occurs in insns. Zero value means that given
732 unit is not used in insns. */
733 int max_occ_cycle_num;
734 /* The following list contains units which conflict with given
735 unit. */
736 unit_set_el_t excl_list;
737 /* The following list contains units which are required to
738 reservation of given unit. */
739 unit_set_el_t presence_list;
740 /* The following list contains units which should be not present in
741 reservation for given unit. */
742 unit_set_el_t absence_list;
743 /* The following is used only when `query_p' has nonzero value.
744 This is query number for the unit. */
745 int query_num;
747 /* The following fields are defined by automaton generator. */
749 /* The following field value is number of the automaton to which
750 given unit belongs. */
751 int corresponding_automaton_num;
754 /* This describes define_bypass (see file rtl.def). */
755 struct bypass_decl
757 int latency;
758 char *out_insn_name;
759 char *in_insn_name;
760 char *bypass_guard_name;
762 /* The following fields are defined by checker. */
764 /* output and input insns of given bypass. */
765 struct insn_reserv_decl *out_insn_reserv;
766 struct insn_reserv_decl *in_insn_reserv;
767 /* The next bypass for given output insn. */
768 struct bypass_decl *next;
771 /* This describes define_automaton (see file rtl.def). */
772 struct automaton_decl
774 char *name;
776 /* The following fields are defined by automaton generator. */
778 /* The following field value is nonzero if the automaton is used in
779 an regexp definition. */
780 char automaton_is_used;
782 /* The following fields are defined by checker. */
784 /* The following field value is the corresponding automaton. This
785 field is not NULL only if the automaton is present in unit
786 declarations and the automatic partition on automata is not
787 used. */
788 automaton_t corresponding_automaton;
791 /* This describes unit relations: exclusion_set, presence_set, or
792 absence_set (see file rtl.def). */
793 struct unit_rel_decl
795 int names_num;
796 int first_list_length;
797 char *names [1];
800 /* This describes define_reservation (see file rtl.def). */
801 struct reserv_decl
803 char *name;
804 regexp_t regexp;
806 /* The following fields are defined by checker. */
808 /* The following field value is nonzero if the unit is used in an
809 regexp. */
810 char reserv_is_used;
811 /* The following field is used to check up cycle in expression
812 definition. */
813 int loop_pass_num;
816 /* This describes define_insn_reservartion (see file rtl.def). */
817 struct insn_reserv_decl
819 rtx condexp;
820 int default_latency;
821 regexp_t regexp;
822 char *name;
824 /* The following fields are defined by checker. */
826 /* The following field value is order number (0, 1, ...) of given
827 insn. */
828 int insn_num;
829 /* The following field value is list of bypasses in which given insn
830 is output insn. */
831 struct bypass_decl *bypass_list;
833 /* The following fields are defined by automaton generator. */
835 /* The following field is the insn regexp transformed that
836 the regexp has not optional regexp, repetition regexp, and an
837 reservation name (i.e. reservation identifiers are changed by the
838 corresponding regexp) and all alternations are the topest level
839 of the regexp. The value can be NULL only if it is special
840 insn `cycle advancing'. */
841 regexp_t transformed_regexp;
842 /* The following field value is list of arcs marked given
843 insn. The field is used in transfromation NDFA -> DFA. */
844 arc_t arcs_marked_by_insn;
845 /* The two following fields are used during minimization of a finite state
846 automaton. */
847 /* The field value is number of equivalence class of state into
848 which arc marked by given insn enters from a state (fixed during
849 an automaton minimization). */
850 int equiv_class_num;
851 /* The field value is state_alts of arc leaving a state (fixed
852 during an automaton minimization) and marked by given insn
853 enters. */
854 int state_alts;
855 /* The following member value is the list to automata which can be
856 changed by the insn issue. */
857 automata_list_el_t important_automata_list;
858 /* The following member is used to process insn once for output. */
859 int processed_p;
862 /* This contains a declaration mentioned above. */
863 struct decl
865 /* What node in the union? */
866 enum decl_mode mode;
867 pos_t pos;
868 union
870 struct unit_decl unit;
871 struct bypass_decl bypass;
872 struct automaton_decl automaton;
873 struct unit_rel_decl excl;
874 struct unit_rel_decl presence;
875 struct unit_rel_decl absence;
876 struct reserv_decl reserv;
877 struct insn_reserv_decl insn_reserv;
878 } decl;
881 /* The following structures represent parsed reservation strings. */
882 enum regexp_mode
884 rm_unit,
885 rm_reserv,
886 rm_nothing,
887 rm_sequence,
888 rm_repeat,
889 rm_allof,
890 rm_oneof
893 /* Cpu unit in reservation. */
894 struct unit_regexp
896 char *name;
897 unit_decl_t unit_decl;
900 /* Define_reservation in a reservation. */
901 struct reserv_regexp
903 char *name;
904 struct reserv_decl *reserv_decl;
907 /* Absence of reservation (represented by string `nothing'). */
908 struct nothing_regexp
910 /* This used to be empty but ISO C doesn't allow that. */
911 char unused;
914 /* Representation of reservations separated by ',' (see file
915 rtl.def). */
916 struct sequence_regexp
918 int regexps_num;
919 regexp_t regexps [1];
922 /* Representation of construction `repeat' (see file rtl.def). */
923 struct repeat_regexp
925 int repeat_num;
926 regexp_t regexp;
929 /* Representation of reservations separated by '+' (see file
930 rtl.def). */
931 struct allof_regexp
933 int regexps_num;
934 regexp_t regexps [1];
937 /* Representation of reservations separated by '|' (see file
938 rtl.def). */
939 struct oneof_regexp
941 int regexps_num;
942 regexp_t regexps [1];
945 /* Representation of a reservation string. */
946 struct regexp
948 /* What node in the union? */
949 enum regexp_mode mode;
950 pos_t pos;
951 union
953 struct unit_regexp unit;
954 struct reserv_regexp reserv;
955 struct nothing_regexp nothing;
956 struct sequence_regexp sequence;
957 struct repeat_regexp repeat;
958 struct allof_regexp allof;
959 struct oneof_regexp oneof;
960 } regexp;
963 /* Reperesents description of pipeline hazard description based on
964 NDFA. */
965 struct description
967 int decls_num;
969 /* The following fields are defined by checker. */
971 /* The following fields values are correspondingly number of all
972 units, query units, and insns in the description. */
973 int units_num;
974 int query_units_num;
975 int insns_num;
976 /* The following field value is max length (in cycles) of
977 reservations of insns. The field value is defined only for
978 correct programs. */
979 int max_insn_reserv_cycles;
981 /* The following fields are defined by automaton generator. */
983 /* The following field value is the first automaton. */
984 automaton_t first_automaton;
986 /* The following field is created by pipeline hazard parser and
987 contains all declarations. We allocate additional entry for
988 special insn "cycle advancing" which is added by the automaton
989 generator. */
990 decl_t decls [1];
995 /* The following nodes are created in automaton checker. */
997 /* The following nodes represent exclusion, presence, absence set for
998 cpu units. Each element are accessed through only one excl_list,
999 presence_list, absence_list. */
1000 struct unit_set_el
1002 unit_decl_t unit_decl;
1003 unit_set_el_t next_unit_set_el;
1008 /* The following nodes are created in automaton generator. */
1010 /* The following node type describes state automaton. The state may
1011 be deterministic or non-deterministic. Non-deterministic state has
1012 several component states which represent alternative cpu units
1013 reservations. The state also is used for describing a
1014 deterministic reservation of automaton insn. */
1015 struct state
1017 /* The following member value is nonzero if there is a transition by
1018 cycle advancing. */
1019 int new_cycle_p;
1020 /* The following field is list of processor unit reservations on
1021 each cycle. */
1022 reserv_sets_t reservs;
1023 /* The following field is unique number of given state between other
1024 states. */
1025 int unique_num;
1026 /* The following field value is automaton to which given state
1027 belongs. */
1028 automaton_t automaton;
1029 /* The following field value is the first arc output from given
1030 state. */
1031 arc_t first_out_arc;
1032 /* The following field is used to form NDFA. */
1033 char it_was_placed_in_stack_for_NDFA_forming;
1034 /* The following field is used to form DFA. */
1035 char it_was_placed_in_stack_for_DFA_forming;
1036 /* The following field is used to transform NDFA to DFA. The field
1037 value is not NULL if the state is a compound state. In this case
1038 the value of field `unit_sets_list' is NULL. All states in the
1039 list are in the hash table. The list is formed through field
1040 `next_sorted_alt_state'. */
1041 alt_state_t component_states;
1042 /* The following field is used for passing graph of states. */
1043 int pass_num;
1044 /* The list of states belonging to one equivalence class is formed
1045 with the aid of the following field. */
1046 state_t next_equiv_class_state;
1047 /* The two following fields are used during minimization of a finite
1048 state automaton. */
1049 int equiv_class_num_1, equiv_class_num_2;
1050 /* The following field is used during minimization of a finite state
1051 automaton. The field value is state corresponding to equivalence
1052 class to which given state belongs. */
1053 state_t equiv_class_state;
1054 /* The following field value is the order number of given state.
1055 The states in final DFA is enumerated with the aid of the
1056 following field. */
1057 int order_state_num;
1058 /* This member is used for passing states for searching minimal
1059 delay time. */
1060 int state_pass_num;
1061 /* The following member is used to evaluate min issue delay of insn
1062 for a state. */
1063 int min_insn_issue_delay;
1064 /* The following member is used to evaluate max issue rate of the
1065 processor. The value of the member is maximal length of the path
1066 from given state no containing arcs marked by special insn `cycle
1067 advancing'. */
1068 int longest_path_length;
1071 /* The following macro is an initial value of member
1072 `longest_path_length' of a state. */
1073 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1075 /* Automaton arc. */
1076 struct arc
1078 /* The following field refers for the state into which given arc
1079 enters. */
1080 state_t to_state;
1081 /* The following field describes that the insn issue (with cycle
1082 advancing for special insn `cycle advancing' and without cycle
1083 advancing for others) makes transition from given state to
1084 another given state. */
1085 ainsn_t insn;
1086 /* The following field value is the next arc output from the same
1087 state. */
1088 arc_t next_out_arc;
1089 /* List of arcs marked given insn is formed with the following
1090 field. The field is used in transfromation NDFA -> DFA. */
1091 arc_t next_arc_marked_by_insn;
1092 /* The following field is defined if NDFA_FLAG is zero. The member
1093 value is number of alternative reservations which can be used for
1094 transition for given state by given insn. */
1095 int state_alts;
1098 /* The following node type describes a deterministic alternative in
1099 non-deterministic state which characterizes cpu unit reservations
1100 of automaton insn or which is part of NDFA. */
1101 struct alt_state
1103 /* The following field is a determinist state which characterizes
1104 unit reservations of the instruction. */
1105 state_t state;
1106 /* The following field refers to the next state which characterizes
1107 unit reservations of the instruction. */
1108 alt_state_t next_alt_state;
1109 /* The following field refers to the next state in sorted list. */
1110 alt_state_t next_sorted_alt_state;
1113 /* The following node type describes insn of automaton. They are
1114 labels of FA arcs. */
1115 struct ainsn
1117 /* The following field value is the corresponding insn declaration
1118 of description. */
1119 struct insn_reserv_decl *insn_reserv_decl;
1120 /* The following field value is the next insn declaration for an
1121 automaton. */
1122 ainsn_t next_ainsn;
1123 /* The following field is states which characterize automaton unit
1124 reservations of the instruction. The value can be NULL only if it
1125 is special insn `cycle advancing'. */
1126 alt_state_t alt_states;
1127 /* The following field is sorted list of states which characterize
1128 automaton unit reservations of the instruction. The value can be
1129 NULL only if it is special insn `cycle advancing'. */
1130 alt_state_t sorted_alt_states;
1131 /* The following field refers the next automaton insn with
1132 the same reservations. */
1133 ainsn_t next_same_reservs_insn;
1134 /* The following field is flag of the first automaton insn with the
1135 same reservations in the declaration list. Only arcs marked such
1136 insn is present in the automaton. This significantly decreases
1137 memory requirements especially when several automata are
1138 formed. */
1139 char first_insn_with_same_reservs;
1140 /* The following member has nonzero value if there is arc from state of
1141 the automaton marked by the ainsn. */
1142 char arc_exists_p;
1143 /* Cyclic list of insns of an equivalence class is formed with the
1144 aid of the following field. */
1145 ainsn_t next_equiv_class_insn;
1146 /* The following field value is nonzero if the insn declaration is
1147 the first insn declaration with given equivalence number. */
1148 char first_ainsn_with_given_equialence_num;
1149 /* The following field is number of class of equivalence of insns.
1150 It is necessary because many insns may be equivalent with the
1151 point of view of pipeline hazards. */
1152 int insn_equiv_class_num;
1153 /* The following member value is TRUE if there is an arc in the
1154 automaton marked by the insn into another state. In other
1155 words, the insn can change the state of the automaton. */
1156 int important_p;
1159 /* The folowing describes an automaton for PHR. */
1160 struct automaton
1162 /* The following field value is the list of insn declarations for
1163 given automaton. */
1164 ainsn_t ainsn_list;
1165 /* The following field value is the corresponding automaton
1166 declaration. This field is not NULL only if the automatic
1167 partition on automata is not used. */
1168 struct automaton_decl *corresponding_automaton_decl;
1169 /* The following field value is the next automaton. */
1170 automaton_t next_automaton;
1171 /* The following field is start state of FA. There are not unit
1172 reservations in the state. */
1173 state_t start_state;
1174 /* The following field value is number of equivalence classes of
1175 insns (see field `insn_equiv_class_num' in
1176 `insn_reserv_decl'). */
1177 int insn_equiv_classes_num;
1178 /* The following field value is number of states of final DFA. */
1179 int achieved_states_num;
1180 /* The following field value is the order number (0, 1, ...) of
1181 given automaton. */
1182 int automaton_order_num;
1183 /* The following fields contain statistics information about
1184 building automaton. */
1185 int NDFA_states_num, DFA_states_num;
1186 /* The following field value is defined only if minimization of DFA
1187 is used. */
1188 int minimal_DFA_states_num;
1189 int NDFA_arcs_num, DFA_arcs_num;
1190 /* The following field value is defined only if minimization of DFA
1191 is used. */
1192 int minimal_DFA_arcs_num;
1193 /* The following two members refer for two table state x ainsn ->
1194 int. */
1195 state_ainsn_table_t trans_table;
1196 state_ainsn_table_t state_alts_table;
1197 /* The following member value is maximal value of min issue delay
1198 for insns of the automaton. */
1199 int max_min_delay;
1200 /* Usually min issue delay is small and we can place several (2, 4,
1201 8) elements in one vector element. So the compression factor can
1202 be 1 (no compression), 2, 4, 8. */
1203 int min_issue_delay_table_compression_factor;
1206 /* The following is the element of the list of automata. */
1207 struct automata_list_el
1209 /* The automaton itself. */
1210 automaton_t automaton;
1211 /* The next automata set element. */
1212 automata_list_el_t next_automata_list_el;
1215 /* The following structure describes a table state X ainsn -> int(>= 0). */
1216 struct state_ainsn_table
1218 /* Automaton to which given table belongs. */
1219 automaton_t automaton;
1220 /* The following tree vectors for comb vector implementation of the
1221 table. */
1222 vla_hwint_t comb_vect;
1223 vla_hwint_t check_vect;
1224 vla_hwint_t base_vect;
1225 /* This is simple implementation of the table. */
1226 vla_hwint_t full_vect;
1227 /* Minimal and maximal values of the previous vectors. */
1228 int min_comb_vect_el_value, max_comb_vect_el_value;
1229 int min_base_vect_el_value, max_base_vect_el_value;
1232 /* Macros to access members of unions. Use only them for access to
1233 union members of declarations and regexps. */
1235 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1237 #define DECL_UNIT(d) __extension__ \
1238 (({ struct decl *const _decl = (d); \
1239 if (_decl->mode != dm_unit) \
1240 decl_mode_check_failed (_decl->mode, "dm_unit", \
1241 __FILE__, __LINE__, __FUNCTION__); \
1242 &(_decl)->decl.unit; }))
1244 #define DECL_BYPASS(d) __extension__ \
1245 (({ struct decl *const _decl = (d); \
1246 if (_decl->mode != dm_bypass) \
1247 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1248 __FILE__, __LINE__, __FUNCTION__); \
1249 &(_decl)->decl.bypass; }))
1251 #define DECL_AUTOMATON(d) __extension__ \
1252 (({ struct decl *const _decl = (d); \
1253 if (_decl->mode != dm_automaton) \
1254 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1255 __FILE__, __LINE__, __FUNCTION__); \
1256 &(_decl)->decl.automaton; }))
1258 #define DECL_EXCL(d) __extension__ \
1259 (({ struct decl *const _decl = (d); \
1260 if (_decl->mode != dm_excl) \
1261 decl_mode_check_failed (_decl->mode, "dm_excl", \
1262 __FILE__, __LINE__, __FUNCTION__); \
1263 &(_decl)->decl.excl; }))
1265 #define DECL_PRESENCE(d) __extension__ \
1266 (({ struct decl *const _decl = (d); \
1267 if (_decl->mode != dm_presence) \
1268 decl_mode_check_failed (_decl->mode, "dm_presence", \
1269 __FILE__, __LINE__, __FUNCTION__); \
1270 &(_decl)->decl.presence; }))
1272 #define DECL_ABSENCE(d) __extension__ \
1273 (({ struct decl *const _decl = (d); \
1274 if (_decl->mode != dm_absence) \
1275 decl_mode_check_failed (_decl->mode, "dm_absence", \
1276 __FILE__, __LINE__, __FUNCTION__); \
1277 &(_decl)->decl.absence; }))
1279 #define DECL_RESERV(d) __extension__ \
1280 (({ struct decl *const _decl = (d); \
1281 if (_decl->mode != dm_reserv) \
1282 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1283 __FILE__, __LINE__, __FUNCTION__); \
1284 &(_decl)->decl.reserv; }))
1286 #define DECL_INSN_RESERV(d) __extension__ \
1287 (({ struct decl *const _decl = (d); \
1288 if (_decl->mode != dm_insn_reserv) \
1289 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1290 __FILE__, __LINE__, __FUNCTION__); \
1291 &(_decl)->decl.insn_reserv; }))
1293 static const char *decl_name PARAMS ((enum decl_mode));
1294 static void decl_mode_check_failed PARAMS ((enum decl_mode, const char *,
1295 const char *, int, const char *));
1297 /* Return string representation of declaration mode MODE. */
1298 static const char *
1299 decl_name (mode)
1300 enum decl_mode mode;
1302 static char str [100];
1304 if (mode == dm_unit)
1305 return "dm_unit";
1306 else if (mode == dm_bypass)
1307 return "dm_bypass";
1308 else if (mode == dm_automaton)
1309 return "dm_automaton";
1310 else if (mode == dm_excl)
1311 return "dm_excl";
1312 else if (mode == dm_presence)
1313 return "dm_presence";
1314 else if (mode == dm_absence)
1315 return "dm_absence";
1316 else if (mode == dm_reserv)
1317 return "dm_reserv";
1318 else if (mode == dm_insn_reserv)
1319 return "dm_insn_reserv";
1320 else
1321 sprintf (str, "unknown (%d)", (int) mode);
1322 return str;
1325 /* The function prints message about unexpected declaration and finish
1326 the program. */
1327 static void
1328 decl_mode_check_failed (mode, expected_mode_str, file, line, func)
1329 enum decl_mode mode;
1330 const char *expected_mode_str;
1331 const char *file;
1332 int line;
1333 const char *func;
1335 fprintf
1336 (stderr,
1337 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1338 file, line, func, expected_mode_str, decl_name (mode));
1339 exit (1);
1343 #define REGEXP_UNIT(r) __extension__ \
1344 (({ struct regexp *const _regexp = (r); \
1345 if (_regexp->mode != rm_unit) \
1346 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1347 __FILE__, __LINE__, __FUNCTION__); \
1348 &(_regexp)->regexp.unit; }))
1350 #define REGEXP_RESERV(r) __extension__ \
1351 (({ struct regexp *const _regexp = (r); \
1352 if (_regexp->mode != rm_reserv) \
1353 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1354 __FILE__, __LINE__, __FUNCTION__); \
1355 &(_regexp)->regexp.reserv; }))
1357 #define REGEXP_SEQUENCE(r) __extension__ \
1358 (({ struct regexp *const _regexp = (r); \
1359 if (_regexp->mode != rm_sequence) \
1360 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1361 __FILE__, __LINE__, __FUNCTION__); \
1362 &(_regexp)->regexp.sequence; }))
1364 #define REGEXP_REPEAT(r) __extension__ \
1365 (({ struct regexp *const _regexp = (r); \
1366 if (_regexp->mode != rm_repeat) \
1367 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1368 __FILE__, __LINE__, __FUNCTION__); \
1369 &(_regexp)->regexp.repeat; }))
1371 #define REGEXP_ALLOF(r) __extension__ \
1372 (({ struct regexp *const _regexp = (r); \
1373 if (_regexp->mode != rm_allof) \
1374 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1375 __FILE__, __LINE__, __FUNCTION__); \
1376 &(_regexp)->regexp.allof; }))
1378 #define REGEXP_ONEOF(r) __extension__ \
1379 (({ struct regexp *const _regexp = (r); \
1380 if (_regexp->mode != rm_oneof) \
1381 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1382 __FILE__, __LINE__, __FUNCTION__); \
1383 &(_regexp)->regexp.oneof; }))
1385 static const char *regexp_name PARAMS ((enum regexp_mode));
1386 static void regexp_mode_check_failed PARAMS ((enum regexp_mode, const char *,
1387 const char *, int,
1388 const char *));
1391 /* Return string representation of regexp mode MODE. */
1392 static const char *
1393 regexp_name (mode)
1394 enum regexp_mode mode;
1396 static char str [100];
1398 if (mode == rm_unit)
1399 return "rm_unit";
1400 else if (mode == rm_reserv)
1401 return "rm_reserv";
1402 else if (mode == rm_nothing)
1403 return "rm_nothing";
1404 else if (mode == rm_sequence)
1405 return "rm_sequence";
1406 else if (mode == rm_repeat)
1407 return "rm_repeat";
1408 else if (mode == rm_allof)
1409 return "rm_allof";
1410 else if (mode == rm_oneof)
1411 return "rm_oneof";
1412 else
1413 sprintf (str, "unknown (%d)", (int) mode);
1414 return str;
1417 /* The function prints message about unexpected regexp and finish the
1418 program. */
1419 static void
1420 regexp_mode_check_failed (mode, expected_mode_str, file, line, func)
1421 enum regexp_mode mode;
1422 const char *expected_mode_str;
1423 const char *file;
1424 int line;
1425 const char *func;
1427 fprintf
1428 (stderr,
1429 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1430 file, line, func, expected_mode_str, regexp_name (mode));
1431 exit (1);
1434 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1436 #define DECL_UNIT(d) (&(d)->decl.unit)
1437 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1438 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1439 #define DECL_EXCL(d) (&(d)->decl.excl)
1440 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1441 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1442 #define DECL_RESERV(d) (&(d)->decl.reserv)
1443 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1445 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1446 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1447 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1448 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1449 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1450 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1452 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1454 /* Create IR structure (node). */
1455 static void *
1456 create_node (size)
1457 size_t size;
1459 void *result;
1461 obstack_blank (&irp, size);
1462 result = obstack_base (&irp);
1463 obstack_finish (&irp);
1464 /* Default values of members are NULL and zero. */
1465 memset (result, 0, size);
1466 return result;
1469 /* Copy IR structure (node). */
1470 static void *
1471 copy_node (from, size)
1472 const void *from;
1473 size_t size;
1475 void *const result = create_node (size);
1476 memcpy (result, from, size);
1477 return result;
1480 /* The function checks that NAME does not contain quotes (`"'). */
1481 static char *
1482 check_name (name, pos)
1483 char * name;
1484 pos_t pos ATTRIBUTE_UNUSED;
1486 const char *str;
1488 for (str = name; *str != '\0'; str++)
1489 if (*str == '\"')
1490 error ("Name `%s' contains quotes", name);
1491 return name;
1494 /* Pointers top all declartions during IR generation are stored in the
1495 following. */
1496 static vla_ptr_t decls;
1498 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1499 string containing the next separated element, taking parentheses
1500 into account if PAR_FLAG has nonzero value. Advance the pointer to
1501 after the string scanned, or the end-of-string. Return NULL if at
1502 end of string. */
1503 static char *
1504 next_sep_el (pstr, sep, par_flag)
1505 char **pstr;
1506 int sep;
1507 int par_flag;
1509 char *out_str;
1510 char *p;
1511 int pars_num;
1512 int n_spaces;
1514 /* Remove leading whitespaces. */
1515 while (ISSPACE ((int) **pstr))
1516 (*pstr)++;
1518 if (**pstr == '\0')
1519 return NULL;
1521 n_spaces = 0;
1522 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1524 if (par_flag && *p == '(')
1525 pars_num++;
1526 else if (par_flag && *p == ')')
1527 pars_num--;
1528 else if (pars_num == 0 && *p == sep)
1529 break;
1530 if (pars_num == 0 && ISSPACE ((int) *p))
1531 n_spaces++;
1532 else
1534 for (; n_spaces != 0; n_spaces--)
1535 obstack_1grow (&irp, p [-n_spaces]);
1536 obstack_1grow (&irp, *p);
1539 obstack_1grow (&irp, '\0');
1540 out_str = obstack_base (&irp);
1541 obstack_finish (&irp);
1543 *pstr = p;
1544 if (**pstr == sep)
1545 (*pstr)++;
1547 return out_str;
1550 /* Given a string and a separator, return the number of separated
1551 elements in it, taking parentheses into account if PAR_FLAG has
1552 nonzero value. Return 0 for the null string, -1 if parantheses is
1553 not balanced. */
1554 static int
1555 n_sep_els (s, sep, par_flag)
1556 char *s;
1557 int sep;
1558 int par_flag;
1560 int n;
1561 int pars_num;
1563 if (*s == '\0')
1564 return 0;
1566 for (pars_num = 0, n = 1; *s; s++)
1567 if (par_flag && *s == '(')
1568 pars_num++;
1569 else if (par_flag && *s == ')')
1570 pars_num--;
1571 else if (pars_num == 0 && *s == sep)
1572 n++;
1574 return (pars_num != 0 ? -1 : n);
1577 /* Given a string and a separator, return vector of strings which are
1578 elements in the string and number of elements through els_num.
1579 Take parentheses into account if PAR_FLAG has nonzero value.
1580 Return 0 for the null string, -1 if parantheses are not balanced. */
1581 static char **
1582 get_str_vect (str, els_num, sep, par_flag)
1583 char *str;
1584 int *els_num;
1585 int sep;
1586 int par_flag;
1588 int i;
1589 char **vect;
1590 char **pstr;
1592 *els_num = n_sep_els (str, sep, par_flag);
1593 if (*els_num <= 0)
1594 return NULL;
1595 obstack_blank (&irp, sizeof (char *) * (*els_num));
1596 vect = (char **) obstack_base (&irp);
1597 obstack_finish (&irp);
1598 pstr = &str;
1599 for (i = 0; i < *els_num; i++)
1600 vect [i] = next_sep_el (pstr, sep, par_flag);
1601 if (next_sep_el (pstr, sep, par_flag) != NULL)
1602 abort ();
1603 return vect;
1606 /* Process a DEFINE_CPU_UNIT.
1608 This gives information about a unit contained in CPU. We fill a
1609 struct unit_decl with information used later by `expand_automata'. */
1610 void
1611 gen_cpu_unit (def)
1612 rtx def;
1614 decl_t decl;
1615 char **str_cpu_units;
1616 int vect_length;
1617 int i;
1619 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1620 if (str_cpu_units == NULL)
1621 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1622 for (i = 0; i < vect_length; i++)
1624 decl = create_node (sizeof (struct decl));
1625 decl->mode = dm_unit;
1626 decl->pos = 0;
1627 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1628 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1629 DECL_UNIT (decl)->query_p = 0;
1630 VLA_PTR_ADD (decls, decl);
1631 num_dfa_decls++;
1635 /* Process a DEFINE_QUERY_CPU_UNIT.
1637 This gives information about a unit contained in CPU. We fill a
1638 struct unit_decl with information used later by `expand_automata'. */
1639 void
1640 gen_query_cpu_unit (def)
1641 rtx def;
1643 decl_t decl;
1644 char **str_cpu_units;
1645 int vect_length;
1646 int i;
1648 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1649 if (str_cpu_units == NULL)
1650 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1651 for (i = 0; i < vect_length; i++)
1653 decl = create_node (sizeof (struct decl));
1654 decl->mode = dm_unit;
1655 decl->pos = 0;
1656 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1657 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1658 DECL_UNIT (decl)->query_p = 1;
1659 VLA_PTR_ADD (decls, decl);
1660 num_dfa_decls++;
1664 /* Process a DEFINE_BYPASS.
1666 This gives information about a unit contained in the CPU. We fill
1667 in a struct bypass_decl with information used later by
1668 `expand_automata'. */
1669 void
1670 gen_bypass (def)
1671 rtx def;
1673 decl_t decl;
1674 char **out_insns;
1675 int out_length;
1676 char **in_insns;
1677 int in_length;
1678 int i, j;
1680 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', 0);
1681 if (out_insns == NULL)
1682 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1683 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', 0);
1684 if (in_insns == NULL)
1685 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1686 for (i = 0; i < out_length; i++)
1687 for (j = 0; j < in_length; j++)
1689 decl = create_node (sizeof (struct decl));
1690 decl->mode = dm_bypass;
1691 decl->pos = 0;
1692 DECL_BYPASS (decl)->latency = XINT (def, 0);
1693 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1694 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1695 DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
1696 VLA_PTR_ADD (decls, decl);
1697 num_dfa_decls++;
1701 /* Process an EXCLUSION_SET.
1703 This gives information about a cpu unit conflicts. We fill a
1704 struct unit_rel_decl (excl) with information used later by
1705 `expand_automata'. */
1706 void
1707 gen_excl_set (def)
1708 rtx def;
1710 decl_t decl;
1711 char **first_str_cpu_units;
1712 char **second_str_cpu_units;
1713 int first_vect_length;
1714 int length;
1715 int i;
1717 first_str_cpu_units
1718 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1719 if (first_str_cpu_units == NULL)
1720 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1721 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1723 if (second_str_cpu_units == NULL)
1724 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1725 length += first_vect_length;
1726 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1727 decl->mode = dm_excl;
1728 decl->pos = 0;
1729 DECL_EXCL (decl)->names_num = length;
1730 DECL_EXCL (decl)->first_list_length = first_vect_length;
1731 for (i = 0; i < length; i++)
1732 if (i < first_vect_length)
1733 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1734 else
1735 DECL_EXCL (decl)->names [i]
1736 = second_str_cpu_units [i - first_vect_length];
1737 VLA_PTR_ADD (decls, decl);
1738 num_dfa_decls++;
1741 /* Process a PRESENCE_SET.
1743 This gives information about a cpu unit reservation requirements.
1744 We fill a struct unit_rel_decl (presence) with information used
1745 later by `expand_automata'. */
1746 void
1747 gen_presence_set (def)
1748 rtx def;
1750 decl_t decl;
1751 char **first_str_cpu_units;
1752 char **second_str_cpu_units;
1753 int first_vect_length;
1754 int length;
1755 int i;
1757 first_str_cpu_units
1758 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1759 if (first_str_cpu_units == NULL)
1760 fatal ("invalid first string `%s' in presence_set", XSTR (def, 0));
1761 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1763 if (second_str_cpu_units == NULL)
1764 fatal ("invalid second string `%s' in presence_set", XSTR (def, 1));
1765 length += first_vect_length;
1766 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1767 decl->mode = dm_presence;
1768 decl->pos = 0;
1769 DECL_PRESENCE (decl)->names_num = length;
1770 DECL_PRESENCE (decl)->first_list_length = first_vect_length;
1771 for (i = 0; i < length; i++)
1772 if (i < first_vect_length)
1773 DECL_PRESENCE (decl)->names [i] = first_str_cpu_units [i];
1774 else
1775 DECL_PRESENCE (decl)->names [i]
1776 = second_str_cpu_units [i - first_vect_length];
1777 VLA_PTR_ADD (decls, decl);
1778 num_dfa_decls++;
1781 /* Process an ABSENCE_SET.
1783 This gives information about a cpu unit reservation requirements.
1784 We fill a struct unit_rel_decl (absence) with information used
1785 later by `expand_automata'. */
1786 void
1787 gen_absence_set (def)
1788 rtx def;
1790 decl_t decl;
1791 char **first_str_cpu_units;
1792 char **second_str_cpu_units;
1793 int first_vect_length;
1794 int length;
1795 int i;
1797 first_str_cpu_units
1798 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1799 if (first_str_cpu_units == NULL)
1800 fatal ("invalid first string `%s' in absence_set", XSTR (def, 0));
1801 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1803 if (second_str_cpu_units == NULL)
1804 fatal ("invalid second string `%s' in absence_set", XSTR (def, 1));
1805 length += first_vect_length;
1806 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1807 decl->mode = dm_absence;
1808 decl->pos = 0;
1809 DECL_ABSENCE (decl)->names_num = length;
1810 DECL_ABSENCE (decl)->first_list_length = first_vect_length;
1811 for (i = 0; i < length; i++)
1812 if (i < first_vect_length)
1813 DECL_ABSENCE (decl)->names [i] = first_str_cpu_units [i];
1814 else
1815 DECL_ABSENCE (decl)->names [i]
1816 = second_str_cpu_units [i - first_vect_length];
1817 VLA_PTR_ADD (decls, decl);
1818 num_dfa_decls++;
1821 /* Process a DEFINE_AUTOMATON.
1823 This gives information about a finite state automaton used for
1824 recognizing pipeline hazards. We fill a struct automaton_decl
1825 with information used later by `expand_automata'. */
1826 void
1827 gen_automaton (def)
1828 rtx def;
1830 decl_t decl;
1831 char **str_automata;
1832 int vect_length;
1833 int i;
1835 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1836 if (str_automata == NULL)
1837 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1838 for (i = 0; i < vect_length; i++)
1840 decl = create_node (sizeof (struct decl));
1841 decl->mode = dm_automaton;
1842 decl->pos = 0;
1843 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1844 VLA_PTR_ADD (decls, decl);
1845 num_dfa_decls++;
1849 /* Process an AUTOMATA_OPTION.
1851 This gives information how to generate finite state automaton used
1852 for recognizing pipeline hazards. */
1853 void
1854 gen_automata_option (def)
1855 rtx def;
1857 if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1858 no_minimization_flag = 1;
1859 else if (strcmp ((char *) XSTR (def, 0), TIME_OPTION + 1) == 0)
1860 time_flag = 1;
1861 else if (strcmp ((char *) XSTR (def, 0), V_OPTION + 1) == 0)
1862 v_flag = 1;
1863 else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
1864 w_flag = 1;
1865 else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
1866 ndfa_flag = 1;
1867 else
1868 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1871 /* Name in reservation to denote absence reservation. */
1872 #define NOTHING_NAME "nothing"
1874 /* The following string contains original reservation string being
1875 parsed. */
1876 static char *reserv_str;
1878 /* Parse an element in STR. */
1879 static regexp_t
1880 gen_regexp_el (str)
1881 char *str;
1883 regexp_t regexp;
1884 int len;
1886 if (*str == '(')
1888 len = strlen (str);
1889 if (str [len - 1] != ')')
1890 fatal ("garbage after ) in reservation `%s'", reserv_str);
1891 str [len - 1] = '\0';
1892 regexp = gen_regexp_sequence (str + 1);
1894 else if (strcmp (str, NOTHING_NAME) == 0)
1896 regexp = create_node (sizeof (struct decl));
1897 regexp->mode = rm_nothing;
1899 else
1901 regexp = create_node (sizeof (struct decl));
1902 regexp->mode = rm_unit;
1903 REGEXP_UNIT (regexp)->name = str;
1905 return regexp;
1908 /* Parse construction `repeat' in STR. */
1909 static regexp_t
1910 gen_regexp_repeat (str)
1911 char *str;
1913 regexp_t regexp;
1914 regexp_t repeat;
1915 char **repeat_vect;
1916 int els_num;
1917 int i;
1919 repeat_vect = get_str_vect (str, &els_num, '*', 1);
1920 if (repeat_vect == NULL)
1921 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1922 if (els_num > 1)
1924 regexp = gen_regexp_el (repeat_vect [0]);
1925 for (i = 1; i < els_num; i++)
1927 repeat = create_node (sizeof (struct regexp));
1928 repeat->mode = rm_repeat;
1929 REGEXP_REPEAT (repeat)->regexp = regexp;
1930 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1931 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1932 fatal ("repetition `%s' <= 1 in reservation `%s'",
1933 str, reserv_str);
1934 regexp = repeat;
1936 return regexp;
1938 else
1939 return gen_regexp_el (str);
1942 /* Parse reservation STR which possibly contains separator '+'. */
1943 static regexp_t
1944 gen_regexp_allof (str)
1945 char *str;
1947 regexp_t allof;
1948 char **allof_vect;
1949 int els_num;
1950 int i;
1952 allof_vect = get_str_vect (str, &els_num, '+', 1);
1953 if (allof_vect == NULL)
1954 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1955 if (els_num > 1)
1957 allof = create_node (sizeof (struct regexp)
1958 + sizeof (regexp_t) * (els_num - 1));
1959 allof->mode = rm_allof;
1960 REGEXP_ALLOF (allof)->regexps_num = els_num;
1961 for (i = 0; i < els_num; i++)
1962 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1963 return allof;
1965 else
1966 return gen_regexp_repeat (str);
1969 /* Parse reservation STR which possibly contains separator '|'. */
1970 static regexp_t
1971 gen_regexp_oneof (str)
1972 char *str;
1974 regexp_t oneof;
1975 char **oneof_vect;
1976 int els_num;
1977 int i;
1979 oneof_vect = get_str_vect (str, &els_num, '|', 1);
1980 if (oneof_vect == NULL)
1981 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1982 if (els_num > 1)
1984 oneof = create_node (sizeof (struct regexp)
1985 + sizeof (regexp_t) * (els_num - 1));
1986 oneof->mode = rm_oneof;
1987 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1988 for (i = 0; i < els_num; i++)
1989 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1990 return oneof;
1992 else
1993 return gen_regexp_allof (str);
1996 /* Parse reservation STR which possibly contains separator ','. */
1997 static regexp_t
1998 gen_regexp_sequence (str)
1999 char *str;
2001 regexp_t sequence;
2002 char **sequence_vect;
2003 int els_num;
2004 int i;
2006 sequence_vect = get_str_vect (str, &els_num, ',', 1);
2007 if (els_num > 1)
2009 sequence = create_node (sizeof (struct regexp)
2010 + sizeof (regexp_t) * (els_num - 1));
2011 sequence->mode = rm_sequence;
2012 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2013 for (i = 0; i < els_num; i++)
2014 REGEXP_SEQUENCE (sequence)->regexps [i]
2015 = gen_regexp_oneof (sequence_vect [i]);
2016 return sequence;
2018 else
2019 return gen_regexp_oneof (str);
2022 /* Parse construction reservation STR. */
2023 static regexp_t
2024 gen_regexp (str)
2025 char *str;
2027 reserv_str = str;
2028 return gen_regexp_sequence (str);;
2031 /* Process a DEFINE_RESERVATION.
2033 This gives information about a reservation of cpu units. We fill
2034 in a struct reserv_decl with information used later by
2035 `expand_automata'. */
2036 void
2037 gen_reserv (def)
2038 rtx def;
2040 decl_t decl;
2042 decl = create_node (sizeof (struct decl));
2043 decl->mode = dm_reserv;
2044 decl->pos = 0;
2045 DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2046 DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2047 VLA_PTR_ADD (decls, decl);
2048 num_dfa_decls++;
2051 /* Process a DEFINE_INSN_RESERVATION.
2053 This gives information about the reservation of cpu units by an
2054 insn. We fill a struct insn_reserv_decl with information used
2055 later by `expand_automata'. */
2056 void
2057 gen_insn_reserv (def)
2058 rtx def;
2060 decl_t decl;
2062 decl = create_node (sizeof (struct decl));
2063 decl->mode = dm_insn_reserv;
2064 decl->pos = 0;
2065 DECL_INSN_RESERV (decl)->name
2066 = check_name ((char *) XSTR (def, 0), decl->pos);
2067 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2068 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2069 DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2070 VLA_PTR_ADD (decls, decl);
2071 num_dfa_decls++;
2076 /* The function evaluates hash value (0..UINT_MAX) of string. */
2077 static unsigned
2078 string_hash (string)
2079 const char *string;
2081 unsigned result, i;
2083 for (result = i = 0;*string++ != '\0'; i++)
2084 result += ((unsigned char) *string << (i % CHAR_BIT));
2085 return result;
2090 /* This page contains abstract data `table of automaton declarations'.
2091 Elements of the table is nodes representing automaton declarations.
2092 Key of the table elements is name of given automaton. Rememeber
2093 that automaton names have own space. */
2095 /* The function evaluates hash value of an automaton declaration. The
2096 function is used by abstract data `hashtab'. The function returns
2097 hash value (0..UINT_MAX) of given automaton declaration. */
2098 static unsigned
2099 automaton_decl_hash (automaton_decl)
2100 const void *automaton_decl;
2102 const decl_t decl = (decl_t) automaton_decl;
2104 if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
2105 abort ();
2106 return string_hash (DECL_AUTOMATON (decl)->name);
2109 /* The function tests automaton declarations on equality of their
2110 keys. The function is used by abstract data `hashtab'. The
2111 function returns 1 if the declarations have the same key, 0
2112 otherwise. */
2113 static int
2114 automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
2115 const void* automaton_decl_1;
2116 const void* automaton_decl_2;
2118 const decl_t decl1 = (decl_t) automaton_decl_1;
2119 const decl_t decl2 = (decl_t) automaton_decl_2;
2121 if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
2122 || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
2123 abort ();
2124 return strcmp (DECL_AUTOMATON (decl1)->name,
2125 DECL_AUTOMATON (decl2)->name) == 0;
2128 /* The automaton declaration table itself is represented by the
2129 following variable. */
2130 static htab_t automaton_decl_table;
2132 /* The function inserts automaton declaration into the table. The
2133 function does nothing if an automaton declaration with the same key
2134 exists already in the table. The function returns automaton
2135 declaration node in the table with the same key as given automaton
2136 declaration node. */
2137 static decl_t
2138 insert_automaton_decl (automaton_decl)
2139 decl_t automaton_decl;
2141 void **entry_ptr;
2143 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
2144 if (*entry_ptr == NULL)
2145 *entry_ptr = (void *) automaton_decl;
2146 return (decl_t) *entry_ptr;
2149 /* The following variable value is node representing automaton
2150 declaration. The node used for searching automaton declaration
2151 with given name. */
2152 static struct decl work_automaton_decl;
2154 /* The function searches for automaton declaration in the table with
2155 the same key as node representing name of the automaton
2156 declaration. The function returns node found in the table, NULL if
2157 such node does not exist in the table. */
2158 static decl_t
2159 find_automaton_decl (name)
2160 char *name;
2162 void *entry;
2164 work_automaton_decl.mode = dm_automaton;
2165 DECL_AUTOMATON (&work_automaton_decl)->name = name;
2166 entry = htab_find (automaton_decl_table, &work_automaton_decl);
2167 return (decl_t) entry;
2170 /* The function creates empty automaton declaration table and node
2171 representing automaton declaration and used for searching automaton
2172 declaration with given name. The function must be called only once
2173 before any work with the automaton declaration table. */
2174 static void
2175 initiate_automaton_decl_table ()
2177 work_automaton_decl.mode = dm_automaton;
2178 automaton_decl_table = htab_create (10, automaton_decl_hash,
2179 automaton_decl_eq_p, (htab_del) 0);
2182 /* The function deletes the automaton declaration table. Only call of
2183 function `initiate_automaton_decl_table' is possible immediately
2184 after this function call. */
2185 static void
2186 finish_automaton_decl_table ()
2188 htab_delete (automaton_decl_table);
2193 /* This page contains abstract data `table of insn declarations'.
2194 Elements of the table is nodes representing insn declarations. Key
2195 of the table elements is name of given insn (in corresponding
2196 define_insn_reservation). Rememeber that insn names have own
2197 space. */
2199 /* The function evaluates hash value of an insn declaration. The
2200 function is used by abstract data `hashtab'. The function returns
2201 hash value (0..UINT_MAX) of given insn declaration. */
2202 static unsigned
2203 insn_decl_hash (insn_decl)
2204 const void *insn_decl;
2206 const decl_t decl = (decl_t) insn_decl;
2208 if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
2209 abort ();
2210 return string_hash (DECL_INSN_RESERV (decl)->name);
2213 /* The function tests insn declarations on equality of their keys.
2214 The function is used by abstract data `hashtab'. The function
2215 returns 1 if declarations have the same key, 0 otherwise. */
2216 static int
2217 insn_decl_eq_p (insn_decl_1, insn_decl_2)
2218 const void *insn_decl_1;
2219 const void *insn_decl_2;
2221 const decl_t decl1 = (decl_t) insn_decl_1;
2222 const decl_t decl2 = (decl_t) insn_decl_2;
2224 if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
2225 || decl2->mode != dm_insn_reserv
2226 || DECL_INSN_RESERV (decl2)->name == NULL)
2227 abort ();
2228 return strcmp (DECL_INSN_RESERV (decl1)->name,
2229 DECL_INSN_RESERV (decl2)->name) == 0;
2232 /* The insn declaration table itself is represented by the following
2233 variable. The table does not contain insn reservation
2234 declarations. */
2235 static htab_t insn_decl_table;
2237 /* The function inserts insn declaration into the table. The function
2238 does nothing if an insn declaration with the same key exists
2239 already in the table. The function returns insn declaration node
2240 in the table with the same key as given insn declaration node. */
2241 static decl_t
2242 insert_insn_decl (insn_decl)
2243 decl_t insn_decl;
2245 void **entry_ptr;
2247 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2248 if (*entry_ptr == NULL)
2249 *entry_ptr = (void *) insn_decl;
2250 return (decl_t) *entry_ptr;
2253 /* The following variable value is node representing insn reservation
2254 declaration. The node used for searching insn reservation
2255 declaration with given name. */
2256 static struct decl work_insn_decl;
2258 /* The function searches for insn reservation declaration in the table
2259 with the same key as node representing name of the insn reservation
2260 declaration. The function returns node found in the table, NULL if
2261 such node does not exist in the table. */
2262 static decl_t
2263 find_insn_decl (name)
2264 char *name;
2266 void *entry;
2268 work_insn_decl.mode = dm_insn_reserv;
2269 DECL_INSN_RESERV (&work_insn_decl)->name = name;
2270 entry = htab_find (insn_decl_table, &work_insn_decl);
2271 return (decl_t) entry;
2274 /* The function creates empty insn declaration table and node
2275 representing insn declaration and used for searching insn
2276 declaration with given name. The function must be called only once
2277 before any work with the insn declaration table. */
2278 static void
2279 initiate_insn_decl_table ()
2281 work_insn_decl.mode = dm_insn_reserv;
2282 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2283 (htab_del) 0);
2286 /* The function deletes the insn declaration table. Only call of
2287 function `initiate_insn_decl_table' is possible immediately after
2288 this function call. */
2289 static void
2290 finish_insn_decl_table ()
2292 htab_delete (insn_decl_table);
2297 /* This page contains abstract data `table of declarations'. Elements
2298 of the table is nodes representing declarations (of units and
2299 reservations). Key of the table elements is names of given
2300 declarations. */
2302 /* The function evaluates hash value of a declaration. The function
2303 is used by abstract data `hashtab'. The function returns hash
2304 value (0..UINT_MAX) of given declaration. */
2305 static unsigned
2306 decl_hash (decl)
2307 const void *decl;
2309 const decl_t d = (const decl_t) decl;
2311 if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
2312 && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
2313 abort ();
2314 return string_hash (d->mode == dm_unit
2315 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
2318 /* The function tests declarations on equality of their keys. The
2319 function is used by abstract data `hashtab'. The function
2320 returns 1 if the declarations have the same key, 0 otherwise. */
2321 static int
2322 decl_eq_p (decl_1, decl_2)
2323 const void *decl_1;
2324 const void *decl_2;
2326 const decl_t d1 = (const decl_t) decl_1;
2327 const decl_t d2 = (const decl_t) decl_2;
2329 if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
2330 && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
2331 || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
2332 && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
2333 abort ();
2334 return strcmp ((d1->mode == dm_unit
2335 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
2336 (d2->mode == dm_unit
2337 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2340 /* The declaration table itself is represented by the following
2341 variable. */
2342 static htab_t decl_table;
2344 /* The function inserts declaration into the table. The function does
2345 nothing if a declaration with the same key exists already in the
2346 table. The function returns declaration node in the table with the
2347 same key as given declaration node. */
2349 static decl_t
2350 insert_decl (decl)
2351 decl_t decl;
2353 void **entry_ptr;
2355 entry_ptr = htab_find_slot (decl_table, decl, 1);
2356 if (*entry_ptr == NULL)
2357 *entry_ptr = (void *) decl;
2358 return (decl_t) *entry_ptr;
2361 /* The following variable value is node representing declaration. The
2362 node used for searching declaration with given name. */
2363 static struct decl work_decl;
2365 /* The function searches for declaration in the table with the same
2366 key as node representing name of the declaration. The function
2367 returns node found in the table, NULL if such node does not exist
2368 in the table. */
2369 static decl_t
2370 find_decl (name)
2371 char *name;
2373 void *entry;
2375 work_decl.mode = dm_unit;
2376 DECL_UNIT (&work_decl)->name = name;
2377 entry = htab_find (decl_table, &work_decl);
2378 return (decl_t) entry;
2381 /* The function creates empty declaration table and node representing
2382 declaration and used for searching declaration with given name.
2383 The function must be called only once before any work with the
2384 declaration table. */
2385 static void
2386 initiate_decl_table ()
2388 work_decl.mode = dm_unit;
2389 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2392 /* The function deletes the declaration table. Only call of function
2393 `initiate_declaration_table' is possible immediately after this
2394 function call. */
2395 static void
2396 finish_decl_table ()
2398 htab_delete (decl_table);
2403 /* This page contains checker of pipeline hazard description. */
2405 /* Checking NAMES in an exclusion clause vector and returning formed
2406 unit_set_el_list. */
2407 static unit_set_el_t
2408 process_excls (names, num, excl_pos)
2409 char **names;
2410 int num;
2411 pos_t excl_pos ATTRIBUTE_UNUSED;
2413 unit_set_el_t el_list;
2414 unit_set_el_t last_el;
2415 unit_set_el_t new_el;
2416 decl_t decl_in_table;
2417 int i;
2419 el_list = NULL;
2420 last_el = NULL;
2421 for (i = 0; i < num; i++)
2423 decl_in_table = find_decl (names [i]);
2424 if (decl_in_table == NULL)
2425 error ("unit `%s' in exclusion is not declared", names [i]);
2426 else if (decl_in_table->mode != dm_unit)
2427 error ("`%s' in exclusion is not unit", names [i]);
2428 else
2430 new_el = create_node (sizeof (struct unit_set_el));
2431 new_el->unit_decl = DECL_UNIT (decl_in_table);
2432 new_el->next_unit_set_el = NULL;
2433 if (last_el == NULL)
2434 el_list = last_el = new_el;
2435 else
2437 last_el->next_unit_set_el = new_el;
2438 last_el = last_el->next_unit_set_el;
2442 return el_list;
2445 /* The function adds each element from SOURCE_LIST to the exclusion
2446 list of the each element from DEST_LIST. Checking situation "unit
2447 excludes itself". */
2448 static void
2449 add_excls (dest_list, source_list, excl_pos)
2450 unit_set_el_t dest_list;
2451 unit_set_el_t source_list;
2452 pos_t excl_pos ATTRIBUTE_UNUSED;
2454 unit_set_el_t dst;
2455 unit_set_el_t src;
2456 unit_set_el_t curr_el;
2457 unit_set_el_t prev_el;
2458 unit_set_el_t copy;
2460 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2461 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2463 if (dst->unit_decl == src->unit_decl)
2465 error ("unit `%s' excludes itself", src->unit_decl->name);
2466 continue;
2468 if (dst->unit_decl->automaton_name != NULL
2469 && src->unit_decl->automaton_name != NULL
2470 && strcmp (dst->unit_decl->automaton_name,
2471 src->unit_decl->automaton_name) != 0)
2473 error ("units `%s' and `%s' in exclusion set belong to different automata",
2474 src->unit_decl->name, dst->unit_decl->name);
2475 continue;
2477 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2478 curr_el != NULL;
2479 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2480 if (curr_el->unit_decl == src->unit_decl)
2481 break;
2482 if (curr_el == NULL)
2484 /* Element not found - insert. */
2485 copy = copy_node (src, sizeof (*src));
2486 copy->next_unit_set_el = NULL;
2487 if (prev_el == NULL)
2488 dst->unit_decl->excl_list = copy;
2489 else
2490 prev_el->next_unit_set_el = copy;
2495 /* Checking NAMES in an presence clause vector and returning formed
2496 unit_set_el_list. The function is called only after processing all
2497 exclusion sets. */
2498 static unit_set_el_t
2499 process_presence_absence (names, num, req_pos, presence_p)
2500 char **names;
2501 int num;
2502 pos_t req_pos ATTRIBUTE_UNUSED;
2503 int presence_p;
2505 unit_set_el_t el_list;
2506 unit_set_el_t last_el;
2507 unit_set_el_t new_el;
2508 decl_t decl_in_table;
2509 int i;
2511 el_list = NULL;
2512 last_el = NULL;
2513 for (i = 0; i < num; i++)
2515 decl_in_table = find_decl (names [i]);
2516 if (decl_in_table == NULL)
2517 error ((presence_p
2518 ? "unit `%s' in presence set is not declared"
2519 : "unit `%s' in absence set is not declared"), names [i]);
2520 else if (decl_in_table->mode != dm_unit)
2521 error ((presence_p
2522 ? "`%s' in presence set is not unit"
2523 : "`%s' in absence set is not unit"), names [i]);
2524 else
2526 new_el = create_node (sizeof (struct unit_set_el));
2527 new_el->unit_decl = DECL_UNIT (decl_in_table);
2528 new_el->next_unit_set_el = NULL;
2529 if (last_el == NULL)
2530 el_list = last_el = new_el;
2531 else
2533 last_el->next_unit_set_el = new_el;
2534 last_el = last_el->next_unit_set_el;
2538 return el_list;
2541 /* The function adds each element from SOURCE_LIST to presence (if
2542 PRESENCE_P) or absence list of the each element from DEST_LIST.
2543 Checking situations "unit requires own presence", "unit requires
2544 own absence", and "unit excludes and requires presence of ...".
2545 Remember that we process absence sets only after all presence
2546 sets. */
2547 static void
2548 add_presence_absence (dest_list, source_list, req_pos, presence_p)
2549 unit_set_el_t dest_list;
2550 unit_set_el_t source_list;
2551 pos_t req_pos ATTRIBUTE_UNUSED;
2552 int presence_p;
2554 unit_set_el_t dst;
2555 unit_set_el_t src;
2556 unit_set_el_t curr_el;
2557 unit_set_el_t prev_el;
2558 unit_set_el_t copy;
2560 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2561 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2563 if (dst->unit_decl == src->unit_decl)
2565 error ((presence_p
2566 ? "unit `%s' requires own presence"
2567 : "unit `%s' requires own absence"), src->unit_decl->name);
2568 continue;
2570 if (dst->unit_decl->automaton_name != NULL
2571 && src->unit_decl->automaton_name != NULL
2572 && strcmp (dst->unit_decl->automaton_name,
2573 src->unit_decl->automaton_name) != 0)
2575 error ((presence_p
2576 ? "units `%s' and `%s' in presence set belong to different automata"
2577 : "units `%s' and `%s' in absence set belong to different automata"),
2578 src->unit_decl->name, dst->unit_decl->name);
2579 continue;
2581 for (curr_el = (presence_p
2582 ? dst->unit_decl->presence_list
2583 : dst->unit_decl->absence_list), prev_el = NULL;
2584 curr_el != NULL;
2585 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2586 if (curr_el->unit_decl == src->unit_decl)
2587 break;
2588 if (curr_el == NULL)
2590 /* Element not found - insert if there is no error. */
2591 int no_error_flag = 1;
2593 if (presence_p)
2594 for (curr_el = dst->unit_decl->excl_list;
2595 curr_el != NULL;
2596 curr_el = curr_el->next_unit_set_el)
2598 if (src->unit_decl == curr_el->unit_decl)
2600 if (!w_flag)
2602 error
2603 ("unit `%s' excludes and requires presence of `%s'",
2604 dst->unit_decl->name, src->unit_decl->name);
2605 no_error_flag = 0;
2607 else
2608 warning
2609 ("unit `%s' excludes and requires presence of `%s'",
2610 dst->unit_decl->name, src->unit_decl->name);
2613 else
2614 for (curr_el = dst->unit_decl->presence_list;
2615 curr_el != NULL;
2616 curr_el = curr_el->next_unit_set_el)
2618 if (src->unit_decl == curr_el->unit_decl)
2620 if (!w_flag)
2622 error
2623 ("unit `%s' requires absence and presence of `%s'",
2624 dst->unit_decl->name, src->unit_decl->name);
2625 no_error_flag = 0;
2627 else
2628 warning
2629 ("unit `%s' requires absence and presence of `%s'",
2630 dst->unit_decl->name, src->unit_decl->name);
2633 if (no_error_flag)
2635 copy = copy_node (src, sizeof (*src));
2636 copy->next_unit_set_el = NULL;
2637 if (prev_el == NULL)
2639 if (presence_p)
2640 dst->unit_decl->presence_list = copy;
2641 else
2642 dst->unit_decl->absence_list = copy;
2644 else
2645 prev_el->next_unit_set_el = copy;
2651 /* The function searches for bypass with given IN_INSN_RESERV in given
2652 BYPASS_LIST. */
2653 static struct bypass_decl *
2654 find_bypass (bypass_list, in_insn_reserv)
2655 struct bypass_decl *bypass_list;
2656 struct insn_reserv_decl *in_insn_reserv;
2658 struct bypass_decl *bypass;
2660 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2661 if (bypass->in_insn_reserv == in_insn_reserv)
2662 break;
2663 return bypass;
2666 /* The function processes pipeline description declarations, checks
2667 their correctness, and forms exclusion/presence/absence sets. */
2668 static void
2669 process_decls ()
2671 decl_t decl;
2672 decl_t automaton_decl;
2673 decl_t decl_in_table;
2674 decl_t out_insn_reserv;
2675 decl_t in_insn_reserv;
2676 struct bypass_decl *bypass;
2677 int automaton_presence;
2678 int i;
2680 /* Checking repeated automata declarations. */
2681 automaton_presence = 0;
2682 for (i = 0; i < description->decls_num; i++)
2684 decl = description->decls [i];
2685 if (decl->mode == dm_automaton)
2687 automaton_presence = 1;
2688 decl_in_table = insert_automaton_decl (decl);
2689 if (decl_in_table != decl)
2691 if (!w_flag)
2692 error ("repeated declaration of automaton `%s'",
2693 DECL_AUTOMATON (decl)->name);
2694 else
2695 warning ("repeated declaration of automaton `%s'",
2696 DECL_AUTOMATON (decl)->name);
2700 /* Checking undeclared automata, repeated declarations (except for
2701 automata) and correctness of their attributes (insn latency times
2702 etc.). */
2703 for (i = 0; i < description->decls_num; i++)
2705 decl = description->decls [i];
2706 if (decl->mode == dm_insn_reserv)
2708 DECL_INSN_RESERV (decl)->condexp
2709 = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
2710 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2711 error ("define_insn_reservation `%s' has negative latency time",
2712 DECL_INSN_RESERV (decl)->name);
2713 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2714 description->insns_num++;
2715 decl_in_table = insert_insn_decl (decl);
2716 if (decl_in_table != decl)
2717 error ("`%s' is already used as insn reservation name",
2718 DECL_INSN_RESERV (decl)->name);
2720 else if (decl->mode == dm_bypass)
2722 if (DECL_BYPASS (decl)->latency < 0)
2723 error ("define_bypass `%s - %s' has negative latency time",
2724 DECL_BYPASS (decl)->out_insn_name,
2725 DECL_BYPASS (decl)->in_insn_name);
2727 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2729 if (decl->mode == dm_unit)
2731 DECL_UNIT (decl)->automaton_decl = NULL;
2732 if (DECL_UNIT (decl)->automaton_name != NULL)
2734 automaton_decl
2735 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2736 if (automaton_decl == NULL)
2737 error ("automaton `%s' is not declared",
2738 DECL_UNIT (decl)->automaton_name);
2739 else
2741 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2742 DECL_UNIT (decl)->automaton_decl
2743 = DECL_AUTOMATON (automaton_decl);
2746 else if (automaton_presence)
2747 error ("define_unit `%s' without automaton when one defined",
2748 DECL_UNIT (decl)->name);
2749 DECL_UNIT (decl)->unit_num = description->units_num;
2750 description->units_num++;
2751 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2753 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2754 continue;
2756 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2758 else
2760 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2762 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2763 continue;
2765 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2767 if (decl_in_table == NULL)
2768 decl_in_table = insert_decl (decl);
2769 else
2771 if (decl->mode == dm_unit)
2772 error ("repeated declaration of unit `%s'",
2773 DECL_UNIT (decl)->name);
2774 else
2775 error ("repeated declaration of reservation `%s'",
2776 DECL_RESERV (decl)->name);
2780 /* Check bypasses and form list of bypasses for each (output)
2781 insn. */
2782 for (i = 0; i < description->decls_num; i++)
2784 decl = description->decls [i];
2785 if (decl->mode == dm_bypass)
2787 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2788 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2789 if (out_insn_reserv == NULL)
2790 error ("there is no insn reservation `%s'",
2791 DECL_BYPASS (decl)->out_insn_name);
2792 else if (in_insn_reserv == NULL)
2793 error ("there is no insn reservation `%s'",
2794 DECL_BYPASS (decl)->in_insn_name);
2795 else
2797 DECL_BYPASS (decl)->out_insn_reserv
2798 = DECL_INSN_RESERV (out_insn_reserv);
2799 DECL_BYPASS (decl)->in_insn_reserv
2800 = DECL_INSN_RESERV (in_insn_reserv);
2801 bypass
2802 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2803 DECL_BYPASS (decl)->in_insn_reserv);
2804 if (bypass != NULL)
2806 if (DECL_BYPASS (decl)->latency == bypass->latency)
2808 if (!w_flag)
2809 error
2810 ("the same bypass `%s - %s' is already defined",
2811 DECL_BYPASS (decl)->out_insn_name,
2812 DECL_BYPASS (decl)->in_insn_name);
2813 else
2814 warning
2815 ("the same bypass `%s - %s' is already defined",
2816 DECL_BYPASS (decl)->out_insn_name,
2817 DECL_BYPASS (decl)->in_insn_name);
2819 else
2820 error ("bypass `%s - %s' is already defined",
2821 DECL_BYPASS (decl)->out_insn_name,
2822 DECL_BYPASS (decl)->in_insn_name);
2824 else
2826 DECL_BYPASS (decl)->next
2827 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2828 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2829 = DECL_BYPASS (decl);
2835 /* Check exclusion set declarations and form exclussion sets. */
2836 for (i = 0; i < description->decls_num; i++)
2838 decl = description->decls [i];
2839 if (decl->mode == dm_excl)
2841 unit_set_el_t unit_set_el_list;
2842 unit_set_el_t unit_set_el_list_2;
2844 unit_set_el_list
2845 = process_excls (DECL_EXCL (decl)->names,
2846 DECL_EXCL (decl)->first_list_length, decl->pos);
2847 unit_set_el_list_2
2848 = process_excls (&DECL_EXCL (decl)->names
2849 [DECL_EXCL (decl)->first_list_length],
2850 DECL_EXCL (decl)->names_num
2851 - DECL_EXCL (decl)->first_list_length,
2852 decl->pos);
2853 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2854 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2858 /* Check presence set declarations and form presence sets. */
2859 for (i = 0; i < description->decls_num; i++)
2861 decl = description->decls [i];
2862 if (decl->mode == dm_presence)
2864 unit_set_el_t unit_set_el_list;
2865 unit_set_el_t unit_set_el_list_2;
2867 unit_set_el_list
2868 = process_presence_absence
2869 (DECL_PRESENCE (decl)->names,
2870 DECL_PRESENCE (decl)->first_list_length, decl->pos, 1);
2871 unit_set_el_list_2
2872 = process_presence_absence
2873 (&DECL_PRESENCE (decl)->names
2874 [DECL_PRESENCE (decl)->first_list_length],
2875 DECL_PRESENCE (decl)->names_num
2876 - DECL_PRESENCE (decl)->first_list_length,
2877 decl->pos, 1);
2878 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2879 decl->pos, 1);
2883 /* Check absence set declarations and form absence sets. */
2884 for (i = 0; i < description->decls_num; i++)
2886 decl = description->decls [i];
2887 if (decl->mode == dm_absence)
2889 unit_set_el_t unit_set_el_list;
2890 unit_set_el_t unit_set_el_list_2;
2892 unit_set_el_list
2893 = process_presence_absence
2894 (DECL_ABSENCE (decl)->names,
2895 DECL_ABSENCE (decl)->first_list_length, decl->pos, 0);
2896 unit_set_el_list_2
2897 = process_presence_absence
2898 (&DECL_ABSENCE (decl)->names
2899 [DECL_ABSENCE (decl)->first_list_length],
2900 DECL_ABSENCE (decl)->names_num
2901 - DECL_ABSENCE (decl)->first_list_length,
2902 decl->pos, 0);
2903 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2904 decl->pos, 0);
2909 /* The following function checks that declared automaton is used. If
2910 the automaton is not used, the function fixes error/warning. The
2911 following function must be called only after `process_decls'. */
2912 static void
2913 check_automaton_usage ()
2915 decl_t decl;
2916 int i;
2918 for (i = 0; i < description->decls_num; i++)
2920 decl = description->decls [i];
2921 if (decl->mode == dm_automaton
2922 && !DECL_AUTOMATON (decl)->automaton_is_used)
2924 if (!w_flag)
2925 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2926 else
2927 warning ("automaton `%s' is not used",
2928 DECL_AUTOMATON (decl)->name);
2933 /* The following recursive function processes all regexp in order to
2934 fix usage of units or reservations and to fix errors of undeclared
2935 name. The function may change unit_regexp onto reserv_regexp.
2936 Remember that reserv_regexp does not exist before the function
2937 call. */
2938 static regexp_t
2939 process_regexp (regexp)
2940 regexp_t regexp;
2942 decl_t decl_in_table;
2943 regexp_t new_regexp;
2944 int i;
2946 if (regexp->mode == rm_unit)
2948 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2949 if (decl_in_table == NULL)
2950 error ("undeclared unit or reservation `%s'",
2951 REGEXP_UNIT (regexp)->name);
2952 else if (decl_in_table->mode == dm_unit)
2954 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2955 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2957 else if (decl_in_table->mode == dm_reserv)
2959 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2960 new_regexp = create_node (sizeof (struct regexp));
2961 new_regexp->mode = rm_reserv;
2962 new_regexp->pos = regexp->pos;
2963 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2964 REGEXP_RESERV (new_regexp)->reserv_decl
2965 = DECL_RESERV (decl_in_table);
2966 regexp = new_regexp;
2968 else
2969 abort ();
2971 else if (regexp->mode == rm_sequence)
2972 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2973 REGEXP_SEQUENCE (regexp)->regexps [i]
2974 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2975 else if (regexp->mode == rm_allof)
2976 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2977 REGEXP_ALLOF (regexp)->regexps [i]
2978 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2979 else if (regexp->mode == rm_oneof)
2980 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2981 REGEXP_ONEOF (regexp)->regexps [i]
2982 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2983 else if (regexp->mode == rm_repeat)
2984 REGEXP_REPEAT (regexp)->regexp
2985 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2986 else if (regexp->mode != rm_nothing)
2987 abort ();
2988 return regexp;
2991 /* The following function processes regexp of define_reservation and
2992 define_insn_reservation with the aid of function
2993 `process_regexp'. */
2994 static void
2995 process_regexp_decls ()
2997 decl_t decl;
2998 int i;
3000 for (i = 0; i < description->decls_num; i++)
3002 decl = description->decls [i];
3003 if (decl->mode == dm_reserv)
3004 DECL_RESERV (decl)->regexp
3005 = process_regexp (DECL_RESERV (decl)->regexp);
3006 else if (decl->mode == dm_insn_reserv)
3007 DECL_INSN_RESERV (decl)->regexp
3008 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3012 /* The following function checks that declared unit is used. If the
3013 unit is not used, the function fixes errors/warnings. The
3014 following function must be called only after `process_decls',
3015 `process_regexp_decls'. */
3016 static void
3017 check_usage ()
3019 decl_t decl;
3020 int i;
3022 for (i = 0; i < description->decls_num; i++)
3024 decl = description->decls [i];
3025 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3027 if (!w_flag)
3028 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3029 else
3030 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3032 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3034 if (!w_flag)
3035 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3036 else
3037 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3042 /* The following variable value is number of reservation being
3043 processed on loop recognition. */
3044 static int curr_loop_pass_num;
3046 /* The following recursive function returns nonzero value if REGEXP
3047 contains given decl or reservations in given regexp refers for
3048 given decl. */
3049 static int
3050 loop_in_regexp (regexp, start_decl)
3051 regexp_t regexp;
3052 decl_t start_decl;
3054 int i;
3056 if (regexp == NULL)
3057 return 0;
3058 if (regexp->mode == rm_unit)
3059 return 0;
3060 else if (regexp->mode == rm_reserv)
3062 if (start_decl->mode == dm_reserv
3063 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3064 return 1;
3065 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3066 == curr_loop_pass_num)
3067 /* declaration has been processed. */
3068 return 0;
3069 else
3071 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3072 = curr_loop_pass_num;
3073 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3074 start_decl);
3077 else if (regexp->mode == rm_sequence)
3079 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3080 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3081 return 1;
3082 return 0;
3084 else if (regexp->mode == rm_allof)
3086 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3087 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3088 return 1;
3089 return 0;
3091 else if (regexp->mode == rm_oneof)
3093 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3094 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3095 return 1;
3096 return 0;
3098 else if (regexp->mode == rm_repeat)
3099 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3100 else
3102 if (regexp->mode != rm_nothing)
3103 abort ();
3104 return 0;
3108 /* The following function fixes errors "cycle in definition ...". The
3109 function uses function `loop_in_regexp' for that. */
3110 static void
3111 check_loops_in_regexps ()
3113 decl_t decl;
3114 int i;
3116 for (i = 0; i < description->decls_num; i++)
3118 decl = description->decls [i];
3119 if (decl->mode == dm_reserv)
3120 DECL_RESERV (decl)->loop_pass_num = 0;
3122 for (i = 0; i < description->decls_num; i++)
3124 decl = description->decls [i];
3125 curr_loop_pass_num = i;
3127 if (decl->mode == dm_reserv)
3129 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
3130 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3132 if (DECL_RESERV (decl)->regexp == NULL)
3133 abort ();
3134 error ("cycle in definition of reservation `%s'",
3135 DECL_RESERV (decl)->name);
3141 /* The function recursively processes IR of reservation and defines
3142 max and min cycle for reservation of unit and for result in the
3143 reservation. */
3144 static int
3145 process_regexp_cycles (regexp, start_cycle)
3146 regexp_t regexp;
3147 int start_cycle;
3149 int i;
3151 if (regexp->mode == rm_unit)
3153 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < start_cycle)
3154 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = start_cycle;
3155 return start_cycle;
3157 else if (regexp->mode == rm_reserv)
3158 return process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3159 start_cycle);
3160 else if (regexp->mode == rm_repeat)
3162 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3163 start_cycle = process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3164 start_cycle) + 1;
3165 return start_cycle;
3167 else if (regexp->mode == rm_sequence)
3169 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3170 start_cycle
3171 = process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3172 start_cycle) + 1;
3173 return start_cycle;
3175 else if (regexp->mode == rm_allof)
3177 int finish_cycle = 0;
3178 int cycle;
3180 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3182 cycle = process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3183 start_cycle);
3184 if (finish_cycle < cycle)
3185 finish_cycle = cycle;
3187 return finish_cycle;
3189 else if (regexp->mode == rm_oneof)
3191 int finish_cycle = 0;
3192 int cycle;
3194 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3196 cycle = process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3197 start_cycle);
3198 if (finish_cycle < cycle)
3199 finish_cycle = cycle;
3201 return finish_cycle;
3203 else
3205 if (regexp->mode != rm_nothing)
3206 abort ();
3207 return start_cycle;
3211 /* The following function is called only for correct program. The
3212 function defines max reservation of insns in cycles. */
3213 static void
3214 evaluate_max_reserv_cycles ()
3216 int max_insn_cycles_num;
3217 decl_t decl;
3218 int i;
3220 description->max_insn_reserv_cycles = 0;
3221 for (i = 0; i < description->decls_num; i++)
3223 decl = description->decls [i];
3224 if (decl->mode == dm_insn_reserv)
3226 max_insn_cycles_num
3227 = process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0);
3228 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3229 description->max_insn_reserv_cycles = max_insn_cycles_num;
3232 description->max_insn_reserv_cycles++;
3235 /* The following function calls functions for checking all
3236 description. */
3237 static void
3238 check_all_description ()
3240 process_decls ();
3241 check_automaton_usage ();
3242 process_regexp_decls ();
3243 check_usage ();
3244 check_loops_in_regexps ();
3245 if (!have_error)
3246 evaluate_max_reserv_cycles ();
3251 /* The page contains abstract data `ticker'. This data is used to
3252 report time of different phases of building automata. It is
3253 possibly to write a description for which automata will be built
3254 during several minutes even on fast machine. */
3256 /* The following function creates ticker and makes it active. */
3257 static ticker_t
3258 create_ticker ()
3260 ticker_t ticker;
3262 ticker.modified_creation_time = get_run_time ();
3263 ticker.incremented_off_time = 0;
3264 return ticker;
3267 /* The following function switches off given ticker. */
3268 static void
3269 ticker_off (ticker)
3270 ticker_t *ticker;
3272 if (ticker->incremented_off_time == 0)
3273 ticker->incremented_off_time = get_run_time () + 1;
3276 /* The following function switches on given ticker. */
3277 static void
3278 ticker_on (ticker)
3279 ticker_t *ticker;
3281 if (ticker->incremented_off_time != 0)
3283 ticker->modified_creation_time
3284 += get_run_time () - ticker->incremented_off_time + 1;
3285 ticker->incremented_off_time = 0;
3289 /* The following function returns current time in milliseconds since
3290 the moment when given ticker was created. */
3291 static int
3292 active_time (ticker)
3293 ticker_t ticker;
3295 if (ticker.incremented_off_time != 0)
3296 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3297 else
3298 return get_run_time () - ticker.modified_creation_time;
3301 /* The following function returns string representation of active time
3302 of given ticker. The result is string representation of seconds
3303 with accuracy of 1/100 second. Only result of the last call of the
3304 function exists. Therefore the following code is not correct
3306 printf ("parser time: %s\ngeneration time: %s\n",
3307 active_time_string (parser_ticker),
3308 active_time_string (generation_ticker));
3310 Correct code has to be the following
3312 printf ("parser time: %s\n", active_time_string (parser_ticker));
3313 printf ("generation time: %s\n",
3314 active_time_string (generation_ticker));
3317 static void
3318 print_active_time (f, ticker)
3319 FILE *f;
3320 ticker_t ticker;
3322 int msecs;
3324 msecs = active_time (ticker);
3325 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3330 /* The following variable value is number of automaton which are
3331 really being created. This value is defined on the base of
3332 argument of option `-split'. If the variable has zero value the
3333 number of automata is defined by the constructions `%automaton'.
3334 This case occures when option `-split' is absent or has zero
3335 argument. If constructions `define_automaton' is absent only one
3336 automaton is created. */
3337 static int automata_num;
3339 /* The following variable values are times of
3340 o transformation of regular expressions
3341 o building NDFA (DFA if !ndfa_flag)
3342 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3343 o DFA minimization
3344 o building insn equivalence classes
3345 o all previous ones
3346 o code output */
3347 static ticker_t transform_time;
3348 static ticker_t NDFA_time;
3349 static ticker_t NDFA_to_DFA_time;
3350 static ticker_t minimize_time;
3351 static ticker_t equiv_time;
3352 static ticker_t automaton_generation_time;
3353 static ticker_t output_time;
3355 /* The following variable values are times of
3356 all checking
3357 all generation
3358 all pipeline hazard translator work */
3359 static ticker_t check_time;
3360 static ticker_t generation_time;
3361 static ticker_t all_time;
3365 /* Pseudo insn decl which denotes advancing cycle. */
3366 static decl_t advance_cycle_insn_decl;
3367 static void
3368 add_advance_cycle_insn_decl ()
3370 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3371 advance_cycle_insn_decl->mode = dm_insn_reserv;
3372 advance_cycle_insn_decl->pos = no_pos;
3373 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3374 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
3375 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3376 = description->insns_num;
3377 description->decls [description->decls_num] = advance_cycle_insn_decl;
3378 description->decls_num++;
3379 description->insns_num++;
3380 num_dfa_decls++;
3384 /* Abstract data `alternative states' which reperesents
3385 nondeterministic nature of the description (see comments for
3386 structures alt_state and state). */
3388 /* List of free states. */
3389 static alt_state_t first_free_alt_state;
3391 #ifndef NDEBUG
3392 /* The following variables is maximal number of allocated nodes
3393 alt_state. */
3394 static int allocated_alt_states_num = 0;
3395 #endif
3397 /* The following function returns free node alt_state. It may be new
3398 allocated node or node freed eralier. */
3399 static alt_state_t
3400 get_free_alt_state ()
3402 alt_state_t result;
3404 if (first_free_alt_state != NULL)
3406 result = first_free_alt_state;
3407 first_free_alt_state = first_free_alt_state->next_alt_state;
3409 else
3411 #ifndef NDEBUG
3412 allocated_alt_states_num++;
3413 #endif
3414 result = create_node (sizeof (struct alt_state));
3416 result->state = NULL;
3417 result->next_alt_state = NULL;
3418 result->next_sorted_alt_state = NULL;
3419 return result;
3422 /* The function frees node ALT_STATE. */
3423 static void
3424 free_alt_state (alt_state)
3425 alt_state_t alt_state;
3427 if (alt_state == NULL)
3428 return;
3429 alt_state->next_alt_state = first_free_alt_state;
3430 first_free_alt_state = alt_state;
3433 /* The function frees list started with node ALT_STATE_LIST. */
3434 static void
3435 free_alt_states (alt_states_list)
3436 alt_state_t alt_states_list;
3438 alt_state_t curr_alt_state;
3439 alt_state_t next_alt_state;
3441 for (curr_alt_state = alt_states_list;
3442 curr_alt_state != NULL;
3443 curr_alt_state = next_alt_state)
3445 next_alt_state = curr_alt_state->next_alt_state;
3446 free_alt_state (curr_alt_state);
3450 /* The function compares unique numbers of alt states. */
3451 static int
3452 alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
3453 const void *alt_state_ptr_1;
3454 const void *alt_state_ptr_2;
3456 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3457 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3458 return 0;
3459 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3460 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3461 return -1;
3462 else
3463 return 1;
3466 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3467 states from the list. The comparison key is alt state unique
3468 number. */
3469 static alt_state_t
3470 uniq_sort_alt_states (alt_states_list)
3471 alt_state_t alt_states_list;
3473 alt_state_t curr_alt_state;
3474 vla_ptr_t alt_states;
3475 size_t i;
3476 size_t prev_unique_state_ind;
3477 alt_state_t result;
3478 alt_state_t *result_ptr;
3480 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3481 for (curr_alt_state = alt_states_list;
3482 curr_alt_state != NULL;
3483 curr_alt_state = curr_alt_state->next_alt_state)
3484 VLA_PTR_ADD (alt_states, curr_alt_state);
3485 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3486 sizeof (alt_state_t), alt_state_cmp);
3487 if (VLA_PTR_LENGTH (alt_states) == 0)
3488 result = NULL;
3489 else
3491 result_ptr = VLA_PTR_BEGIN (alt_states);
3492 prev_unique_state_ind = 0;
3493 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3494 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3496 prev_unique_state_ind++;
3497 result_ptr [prev_unique_state_ind] = result_ptr [i];
3499 #if 0
3500 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3501 free_alt_state (result_ptr [i]);
3502 #endif
3503 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3504 result_ptr = VLA_PTR_BEGIN (alt_states);
3505 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3506 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3507 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3508 result = *result_ptr;
3510 VLA_PTR_DELETE (alt_states);
3511 return result;
3514 /* The function checks equality of alt state lists. Remember that the
3515 lists must be already sorted by the previous function. */
3516 static int
3517 alt_states_eq (alt_states_1, alt_states_2)
3518 alt_state_t alt_states_1;
3519 alt_state_t alt_states_2;
3521 while (alt_states_1 != NULL && alt_states_2 != NULL
3522 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3524 alt_states_1 = alt_states_1->next_sorted_alt_state;
3525 alt_states_2 = alt_states_2->next_sorted_alt_state;
3527 return alt_states_1 == alt_states_2;
3530 /* Initialization of the abstract data. */
3531 static void
3532 initiate_alt_states ()
3534 first_free_alt_state = NULL;
3537 /* Finishing work with the abstract data. */
3538 static void
3539 finish_alt_states ()
3545 /* The page contains macros for work with bits strings. We could use
3546 standard gcc bitmap or sbitmap but it would result in difficulties
3547 of building canadian cross. */
3549 /* Set bit number bitno in the bit string. The macro is not side
3550 effect proof. */
3551 #define SET_BIT(bitstring, bitno) \
3552 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3554 /* Test if bit number bitno in the bitstring is set. The macro is not
3555 side effect proof. */
3556 #define TEST_BIT(bitstring, bitno) \
3557 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3561 /* This page contains abstract data `state'. */
3563 /* Maximal length of reservations in cycles (>= 1). */
3564 static int max_cycles_num;
3566 /* Number of set elements (see type set_el_t) needed for
3567 representation of one cycle reservation. It is depended on units
3568 number. */
3569 static int els_in_cycle_reserv;
3571 /* Number of set elements (see type set_el_t) needed for
3572 representation of maximal length reservation. Deterministic
3573 reservation is stored as set (bit string) of length equal to the
3574 variable value * number of bits in set_el_t. */
3575 static int els_in_reservs;
3577 /* VLA for representation of array of pointers to unit
3578 declarations. */
3579 static vla_ptr_t units_container;
3581 /* The start address of the array. */
3582 static unit_decl_t *units_array;
3584 /* Empty reservation of maximal length. */
3585 static reserv_sets_t empty_reserv;
3587 /* The state table itself is represented by the following variable. */
3588 static htab_t state_table;
3590 /* VLA for representation of array of pointers to free nodes
3591 `state'. */
3592 static vla_ptr_t free_states;
3594 static int curr_unique_state_num;
3596 #ifndef NDEBUG
3597 /* The following variables is maximal number of allocated nodes
3598 `state'. */
3599 static int allocated_states_num = 0;
3600 #endif
3602 /* Allocate new reservation set. */
3603 static reserv_sets_t
3604 alloc_empty_reserv_sets ()
3606 reserv_sets_t result;
3608 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3609 result = (reserv_sets_t) obstack_base (&irp);
3610 obstack_finish (&irp);
3611 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3612 return result;
3615 /* Hash value of reservation set. */
3616 static unsigned
3617 reserv_sets_hash_value (reservs)
3618 reserv_sets_t reservs;
3620 set_el_t hash_value;
3621 unsigned result;
3622 int reservs_num, i;
3623 set_el_t *reserv_ptr;
3625 hash_value = 0;
3626 reservs_num = els_in_reservs;
3627 reserv_ptr = reservs;
3628 i = 0;
3629 while (reservs_num != 0)
3631 reservs_num--;
3632 hash_value += ((*reserv_ptr >> i)
3633 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3634 i++;
3635 if (i == sizeof (set_el_t) * CHAR_BIT)
3636 i = 0;
3637 reserv_ptr++;
3639 if (sizeof (set_el_t) <= sizeof (unsigned))
3640 return hash_value;
3641 result = 0;
3642 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3644 result += (unsigned) hash_value;
3645 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3647 return result;
3650 /* Comparison of given reservation sets. */
3651 static int
3652 reserv_sets_cmp (reservs_1, reservs_2)
3653 reserv_sets_t reservs_1;
3654 reserv_sets_t reservs_2;
3656 int reservs_num;
3657 set_el_t *reserv_ptr_1;
3658 set_el_t *reserv_ptr_2;
3660 if (reservs_1 == NULL || reservs_2 == NULL)
3661 abort ();
3662 reservs_num = els_in_reservs;
3663 reserv_ptr_1 = reservs_1;
3664 reserv_ptr_2 = reservs_2;
3665 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3667 reservs_num--;
3668 reserv_ptr_1++;
3669 reserv_ptr_2++;
3671 if (reservs_num == 0)
3672 return 0;
3673 else if (*reserv_ptr_1 < *reserv_ptr_2)
3674 return -1;
3675 else
3676 return 1;
3679 /* The function checks equality of the reservation sets. */
3680 static int
3681 reserv_sets_eq (reservs_1, reservs_2)
3682 reserv_sets_t reservs_1;
3683 reserv_sets_t reservs_2;
3685 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3688 /* Set up in the reservation set that unit with UNIT_NUM is used on
3689 CYCLE_NUM. */
3690 static void
3691 set_unit_reserv (reservs, cycle_num, unit_num)
3692 reserv_sets_t reservs;
3693 int cycle_num;
3694 int unit_num;
3696 if (cycle_num >= max_cycles_num)
3697 abort ();
3698 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3699 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3702 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3703 used on CYCLE_NUM. */
3704 static int
3705 test_unit_reserv (reservs, cycle_num, unit_num)
3706 reserv_sets_t reservs;
3707 int cycle_num;
3708 int unit_num;
3710 if (cycle_num >= max_cycles_num)
3711 abort ();
3712 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3713 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3716 /* The function checks that the reservation set represents no one unit
3717 reservation. */
3718 static int
3719 it_is_empty_reserv_sets (operand)
3720 reserv_sets_t operand;
3722 set_el_t *reserv_ptr;
3723 int reservs_num;
3725 if (operand == NULL)
3726 abort ();
3727 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3728 reservs_num != 0;
3729 reserv_ptr++, reservs_num--)
3730 if (*reserv_ptr != 0)
3731 return 0;
3732 return 1;
3735 /* The function checks that the reservation sets are intersected,
3736 i.e. there is a unit reservation on a cycle in both reservation
3737 sets. */
3738 static int
3739 reserv_sets_are_intersected (operand_1, operand_2)
3740 reserv_sets_t operand_1;
3741 reserv_sets_t operand_2;
3743 set_el_t *el_ptr_1;
3744 set_el_t *el_ptr_2;
3745 set_el_t *cycle_ptr_1;
3746 set_el_t *cycle_ptr_2;
3747 int nonzero_p;
3749 if (operand_1 == NULL || operand_2 == NULL)
3750 abort ();
3751 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3752 el_ptr_1 < operand_1 + els_in_reservs;
3753 el_ptr_1++, el_ptr_2++)
3754 if (*el_ptr_1 & *el_ptr_2)
3755 return 1;
3756 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3757 cycle_ptr_1 < operand_1 + els_in_reservs;
3758 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3760 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3761 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3762 el_ptr_1++, el_ptr_2++)
3763 if (*el_ptr_1 & *el_ptr_2)
3764 return 1;
3765 nonzero_p = 0;
3766 for (el_ptr_1 = cycle_ptr_1,
3767 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 1);
3768 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3769 el_ptr_1++, el_ptr_2++)
3770 if (*el_ptr_1 & *el_ptr_2)
3771 break;
3772 else if (*el_ptr_2 != 0)
3773 nonzero_p = 1;
3774 if (nonzero_p && el_ptr_1 >= cycle_ptr_1 + els_in_cycle_reserv)
3775 return 1;
3776 for (el_ptr_1 = cycle_ptr_1,
3777 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 0);
3778 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3779 el_ptr_1++, el_ptr_2++)
3780 /* It looks like code for exclusion but exclusion set is
3781 made as symmetric relation preliminary. */
3782 if (*el_ptr_1 & *el_ptr_2)
3783 return 1;
3785 return 0;
3788 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3789 cpu cycle. The remaining bits of OPERAND (representing the last
3790 cycle unit reservations) are not chenged. */
3791 static void
3792 reserv_sets_shift (result, operand)
3793 reserv_sets_t result;
3794 reserv_sets_t operand;
3796 int i;
3798 if (result == NULL || operand == NULL || result == operand)
3799 abort ();
3800 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3801 result [i - els_in_cycle_reserv] = operand [i];
3804 /* OR of the reservation sets. */
3805 static void
3806 reserv_sets_or (result, operand_1, operand_2)
3807 reserv_sets_t result;
3808 reserv_sets_t operand_1;
3809 reserv_sets_t operand_2;
3811 set_el_t *el_ptr_1;
3812 set_el_t *el_ptr_2;
3813 set_el_t *result_set_el_ptr;
3815 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3816 abort ();
3817 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3818 el_ptr_1 < operand_1 + els_in_reservs;
3819 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3820 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3823 /* AND of the reservation sets. */
3824 static void
3825 reserv_sets_and (result, operand_1, operand_2)
3826 reserv_sets_t result;
3827 reserv_sets_t operand_1;
3828 reserv_sets_t operand_2;
3830 set_el_t *el_ptr_1;
3831 set_el_t *el_ptr_2;
3832 set_el_t *result_set_el_ptr;
3834 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3835 abort ();
3836 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3837 el_ptr_1 < operand_1 + els_in_reservs;
3838 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3839 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3842 /* The function outputs string representation of units reservation on
3843 cycle START_CYCLE in the reservation set. The function uses repeat
3844 construction if REPETITION_NUM > 1. */
3845 static void
3846 output_cycle_reservs (f, reservs, start_cycle, repetition_num)
3847 FILE *f;
3848 reserv_sets_t reservs;
3849 int start_cycle;
3850 int repetition_num;
3852 int unit_num;
3853 int reserved_units_num;
3855 reserved_units_num = 0;
3856 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3857 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3858 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3859 reserved_units_num++;
3860 if (repetition_num <= 0)
3861 abort ();
3862 if (repetition_num != 1 && reserved_units_num > 1)
3863 fprintf (f, "(");
3864 reserved_units_num = 0;
3865 for (unit_num = 0;
3866 unit_num < description->units_num;
3867 unit_num++)
3868 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3869 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3871 if (reserved_units_num != 0)
3872 fprintf (f, "+");
3873 reserved_units_num++;
3874 fprintf (f, "%s", units_array [unit_num]->name);
3876 if (reserved_units_num == 0)
3877 fprintf (f, NOTHING_NAME);
3878 if (repetition_num <= 0)
3879 abort ();
3880 if (reserved_units_num > 1)
3881 fprintf (f, ")");
3882 if (repetition_num != 1)
3883 fprintf (f, "*%d", repetition_num);
3886 /* The function outputs string representation of units reservation in
3887 the reservation set. */
3888 static void
3889 output_reserv_sets (f, reservs)
3890 FILE *f;
3891 reserv_sets_t reservs;
3893 int start_cycle = 0;
3894 int cycle;
3895 int repetition_num;
3897 repetition_num = 0;
3898 for (cycle = 0; cycle < max_cycles_num; cycle++)
3899 if (repetition_num == 0)
3901 repetition_num++;
3902 start_cycle = cycle;
3904 else if (memcmp
3905 ((char *) reservs + start_cycle * els_in_cycle_reserv
3906 * sizeof (set_el_t),
3907 (char *) reservs + cycle * els_in_cycle_reserv
3908 * sizeof (set_el_t),
3909 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3910 repetition_num++;
3911 else
3913 if (start_cycle != 0)
3914 fprintf (f, ", ");
3915 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3916 repetition_num = 1;
3917 start_cycle = cycle;
3919 if (start_cycle < max_cycles_num)
3921 if (start_cycle != 0)
3922 fprintf (f, ", ");
3923 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3927 /* The following function returns free node state for AUTOMATON. It
3928 may be new allocated node or node freed eralier. The function also
3929 allocates reservation set if WITH_RESERVS has nonzero value. */
3930 static state_t
3931 get_free_state (with_reservs, automaton)
3932 int with_reservs;
3933 automaton_t automaton;
3935 state_t result;
3937 if (max_cycles_num <= 0 || automaton == NULL)
3938 abort ();
3939 if (VLA_PTR_LENGTH (free_states) != 0)
3941 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
3942 VLA_PTR_SHORTEN (free_states, 1);
3943 result->automaton = automaton;
3944 result->first_out_arc = NULL;
3945 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3946 result->it_was_placed_in_stack_for_DFA_forming = 0;
3947 result->component_states = NULL;
3948 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3950 else
3952 #ifndef NDEBUG
3953 allocated_states_num++;
3954 #endif
3955 result = create_node (sizeof (struct state));
3956 result->automaton = automaton;
3957 result->first_out_arc = NULL;
3958 result->unique_num = curr_unique_state_num;
3959 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3960 curr_unique_state_num++;
3962 if (with_reservs)
3964 if (result->reservs == NULL)
3965 result->reservs = alloc_empty_reserv_sets ();
3966 else
3967 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3969 return result;
3972 /* The function frees node STATE. */
3973 static void
3974 free_state (state)
3975 state_t state;
3977 free_alt_states (state->component_states);
3978 VLA_PTR_ADD (free_states, state);
3981 /* Hash value of STATE. If STATE represents deterministic state it is
3982 simply hash value of the corresponding reservation set. Otherwise
3983 it is formed from hash values of the component deterministic
3984 states. One more key is order number of state automaton. */
3985 static unsigned
3986 state_hash (state)
3987 const void *state;
3989 unsigned int hash_value;
3990 alt_state_t alt_state;
3992 if (((state_t) state)->component_states == NULL)
3993 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3994 else
3996 hash_value = 0;
3997 for (alt_state = ((state_t) state)->component_states;
3998 alt_state != NULL;
3999 alt_state = alt_state->next_sorted_alt_state)
4000 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4001 | (hash_value << CHAR_BIT))
4002 + alt_state->state->unique_num);
4004 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4005 | (hash_value << CHAR_BIT))
4006 + ((state_t) state)->automaton->automaton_order_num);
4007 return hash_value;
4010 /* Return nonzero value if the states are the same. */
4011 static int
4012 state_eq_p (state_1, state_2)
4013 const void *state_1;
4014 const void *state_2;
4016 alt_state_t alt_state_1;
4017 alt_state_t alt_state_2;
4019 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
4020 return 0;
4021 else if (((state_t) state_1)->component_states == NULL
4022 && ((state_t) state_2)->component_states == NULL)
4023 return reserv_sets_eq (((state_t) state_1)->reservs,
4024 ((state_t) state_2)->reservs);
4025 else if (((state_t) state_1)->component_states != NULL
4026 && ((state_t) state_2)->component_states != NULL)
4028 for (alt_state_1 = ((state_t) state_1)->component_states,
4029 alt_state_2 = ((state_t) state_2)->component_states;
4030 alt_state_1 != NULL && alt_state_2 != NULL;
4031 alt_state_1 = alt_state_1->next_sorted_alt_state,
4032 alt_state_2 = alt_state_2->next_sorted_alt_state)
4033 /* All state in the list must be already in the hash table.
4034 Also the lists must be sorted. */
4035 if (alt_state_1->state != alt_state_2->state)
4036 return 0;
4037 return alt_state_1 == alt_state_2;
4039 else
4040 return 0;
4043 /* Insert STATE into the state table. */
4044 static state_t
4045 insert_state (state)
4046 state_t state;
4048 void **entry_ptr;
4050 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
4051 if (*entry_ptr == NULL)
4052 *entry_ptr = (void *) state;
4053 return (state_t) *entry_ptr;
4056 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4057 deterministic STATE. */
4058 static void
4059 set_state_reserv (state, cycle_num, unit_num)
4060 state_t state;
4061 int cycle_num;
4062 int unit_num;
4064 set_unit_reserv (state->reservs, cycle_num, unit_num);
4067 /* Return nonzero value if the deterministic states contains a
4068 reservation of the same cpu unit on the same cpu cycle. */
4069 static int
4070 intersected_state_reservs_p (state1, state2)
4071 state_t state1;
4072 state_t state2;
4074 if (state1->automaton != state2->automaton)
4075 abort ();
4076 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
4079 /* Return deterministic state (inserted into the table) which
4080 representing the automaton state whic is union of reservations of
4081 deterministic states. */
4082 static state_t
4083 states_union (state1, state2)
4084 state_t state1;
4085 state_t state2;
4087 state_t result;
4088 state_t state_in_table;
4090 if (state1->automaton != state2->automaton)
4091 abort ();
4092 result = get_free_state (1, state1->automaton);
4093 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
4094 state_in_table = insert_state (result);
4095 if (result != state_in_table)
4097 free_state (result);
4098 result = state_in_table;
4100 return result;
4103 /* Return deterministic state (inserted into the table) which
4104 represent the automaton state is obtained from deterministic STATE
4105 by advancing cpu cycle. */
4106 static state_t
4107 state_shift (state)
4108 state_t state;
4110 state_t result;
4111 state_t state_in_table;
4113 result = get_free_state (1, state->automaton);
4114 reserv_sets_shift (result->reservs, state->reservs);
4115 state_in_table = insert_state (result);
4116 if (result != state_in_table)
4118 free_state (result);
4119 result = state_in_table;
4121 return result;
4124 /* Initialization of the abstract data. */
4125 static void
4126 initiate_states ()
4128 decl_t decl;
4129 int i;
4131 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
4132 units_array
4133 = (description->decls_num && description->units_num
4134 ? VLA_PTR_BEGIN (units_container) : NULL);
4135 for (i = 0; i < description->decls_num; i++)
4137 decl = description->decls [i];
4138 if (decl->mode == dm_unit)
4139 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
4141 max_cycles_num = description->max_insn_reserv_cycles;
4142 els_in_cycle_reserv
4143 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
4144 / (sizeof (set_el_t) * CHAR_BIT));
4145 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
4146 curr_unique_state_num = 0;
4147 initiate_alt_states ();
4148 VLA_PTR_CREATE (free_states, 1500, "free states");
4149 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
4150 empty_reserv = alloc_empty_reserv_sets ();
4153 /* Finisging work with the abstract data. */
4154 static void
4155 finish_states ()
4157 VLA_PTR_DELETE (units_container);
4158 htab_delete (state_table);
4159 VLA_PTR_DELETE (free_states);
4160 finish_alt_states ();
4165 /* Abstract data `arcs'. */
4167 /* List of free arcs. */
4168 static arc_t first_free_arc;
4170 #ifndef NDEBUG
4171 /* The following variables is maximal number of allocated nodes
4172 `arc'. */
4173 static int allocated_arcs_num = 0;
4174 #endif
4176 /* The function frees node ARC. */
4177 static void
4178 free_arc (arc)
4179 arc_t arc;
4181 arc->next_out_arc = first_free_arc;
4182 first_free_arc = arc;
4185 /* The function removes and frees ARC staring from FROM_STATE. */
4186 static void
4187 remove_arc (from_state, arc)
4188 state_t from_state;
4189 arc_t arc;
4191 arc_t prev_arc;
4192 arc_t curr_arc;
4194 if (arc == NULL)
4195 abort ();
4196 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
4197 curr_arc != NULL;
4198 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4199 if (curr_arc == arc)
4200 break;
4201 if (curr_arc == NULL)
4202 abort ();
4203 if (prev_arc == NULL)
4204 from_state->first_out_arc = arc->next_out_arc;
4205 else
4206 prev_arc->next_out_arc = arc->next_out_arc;
4207 free_arc (arc);
4210 /* The functions returns arc with given characteristics (or NULL if
4211 the arc does not exist). */
4212 static arc_t
4213 find_arc (from_state, to_state, insn)
4214 state_t from_state;
4215 state_t to_state;
4216 ainsn_t insn;
4218 arc_t arc;
4220 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4221 if (arc->to_state == to_state && arc->insn == insn)
4222 return arc;
4223 return NULL;
4226 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4227 and with given STATE_ALTS. The function returns added arc (or
4228 already existing arc). */
4229 static arc_t
4230 add_arc (from_state, to_state, ainsn, state_alts)
4231 state_t from_state;
4232 state_t to_state;
4233 ainsn_t ainsn;
4234 int state_alts;
4236 arc_t new_arc;
4238 new_arc = find_arc (from_state, to_state, ainsn);
4239 if (new_arc != NULL)
4240 return new_arc;
4241 if (first_free_arc == NULL)
4243 #ifndef NDEBUG
4244 allocated_arcs_num++;
4245 #endif
4246 new_arc = create_node (sizeof (struct arc));
4247 new_arc->to_state = NULL;
4248 new_arc->insn = NULL;
4249 new_arc->next_out_arc = NULL;
4251 else
4253 new_arc = first_free_arc;
4254 first_free_arc = first_free_arc->next_out_arc;
4256 new_arc->to_state = to_state;
4257 new_arc->insn = ainsn;
4258 ainsn->arc_exists_p = 1;
4259 new_arc->next_out_arc = from_state->first_out_arc;
4260 from_state->first_out_arc = new_arc;
4261 new_arc->next_arc_marked_by_insn = NULL;
4262 new_arc->state_alts = state_alts;
4263 return new_arc;
4266 /* The function returns the first arc starting from STATE. */
4267 static arc_t
4268 first_out_arc (state)
4269 state_t state;
4271 return state->first_out_arc;
4274 /* The function returns next out arc after ARC. */
4275 static arc_t
4276 next_out_arc (arc)
4277 arc_t arc;
4279 return arc->next_out_arc;
4282 /* Initialization of the abstract data. */
4283 static void
4284 initiate_arcs ()
4286 first_free_arc = NULL;
4289 /* Finishing work with the abstract data. */
4290 static void
4291 finish_arcs ()
4297 /* Abstract data `automata lists'. */
4299 /* List of free states. */
4300 static automata_list_el_t first_free_automata_list_el;
4302 /* The list being formed. */
4303 static automata_list_el_t current_automata_list;
4305 /* Hash table of automata lists. */
4306 static htab_t automata_list_table;
4308 /* The following function returns free automata list el. It may be
4309 new allocated node or node freed earlier. */
4310 static automata_list_el_t
4311 get_free_automata_list_el ()
4313 automata_list_el_t result;
4315 if (first_free_automata_list_el != NULL)
4317 result = first_free_automata_list_el;
4318 first_free_automata_list_el
4319 = first_free_automata_list_el->next_automata_list_el;
4321 else
4322 result = create_node (sizeof (struct automata_list_el));
4323 result->automaton = NULL;
4324 result->next_automata_list_el = NULL;
4325 return result;
4328 /* The function frees node AUTOMATA_LIST_EL. */
4329 static void
4330 free_automata_list_el (automata_list_el)
4331 automata_list_el_t automata_list_el;
4333 if (automata_list_el == NULL)
4334 return;
4335 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4336 first_free_automata_list_el = automata_list_el;
4339 /* The function frees list AUTOMATA_LIST. */
4340 static void
4341 free_automata_list (automata_list)
4342 automata_list_el_t automata_list;
4344 automata_list_el_t curr_automata_list_el;
4345 automata_list_el_t next_automata_list_el;
4347 for (curr_automata_list_el = automata_list;
4348 curr_automata_list_el != NULL;
4349 curr_automata_list_el = next_automata_list_el)
4351 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4352 free_automata_list_el (curr_automata_list_el);
4356 /* Hash value of AUTOMATA_LIST. */
4357 static unsigned
4358 automata_list_hash (automata_list)
4359 const void *automata_list;
4361 unsigned int hash_value;
4362 automata_list_el_t curr_automata_list_el;
4364 hash_value = 0;
4365 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4366 curr_automata_list_el != NULL;
4367 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4368 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4369 | (hash_value << CHAR_BIT))
4370 + curr_automata_list_el->automaton->automaton_order_num);
4371 return hash_value;
4374 /* Return nonzero value if the automata_lists are the same. */
4375 static int
4376 automata_list_eq_p (automata_list_1, automata_list_2)
4377 const void *automata_list_1;
4378 const void *automata_list_2;
4380 automata_list_el_t automata_list_el_1;
4381 automata_list_el_t automata_list_el_2;
4383 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4384 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4385 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4386 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4387 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4388 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4389 return 0;
4390 return automata_list_el_1 == automata_list_el_2;
4393 /* Initialization of the abstract data. */
4394 static void
4395 initiate_automata_lists ()
4397 first_free_automata_list_el = NULL;
4398 automata_list_table = htab_create (1500, automata_list_hash,
4399 automata_list_eq_p, (htab_del) 0);
4402 /* The following function starts new automata list and makes it the
4403 current one. */
4404 static void
4405 automata_list_start ()
4407 current_automata_list = NULL;
4410 /* The following function adds AUTOMATON to the current list. */
4411 static void
4412 automata_list_add (automaton)
4413 automaton_t automaton;
4415 automata_list_el_t el;
4417 el = get_free_automata_list_el ();
4418 el->automaton = automaton;
4419 el->next_automata_list_el = current_automata_list;
4420 current_automata_list = el;
4423 /* The following function finishes forming the current list, inserts
4424 it into the table and returns it. */
4425 static automata_list_el_t
4426 automata_list_finish ()
4428 void **entry_ptr;
4430 if (current_automata_list == NULL)
4431 return NULL;
4432 entry_ptr = htab_find_slot (automata_list_table,
4433 (void *) current_automata_list, 1);
4434 if (*entry_ptr == NULL)
4435 *entry_ptr = (void *) current_automata_list;
4436 else
4437 free_automata_list (current_automata_list);
4438 current_automata_list = NULL;
4439 return (automata_list_el_t) *entry_ptr;
4442 /* Finishing work with the abstract data. */
4443 static void
4444 finish_automata_lists ()
4446 htab_delete (automata_list_table);
4451 /* The page contains abstract data for work with exclusion sets (see
4452 exclusion_set in file rtl.def). */
4454 /* The following variable refers to an exclusion set returned by
4455 get_excl_set. This is bit string of length equal to cpu units
4456 number. If exclusion set for given unit contains 1 for a unit,
4457 then simultaneous reservation of the units is prohibited. */
4458 static reserv_sets_t excl_set;
4460 /* The array contains exclusion sets for each unit. */
4461 static reserv_sets_t *unit_excl_set_table;
4463 /* The following function forms the array containing exclusion sets
4464 for each unit. */
4465 static void
4466 initiate_excl_sets ()
4468 decl_t decl;
4469 reserv_sets_t unit_excl_set;
4470 unit_set_el_t el;
4471 int i;
4473 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4474 excl_set = (reserv_sets_t) obstack_base (&irp);
4475 obstack_finish (&irp);
4476 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4477 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4478 obstack_finish (&irp);
4479 /* Evaluate unit exclusion sets. */
4480 for (i = 0; i < description->decls_num; i++)
4482 decl = description->decls [i];
4483 if (decl->mode == dm_unit)
4485 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4486 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4487 obstack_finish (&irp);
4488 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4489 for (el = DECL_UNIT (decl)->excl_list;
4490 el != NULL;
4491 el = el->next_unit_set_el)
4492 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4493 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4498 /* The function sets up and return EXCL_SET which is union of
4499 exclusion sets for each unit in IN_SET. */
4500 static reserv_sets_t
4501 get_excl_set (in_set)
4502 reserv_sets_t in_set;
4504 int excl_char_num;
4505 int chars_num;
4506 int i;
4507 int start_unit_num;
4508 int unit_num;
4510 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4511 memset (excl_set, 0, chars_num);
4512 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4513 if (((unsigned char *) in_set) [excl_char_num])
4514 for (i = CHAR_BIT - 1; i >= 0; i--)
4515 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4517 start_unit_num = excl_char_num * CHAR_BIT + i;
4518 if (start_unit_num >= description->units_num)
4519 return excl_set;
4520 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4522 excl_set [unit_num]
4523 |= unit_excl_set_table [start_unit_num] [unit_num];
4526 return excl_set;
4531 /* The page contains abstract data for work with presence/absence sets
4532 (see presence_set/absence_set in file rtl.def). */
4534 /* The following variables refer to correspondingly an presence and an
4535 absence set returned by get_presence_absence_set. This is bit
4536 string of length equal to cpu units number. */
4537 static reserv_sets_t presence_set, absence_set;
4539 /* The following arrays contain correspondingly presence and absence
4540 sets for each unit. */
4541 static reserv_sets_t *unit_presence_set_table, *unit_absence_set_table;
4543 /* The following function forms the array containing presence and
4544 absence sets for each unit */
4545 static void
4546 initiate_presence_absence_sets ()
4548 decl_t decl;
4549 reserv_sets_t unit_set;
4550 unit_set_el_t el;
4551 int i;
4553 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4554 presence_set = (reserv_sets_t) obstack_base (&irp);
4555 obstack_finish (&irp);
4556 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4557 unit_presence_set_table = (reserv_sets_t *) obstack_base (&irp);
4558 obstack_finish (&irp);
4559 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4560 absence_set = (reserv_sets_t) obstack_base (&irp);
4561 obstack_finish (&irp);
4562 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4563 unit_absence_set_table = (reserv_sets_t *) obstack_base (&irp);
4564 obstack_finish (&irp);
4565 /* Evaluate unit presence/absence sets. */
4566 for (i = 0; i < description->decls_num; i++)
4568 decl = description->decls [i];
4569 if (decl->mode == dm_unit)
4571 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4572 unit_set = (reserv_sets_t) obstack_base (&irp);
4573 obstack_finish (&irp);
4574 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4575 for (el = DECL_UNIT (decl)->presence_list;
4576 el != NULL;
4577 el = el->next_unit_set_el)
4578 SET_BIT (unit_set, el->unit_decl->unit_num);
4579 unit_presence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4581 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4582 unit_set = (reserv_sets_t) obstack_base (&irp);
4583 obstack_finish (&irp);
4584 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4585 for (el = DECL_UNIT (decl)->absence_list;
4586 el != NULL;
4587 el = el->next_unit_set_el)
4588 SET_BIT (unit_set, el->unit_decl->unit_num);
4589 unit_absence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4594 /* The function sets up and return PRESENCE_SET (if PRESENCE_P) or
4595 ABSENCE_SET which is union of corresponding sets for each unit in
4596 IN_SET. */
4597 static reserv_sets_t
4598 get_presence_absence_set (in_set, presence_p)
4599 reserv_sets_t in_set;
4600 int presence_p;
4602 int char_num;
4603 int chars_num;
4604 int i;
4605 int start_unit_num;
4606 int unit_num;
4608 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4609 if (presence_p)
4610 memset (presence_set, 0, chars_num);
4611 else
4612 memset (absence_set, 0, chars_num);
4613 for (char_num = 0; char_num < chars_num; char_num++)
4614 if (((unsigned char *) in_set) [char_num])
4615 for (i = CHAR_BIT - 1; i >= 0; i--)
4616 if ((((unsigned char *) in_set) [char_num] >> i) & 1)
4618 start_unit_num = char_num * CHAR_BIT + i;
4619 if (start_unit_num >= description->units_num)
4620 return (presence_p ? presence_set : absence_set);
4621 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4622 if (presence_p)
4623 presence_set [unit_num]
4624 |= unit_presence_set_table [start_unit_num] [unit_num];
4625 else
4626 absence_set [unit_num]
4627 |= unit_absence_set_table [start_unit_num] [unit_num];
4629 return (presence_p ? presence_set : absence_set);
4634 /* This page contains code for transformation of original reservations
4635 described in .md file. The main goal of transformations is
4636 simplifying reservation and lifting up all `|' on the top of IR
4637 reservation representation. */
4640 /* The following function makes copy of IR representation of
4641 reservation. The function also substitutes all reservations
4642 defined by define_reservation by corresponding value during making
4643 the copy. */
4644 static regexp_t
4645 copy_insn_regexp (regexp)
4646 regexp_t regexp;
4648 regexp_t result;
4649 int i;
4651 if (regexp->mode == rm_reserv)
4652 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4653 else if (regexp->mode == rm_unit)
4654 result = copy_node (regexp, sizeof (struct regexp));
4655 else if (regexp->mode == rm_repeat)
4657 result = copy_node (regexp, sizeof (struct regexp));
4658 REGEXP_REPEAT (result)->regexp
4659 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4661 else if (regexp->mode == rm_sequence)
4663 result = copy_node (regexp,
4664 sizeof (struct regexp) + sizeof (regexp_t)
4665 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4666 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4667 REGEXP_SEQUENCE (result)->regexps [i]
4668 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4670 else if (regexp->mode == rm_allof)
4672 result = copy_node (regexp,
4673 sizeof (struct regexp) + sizeof (regexp_t)
4674 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4675 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4676 REGEXP_ALLOF (result)->regexps [i]
4677 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4679 else if (regexp->mode == rm_oneof)
4681 result = copy_node (regexp,
4682 sizeof (struct regexp) + sizeof (regexp_t)
4683 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4684 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4685 REGEXP_ONEOF (result)->regexps [i]
4686 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4688 else
4690 if (regexp->mode != rm_nothing)
4691 abort ();
4692 result = copy_node (regexp, sizeof (struct regexp));
4694 return result;
4697 /* The following variable is set up 1 if a transformation has been
4698 applied. */
4699 static int regexp_transformed_p;
4701 /* The function makes transformation
4702 A*N -> A, A, ... */
4703 static regexp_t
4704 transform_1 (regexp)
4705 regexp_t regexp;
4707 int i;
4708 int repeat_num;
4709 regexp_t operand;
4710 pos_t pos;
4712 if (regexp->mode == rm_repeat)
4714 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4715 if (repeat_num <= 1)
4716 abort ();
4717 operand = REGEXP_REPEAT (regexp)->regexp;
4718 pos = regexp->mode;
4719 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4720 * (repeat_num - 1));
4721 regexp->mode = rm_sequence;
4722 regexp->pos = pos;
4723 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4724 for (i = 0; i < repeat_num; i++)
4725 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4726 regexp_transformed_p = 1;
4728 return regexp;
4731 /* The function makes transformations
4732 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4733 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4734 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4735 static regexp_t
4736 transform_2 (regexp)
4737 regexp_t regexp;
4739 if (regexp->mode == rm_sequence)
4741 regexp_t sequence = NULL;
4742 regexp_t result;
4743 int sequence_index = 0;
4744 int i, j;
4746 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4747 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4749 sequence_index = i;
4750 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4751 break;
4753 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4755 if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
4756 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4757 abort ();
4758 result = create_node (sizeof (struct regexp)
4759 + sizeof (regexp_t)
4760 * (REGEXP_SEQUENCE (regexp)->regexps_num
4761 + REGEXP_SEQUENCE (sequence)->regexps_num
4762 - 2));
4763 result->mode = rm_sequence;
4764 result->pos = regexp->pos;
4765 REGEXP_SEQUENCE (result)->regexps_num
4766 = (REGEXP_SEQUENCE (regexp)->regexps_num
4767 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4768 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4769 if (i < sequence_index)
4770 REGEXP_SEQUENCE (result)->regexps [i]
4771 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4772 else if (i > sequence_index)
4773 REGEXP_SEQUENCE (result)->regexps
4774 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4775 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4776 else
4777 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4778 REGEXP_SEQUENCE (result)->regexps [i + j]
4779 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4780 regexp_transformed_p = 1;
4781 regexp = result;
4784 else if (regexp->mode == rm_allof)
4786 regexp_t allof = NULL;
4787 regexp_t result;
4788 int allof_index = 0;
4789 int i, j;
4791 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4792 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4794 allof_index = i;
4795 allof = REGEXP_ALLOF (regexp)->regexps [i];
4796 break;
4798 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4800 if (REGEXP_ALLOF (allof)->regexps_num <= 1
4801 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4802 abort ();
4803 result = create_node (sizeof (struct regexp)
4804 + sizeof (regexp_t)
4805 * (REGEXP_ALLOF (regexp)->regexps_num
4806 + REGEXP_ALLOF (allof)->regexps_num - 2));
4807 result->mode = rm_allof;
4808 result->pos = regexp->pos;
4809 REGEXP_ALLOF (result)->regexps_num
4810 = (REGEXP_ALLOF (regexp)->regexps_num
4811 + REGEXP_ALLOF (allof)->regexps_num - 1);
4812 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4813 if (i < allof_index)
4814 REGEXP_ALLOF (result)->regexps [i]
4815 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4816 else if (i > allof_index)
4817 REGEXP_ALLOF (result)->regexps
4818 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4819 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4820 else
4821 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4822 REGEXP_ALLOF (result)->regexps [i + j]
4823 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4824 regexp_transformed_p = 1;
4825 regexp = result;
4828 else if (regexp->mode == rm_oneof)
4830 regexp_t oneof = NULL;
4831 regexp_t result;
4832 int oneof_index = 0;
4833 int i, j;
4835 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4836 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4838 oneof_index = i;
4839 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4840 break;
4842 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4844 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4845 || REGEXP_ONEOF (regexp)->regexps_num <= 1)
4846 abort ();
4847 result = create_node (sizeof (struct regexp)
4848 + sizeof (regexp_t)
4849 * (REGEXP_ONEOF (regexp)->regexps_num
4850 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4851 result->mode = rm_oneof;
4852 result->pos = regexp->pos;
4853 REGEXP_ONEOF (result)->regexps_num
4854 = (REGEXP_ONEOF (regexp)->regexps_num
4855 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4856 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4857 if (i < oneof_index)
4858 REGEXP_ONEOF (result)->regexps [i]
4859 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4860 else if (i > oneof_index)
4861 REGEXP_ONEOF (result)->regexps
4862 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4863 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4864 else
4865 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4866 REGEXP_ONEOF (result)->regexps [i + j]
4867 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4868 regexp_transformed_p = 1;
4869 regexp = result;
4872 return regexp;
4875 /* The function makes transformations
4876 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4877 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4878 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4879 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4880 static regexp_t
4881 transform_3 (regexp)
4882 regexp_t regexp;
4884 if (regexp->mode == rm_sequence)
4886 regexp_t oneof = NULL;
4887 int oneof_index = 0;
4888 regexp_t result;
4889 regexp_t sequence;
4890 int i, j;
4892 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4893 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4895 oneof_index = i;
4896 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4897 break;
4899 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4901 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4902 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4903 abort ();
4904 result = create_node (sizeof (struct regexp)
4905 + sizeof (regexp_t)
4906 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4907 result->mode = rm_oneof;
4908 result->pos = regexp->pos;
4909 REGEXP_ONEOF (result)->regexps_num
4910 = REGEXP_ONEOF (oneof)->regexps_num;
4911 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4913 sequence
4914 = create_node (sizeof (struct regexp)
4915 + sizeof (regexp_t)
4916 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4917 sequence->mode = rm_sequence;
4918 sequence->pos = regexp->pos;
4919 REGEXP_SEQUENCE (sequence)->regexps_num
4920 = REGEXP_SEQUENCE (regexp)->regexps_num;
4921 REGEXP_ONEOF (result)->regexps [i] = sequence;
4922 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4923 if (j != oneof_index)
4924 REGEXP_SEQUENCE (sequence)->regexps [j]
4925 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4926 else
4927 REGEXP_SEQUENCE (sequence)->regexps [j]
4928 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4930 regexp_transformed_p = 1;
4931 regexp = result;
4934 else if (regexp->mode == rm_allof)
4936 regexp_t oneof = NULL, seq;
4937 int oneof_index = 0, max_seq_length, allof_length;
4938 regexp_t result;
4939 regexp_t allof = NULL, allof_op = NULL;
4940 int i, j;
4942 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4943 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4945 oneof_index = i;
4946 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4947 break;
4949 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4951 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4952 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4953 abort ();
4954 result = create_node (sizeof (struct regexp)
4955 + sizeof (regexp_t)
4956 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4957 result->mode = rm_oneof;
4958 result->pos = regexp->pos;
4959 REGEXP_ONEOF (result)->regexps_num
4960 = REGEXP_ONEOF (oneof)->regexps_num;
4961 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4963 allof
4964 = create_node (sizeof (struct regexp)
4965 + sizeof (regexp_t)
4966 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4967 allof->mode = rm_allof;
4968 allof->pos = regexp->pos;
4969 REGEXP_ALLOF (allof)->regexps_num
4970 = REGEXP_ALLOF (regexp)->regexps_num;
4971 REGEXP_ONEOF (result)->regexps [i] = allof;
4972 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4973 if (j != oneof_index)
4974 REGEXP_ALLOF (allof)->regexps [j]
4975 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4976 else
4977 REGEXP_ALLOF (allof)->regexps [j]
4978 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4980 regexp_transformed_p = 1;
4981 regexp = result;
4983 max_seq_length = 0;
4984 if (regexp->mode == rm_allof)
4985 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;
4997 if (max_seq_length != 0)
4999 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5000 abort ();
5001 result = create_node (sizeof (struct regexp)
5002 + sizeof (regexp_t) * (max_seq_length - 1));
5003 result->mode = rm_sequence;
5004 result->pos = regexp->pos;
5005 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5006 for (i = 0; i < max_seq_length; i++)
5008 allof_length = 0;
5009 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5010 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5011 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5012 ->regexps [j])->regexps_num)))
5014 allof_op
5015 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5016 ->regexps [i]);
5017 allof_length++;
5019 else if (i == 0
5020 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5021 == rm_unit))
5023 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5024 allof_length++;
5026 if (allof_length == 1)
5027 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5028 else
5030 allof = create_node (sizeof (struct regexp)
5031 + sizeof (regexp_t)
5032 * (allof_length - 1));
5033 allof->mode = rm_allof;
5034 allof->pos = regexp->pos;
5035 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5036 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5037 allof_length = 0;
5038 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5039 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5040 && (i <
5041 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5042 ->regexps [j])->regexps_num)))
5044 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5045 ->regexps [j])
5046 ->regexps [i]);
5047 REGEXP_ALLOF (allof)->regexps [allof_length]
5048 = allof_op;
5049 allof_length++;
5051 else if (i == 0
5052 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5053 == rm_unit))
5055 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5056 REGEXP_ALLOF (allof)->regexps [allof_length]
5057 = allof_op;
5058 allof_length++;
5062 regexp_transformed_p = 1;
5063 regexp = result;
5066 return regexp;
5069 /* The function traverses IR of reservation and applies transformations
5070 implemented by FUNC. */
5071 static regexp_t
5072 regexp_transform_func (regexp, func)
5073 regexp_t regexp;
5074 regexp_t (*func) PARAMS ((regexp_t regexp));
5076 int i;
5078 if (regexp->mode == rm_sequence)
5079 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5080 REGEXP_SEQUENCE (regexp)->regexps [i]
5081 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5082 else if (regexp->mode == rm_allof)
5083 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5084 REGEXP_ALLOF (regexp)->regexps [i]
5085 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5086 else if (regexp->mode == rm_oneof)
5087 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5088 REGEXP_ONEOF (regexp)->regexps [i]
5089 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5090 else if (regexp->mode == rm_repeat)
5091 REGEXP_REPEAT (regexp)->regexp
5092 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5093 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5094 abort ();
5095 return (*func) (regexp);
5098 /* The function applies all transformations for IR representation of
5099 reservation REGEXP. */
5100 static regexp_t
5101 transform_regexp (regexp)
5102 regexp_t regexp;
5104 regexp = regexp_transform_func (regexp, transform_1);
5107 regexp_transformed_p = 0;
5108 regexp = regexp_transform_func (regexp, transform_2);
5109 regexp = regexp_transform_func (regexp, transform_3);
5111 while (regexp_transformed_p);
5112 return regexp;
5115 /* The function applys all transformations for reservations of all
5116 insn declarations. */
5117 static void
5118 transform_insn_regexps ()
5120 decl_t decl;
5121 int i;
5123 transform_time = create_ticker ();
5124 add_advance_cycle_insn_decl ();
5125 fprintf (stderr, "Reservation transformation...");
5126 fflush (stderr);
5127 for (i = 0; i < description->decls_num; i++)
5129 decl = description->decls [i];
5130 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5131 DECL_INSN_RESERV (decl)->transformed_regexp
5132 = transform_regexp (copy_insn_regexp
5133 (DECL_INSN_RESERV (decl)->regexp));
5135 fprintf (stderr, "done\n");
5136 ticker_off (&transform_time);
5137 fflush (stderr);
5142 /* The following variable is an array indexed by cycle. Each element
5143 contains cyclic list of units which should be in the same cycle. */
5144 static unit_decl_t *the_same_automaton_lists;
5146 /* The function processes all alternative reservations on CYCLE in
5147 given REGEXP to check the UNIT is not reserved on the all
5148 alternatives. If it is true, the unit should be in the same
5149 automaton with other analogous units reserved on CYCLE in given
5150 REGEXP. */
5151 static void
5152 process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
5153 regexp_t unit;
5154 regexp_t regexp;
5155 int cycle;
5157 int i, k;
5158 regexp_t seq, allof;
5159 unit_decl_t unit_decl, last;
5161 if (regexp == NULL || regexp->mode != rm_oneof)
5162 abort ();
5163 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5164 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5166 seq = REGEXP_ONEOF (regexp)->regexps [i];
5167 if (seq->mode == rm_sequence)
5169 if (cycle >= REGEXP_SEQUENCE (seq)->regexps_num)
5170 break;
5171 allof = REGEXP_SEQUENCE (seq)->regexps [cycle];
5172 if (allof->mode == rm_allof)
5174 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5175 if (REGEXP_ALLOF (allof)->regexps [k]->mode == rm_unit
5176 && (REGEXP_UNIT (REGEXP_ALLOF (allof)->regexps [k])
5177 ->unit_decl == unit_decl))
5178 break;
5179 if (k >= REGEXP_ALLOF (allof)->regexps_num)
5180 break;
5182 else if (allof->mode == rm_unit
5183 && REGEXP_UNIT (allof)->unit_decl != unit_decl)
5184 break;
5186 else if (cycle != 0)
5187 break;
5188 else if (seq->mode == rm_allof)
5190 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5191 if (REGEXP_ALLOF (seq)->regexps [k]->mode == rm_unit
5192 && (REGEXP_UNIT (REGEXP_ALLOF (seq)->regexps [k])->unit_decl
5193 == unit_decl))
5194 break;
5195 if (k >= REGEXP_ALLOF (seq)->regexps_num)
5196 break;
5198 else if (seq->mode == rm_unit
5199 && REGEXP_UNIT (seq)->unit_decl != unit_decl)
5200 break;
5202 if (i >= 0)
5204 if (the_same_automaton_lists [cycle] == NULL)
5205 the_same_automaton_lists [cycle] = unit_decl;
5206 else
5208 for (last = the_same_automaton_lists [cycle];;)
5210 if (last == unit_decl)
5211 return;
5212 if (last->the_same_automaton_unit
5213 == the_same_automaton_lists [cycle])
5214 break;
5215 last = last->the_same_automaton_unit;
5217 last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
5218 unit_decl->the_same_automaton_unit
5219 = the_same_automaton_lists [cycle];
5224 /* The function processes given REGEXP to find units which should be
5225 in the same automaton. */
5226 static void
5227 form_the_same_automaton_unit_lists_from_regexp (regexp)
5228 regexp_t regexp;
5230 int i, j, k;
5231 regexp_t seq, allof, unit;
5233 if (regexp == NULL || regexp->mode != rm_oneof)
5234 return;
5235 for (i = 0; i < description->max_insn_reserv_cycles; i++)
5236 the_same_automaton_lists [i] = NULL;
5237 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5239 seq = REGEXP_ONEOF (regexp)->regexps [i];
5240 if (seq->mode == rm_sequence)
5241 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5243 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5244 if (allof->mode == rm_allof)
5245 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5247 unit = REGEXP_ALLOF (allof)->regexps [k];
5248 if (unit->mode == rm_unit)
5249 process_unit_to_form_the_same_automaton_unit_lists
5250 (unit, regexp, j);
5251 else if (unit->mode != rm_nothing)
5252 abort ();
5254 else if (allof->mode == rm_unit)
5255 process_unit_to_form_the_same_automaton_unit_lists
5256 (allof, regexp, j);
5257 else if (allof->mode != rm_nothing)
5258 abort ();
5260 else if (seq->mode == rm_allof)
5261 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5263 unit = REGEXP_ALLOF (seq)->regexps [k];
5264 if (unit->mode == rm_unit)
5265 process_unit_to_form_the_same_automaton_unit_lists
5266 (unit, regexp, 0);
5267 else if (unit->mode != rm_nothing)
5268 abort ();
5270 else if (seq->mode == rm_unit)
5271 process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
5272 else if (seq->mode != rm_nothing)
5273 abort ();
5277 /* The function initializes data to search for units which should be
5278 in the same automaton and call function
5279 `form_the_same_automaton_unit_lists_from_regexp' for each insn
5280 reservation regexp. */
5281 static void
5282 form_the_same_automaton_unit_lists ()
5284 decl_t decl;
5285 int i;
5287 the_same_automaton_lists
5288 = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
5289 * sizeof (unit_decl_t));
5290 for (i = 0; i < description->decls_num; i++)
5292 decl = description->decls [i];
5293 if (decl->mode == dm_unit)
5295 DECL_UNIT (decl)->the_same_automaton_message_reported_p = FALSE;
5296 DECL_UNIT (decl)->the_same_automaton_unit = DECL_UNIT (decl);
5299 for (i = 0; i < description->decls_num; i++)
5301 decl = description->decls [i];
5302 if (decl->mode == dm_insn_reserv)
5303 form_the_same_automaton_unit_lists_from_regexp
5304 (DECL_INSN_RESERV (decl)->transformed_regexp);
5306 free (the_same_automaton_lists);
5309 /* The function finds units which should be in the same automaton and,
5310 if they are not, reports about it. */
5311 static void
5312 check_unit_distributions_to_automata ()
5314 decl_t decl;
5315 unit_decl_t start_unit_decl, unit_decl;
5316 int i;
5318 form_the_same_automaton_unit_lists ();
5319 for (i = 0; i < description->decls_num; i++)
5321 decl = description->decls [i];
5322 if (decl->mode == dm_unit)
5324 start_unit_decl = DECL_UNIT (decl);
5325 if (!start_unit_decl->the_same_automaton_message_reported_p)
5326 for (unit_decl = start_unit_decl->the_same_automaton_unit;
5327 unit_decl != start_unit_decl;
5328 unit_decl = unit_decl->the_same_automaton_unit)
5329 if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
5331 error ("Units `%s' and `%s' should be in the same automaton",
5332 start_unit_decl->name, unit_decl->name);
5333 unit_decl->the_same_automaton_message_reported_p = TRUE;
5341 /* The page contains code for building alt_states (see comments for
5342 IR) describing all possible insns reservations of an automaton. */
5344 /* Current state being formed for which the current alt_state
5345 refers. */
5346 static state_t state_being_formed;
5348 /* Current alt_state being formed. */
5349 static alt_state_t alt_state_being_formed;
5351 /* This recursive function processes `,' and units in reservation
5352 REGEXP for forming alt_states of AUTOMATON. It is believed that
5353 CURR_CYCLE is start cycle of all reservation REGEXP. */
5354 static int
5355 process_seq_for_forming_states (regexp, automaton, curr_cycle)
5356 regexp_t regexp;
5357 automaton_t automaton;
5358 int curr_cycle;
5360 int i;
5362 if (regexp == NULL)
5363 return curr_cycle;
5364 else if (regexp->mode == rm_unit)
5366 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5367 == automaton->automaton_order_num)
5368 set_state_reserv (state_being_formed, curr_cycle,
5369 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5370 return curr_cycle;
5372 else if (regexp->mode == rm_sequence)
5374 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5375 curr_cycle
5376 = process_seq_for_forming_states
5377 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5378 return curr_cycle;
5380 else if (regexp->mode == rm_allof)
5382 int finish_cycle = 0;
5383 int cycle;
5385 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5387 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5388 ->regexps [i],
5389 automaton, curr_cycle);
5390 if (finish_cycle < cycle)
5391 finish_cycle = cycle;
5393 return finish_cycle;
5395 else
5397 if (regexp->mode != rm_nothing)
5398 abort ();
5399 return curr_cycle;
5403 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5404 inserts alt_state into the table. */
5405 static void
5406 finish_forming_alt_state (alt_state, automaton)
5407 alt_state_t alt_state;
5408 automaton_t automaton ATTRIBUTE_UNUSED;
5410 state_t state_in_table;
5411 state_t corresponding_state;
5413 corresponding_state = alt_state->state;
5414 state_in_table = insert_state (corresponding_state);
5415 if (state_in_table != corresponding_state)
5417 free_state (corresponding_state);
5418 alt_state->state = state_in_table;
5422 /* The following variable value is current automaton insn for whose
5423 reservation the alt states are created. */
5424 static ainsn_t curr_ainsn;
5426 /* This recursive function processes `|' in reservation REGEXP for
5427 forming alt_states of AUTOMATON. List of the alt states should
5428 have the same order as in the description. */
5429 static void
5430 process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5431 regexp_t regexp;
5432 automaton_t automaton;
5433 int inside_oneof_p;
5435 int i;
5437 if (regexp->mode != rm_oneof)
5439 alt_state_being_formed = get_free_alt_state ();
5440 state_being_formed = get_free_state (1, automaton);
5441 alt_state_being_formed->state = state_being_formed;
5442 /* We inserts in reverse order but we process alternatives also
5443 in reverse order. So we have the same order of alternative
5444 as in the description. */
5445 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5446 curr_ainsn->alt_states = alt_state_being_formed;
5447 (void) process_seq_for_forming_states (regexp, automaton, 0);
5448 finish_forming_alt_state (alt_state_being_formed, automaton);
5450 else
5452 if (inside_oneof_p)
5453 abort ();
5454 /* We processes it in reverse order to get list with the same
5455 order as in the description. See also the previous
5456 commentary. */
5457 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5458 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5459 automaton, 1);
5463 /* Create nodes alt_state for all AUTOMATON insns. */
5464 static void
5465 create_alt_states (automaton)
5466 automaton_t automaton;
5468 struct insn_reserv_decl *reserv_decl;
5470 for (curr_ainsn = automaton->ainsn_list;
5471 curr_ainsn != NULL;
5472 curr_ainsn = curr_ainsn->next_ainsn)
5474 reserv_decl = curr_ainsn->insn_reserv_decl;
5475 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5477 curr_ainsn->alt_states = NULL;
5478 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5479 automaton, 0);
5480 curr_ainsn->sorted_alt_states
5481 = uniq_sort_alt_states (curr_ainsn->alt_states);
5488 /* The page contains major code for building DFA(s) for fast pipeline
5489 hazards recognition. */
5491 /* The function forms list of ainsns of AUTOMATON with the same
5492 reservation. */
5493 static void
5494 form_ainsn_with_same_reservs (automaton)
5495 automaton_t automaton;
5497 ainsn_t curr_ainsn;
5498 size_t i;
5499 vla_ptr_t first_insns;
5500 vla_ptr_t last_insns;
5502 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5503 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5504 for (curr_ainsn = automaton->ainsn_list;
5505 curr_ainsn != NULL;
5506 curr_ainsn = curr_ainsn->next_ainsn)
5507 if (curr_ainsn->insn_reserv_decl
5508 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5510 curr_ainsn->next_same_reservs_insn = NULL;
5511 curr_ainsn->first_insn_with_same_reservs = 1;
5513 else
5515 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5516 if (alt_states_eq
5517 (curr_ainsn->sorted_alt_states,
5518 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5519 break;
5520 curr_ainsn->next_same_reservs_insn = NULL;
5521 if (i < VLA_PTR_LENGTH (first_insns))
5523 curr_ainsn->first_insn_with_same_reservs = 0;
5524 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5525 = curr_ainsn;
5526 VLA_PTR (last_insns, i) = curr_ainsn;
5528 else
5530 VLA_PTR_ADD (first_insns, curr_ainsn);
5531 VLA_PTR_ADD (last_insns, curr_ainsn);
5532 curr_ainsn->first_insn_with_same_reservs = 1;
5535 VLA_PTR_DELETE (first_insns);
5536 VLA_PTR_DELETE (last_insns);
5539 /* The following function creates all states of nondeterministic (if
5540 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5541 static void
5542 make_automaton (automaton)
5543 automaton_t automaton;
5545 ainsn_t ainsn;
5546 struct insn_reserv_decl *insn_reserv_decl;
5547 alt_state_t alt_state;
5548 state_t state;
5549 state_t start_state;
5550 state_t state2;
5551 ainsn_t advance_cycle_ainsn;
5552 arc_t added_arc;
5553 vla_ptr_t state_stack;
5555 VLA_PTR_CREATE (state_stack, 150, "state stack");
5556 /* Create the start state (empty state). */
5557 start_state = insert_state (get_free_state (1, automaton));
5558 automaton->start_state = start_state;
5559 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5560 VLA_PTR_ADD (state_stack, start_state);
5561 while (VLA_PTR_LENGTH (state_stack) != 0)
5563 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5564 VLA_PTR_SHORTEN (state_stack, 1);
5565 advance_cycle_ainsn = NULL;
5566 for (ainsn = automaton->ainsn_list;
5567 ainsn != NULL;
5568 ainsn = ainsn->next_ainsn)
5569 if (ainsn->first_insn_with_same_reservs)
5571 insn_reserv_decl = ainsn->insn_reserv_decl;
5572 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5574 /* We process alt_states in the same order as they are
5575 present in the description. */
5576 added_arc = NULL;
5577 for (alt_state = ainsn->alt_states;
5578 alt_state != NULL;
5579 alt_state = alt_state->next_alt_state)
5581 state2 = alt_state->state;
5582 if (!intersected_state_reservs_p (state, state2))
5584 state2 = states_union (state, state2);
5585 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5587 state2->it_was_placed_in_stack_for_NDFA_forming
5588 = 1;
5589 VLA_PTR_ADD (state_stack, state2);
5591 added_arc = add_arc (state, state2, ainsn, 1);
5592 if (!ndfa_flag)
5593 break;
5596 if (!ndfa_flag && added_arc != NULL)
5598 added_arc->state_alts = 0;
5599 for (alt_state = ainsn->alt_states;
5600 alt_state != NULL;
5601 alt_state = alt_state->next_alt_state)
5603 state2 = alt_state->state;
5604 if (!intersected_state_reservs_p (state, state2))
5605 added_arc->state_alts++;
5609 else
5610 advance_cycle_ainsn = ainsn;
5612 /* Add transition to advance cycle. */
5613 state2 = state_shift (state);
5614 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5616 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5617 VLA_PTR_ADD (state_stack, state2);
5619 if (advance_cycle_ainsn == NULL)
5620 abort ();
5621 add_arc (state, state2, advance_cycle_ainsn, 1);
5623 VLA_PTR_DELETE (state_stack);
5626 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5627 static void
5628 form_arcs_marked_by_insn (state)
5629 state_t state;
5631 decl_t decl;
5632 arc_t arc;
5633 int i;
5635 for (i = 0; i < description->decls_num; i++)
5637 decl = description->decls [i];
5638 if (decl->mode == dm_insn_reserv)
5639 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5641 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5643 if (arc->insn == NULL)
5644 abort ();
5645 arc->next_arc_marked_by_insn
5646 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5647 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5651 /* The function creates composed state (see comments for IR) from
5652 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5653 same insn. If the composed state is not in STATE_STACK yet, it is
5654 popped to STATE_STACK. */
5655 static void
5656 create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5657 state_t original_state;
5658 arc_t arcs_marked_by_insn;
5659 vla_ptr_t *state_stack;
5661 state_t state;
5662 alt_state_t curr_alt_state;
5663 alt_state_t new_alt_state;
5664 arc_t curr_arc;
5665 arc_t next_arc;
5666 state_t state_in_table;
5667 state_t temp_state;
5668 alt_state_t canonical_alt_states_list;
5669 int alts_number;
5671 if (arcs_marked_by_insn == NULL)
5672 return;
5673 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5674 state = arcs_marked_by_insn->to_state;
5675 else
5677 if (!ndfa_flag)
5678 abort ();
5679 /* Create composed state. */
5680 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5681 curr_alt_state = NULL;
5682 for (curr_arc = arcs_marked_by_insn;
5683 curr_arc != NULL;
5684 curr_arc = curr_arc->next_arc_marked_by_insn)
5686 new_alt_state = get_free_alt_state ();
5687 new_alt_state->next_alt_state = curr_alt_state;
5688 new_alt_state->state = curr_arc->to_state;
5689 if (curr_arc->to_state->component_states != NULL)
5690 abort ();
5691 curr_alt_state = new_alt_state;
5693 /* There are not identical sets in the alt state list. */
5694 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5695 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5697 temp_state = state;
5698 state = canonical_alt_states_list->state;
5699 free_state (temp_state);
5701 else
5703 state->component_states = canonical_alt_states_list;
5704 state_in_table = insert_state (state);
5705 if (state_in_table != state)
5707 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5708 abort ();
5709 free_state (state);
5710 state = state_in_table;
5712 else
5714 if (state->it_was_placed_in_stack_for_DFA_forming)
5715 abort ();
5716 for (curr_alt_state = state->component_states;
5717 curr_alt_state != NULL;
5718 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5719 for (curr_arc = first_out_arc (curr_alt_state->state);
5720 curr_arc != NULL;
5721 curr_arc = next_out_arc (curr_arc))
5722 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5724 arcs_marked_by_insn->to_state = state;
5725 for (alts_number = 0,
5726 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5727 curr_arc != NULL;
5728 curr_arc = next_arc)
5730 next_arc = curr_arc->next_arc_marked_by_insn;
5731 remove_arc (original_state, curr_arc);
5732 alts_number++;
5734 arcs_marked_by_insn->state_alts = alts_number;
5737 if (!state->it_was_placed_in_stack_for_DFA_forming)
5739 state->it_was_placed_in_stack_for_DFA_forming = 1;
5740 VLA_PTR_ADD (*state_stack, state);
5744 /* The function transformes nondeterminstic AUTOMATON into
5745 deterministic. */
5746 static void
5747 NDFA_to_DFA (automaton)
5748 automaton_t automaton;
5750 state_t start_state;
5751 state_t state;
5752 decl_t decl;
5753 vla_ptr_t state_stack;
5754 int i;
5756 VLA_PTR_CREATE (state_stack, 150, "state stack");
5757 /* Create the start state (empty state). */
5758 start_state = automaton->start_state;
5759 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5760 VLA_PTR_ADD (state_stack, start_state);
5761 while (VLA_PTR_LENGTH (state_stack) != 0)
5763 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5764 VLA_PTR_SHORTEN (state_stack, 1);
5765 form_arcs_marked_by_insn (state);
5766 for (i = 0; i < description->decls_num; i++)
5768 decl = description->decls [i];
5769 if (decl->mode == dm_insn_reserv)
5770 create_composed_state
5771 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5772 &state_stack);
5775 VLA_PTR_DELETE (state_stack);
5778 /* The following variable value is current number (1, 2, ...) of passing
5779 graph of states. */
5780 static int curr_state_graph_pass_num;
5782 /* This recursive function passes all states achieved from START_STATE
5783 and applies APPLIED_FUNC to them. */
5784 static void
5785 pass_state_graph (start_state, applied_func)
5786 state_t start_state;
5787 void (*applied_func) PARAMS ((state_t state));
5789 arc_t arc;
5791 if (start_state->pass_num == curr_state_graph_pass_num)
5792 return;
5793 start_state->pass_num = curr_state_graph_pass_num;
5794 (*applied_func) (start_state);
5795 for (arc = first_out_arc (start_state);
5796 arc != NULL;
5797 arc = next_out_arc (arc))
5798 pass_state_graph (arc->to_state, applied_func);
5801 /* This recursive function passes all states of AUTOMATON and applies
5802 APPLIED_FUNC to them. */
5803 static void
5804 pass_states (automaton, applied_func)
5805 automaton_t automaton;
5806 void (*applied_func) PARAMS ((state_t state));
5808 curr_state_graph_pass_num++;
5809 pass_state_graph (automaton->start_state, applied_func);
5812 /* The function initializes code for passing of all states. */
5813 static void
5814 initiate_pass_states ()
5816 curr_state_graph_pass_num = 0;
5819 /* The following vla is used for storing pointers to all achieved
5820 states. */
5821 static vla_ptr_t all_achieved_states;
5823 /* This function is called by function pass_states to add an achieved
5824 STATE. */
5825 static void
5826 add_achieved_state (state)
5827 state_t state;
5829 VLA_PTR_ADD (all_achieved_states, state);
5832 /* The function sets up equivalence numbers of insns which mark all
5833 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5834 nonzero value) or by equiv_class_num_2 of the destination state.
5835 The function returns number of out arcs of STATE. */
5836 static int
5837 set_out_arc_insns_equiv_num (state, odd_iteration_flag)
5838 state_t state;
5839 int odd_iteration_flag;
5841 int state_out_arcs_num;
5842 arc_t arc;
5844 state_out_arcs_num = 0;
5845 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5847 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
5848 || arc->insn->insn_reserv_decl->state_alts != 0)
5849 abort ();
5850 state_out_arcs_num++;
5851 arc->insn->insn_reserv_decl->equiv_class_num
5852 = (odd_iteration_flag
5853 ? arc->to_state->equiv_class_num_1
5854 : arc->to_state->equiv_class_num_2);
5855 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
5856 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
5857 || arc->insn->insn_reserv_decl->state_alts <= 0)
5858 abort ();
5860 return state_out_arcs_num;
5863 /* The function clears equivalence numbers and alt_states in all insns
5864 which mark all out arcs of STATE. */
5865 static void
5866 clear_arc_insns_equiv_num (state)
5867 state_t state;
5869 arc_t arc;
5871 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5873 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5874 arc->insn->insn_reserv_decl->state_alts = 0;
5878 /* The function copies pointers to equivalent states from vla FROM
5879 into vla TO. */
5880 static void
5881 copy_equiv_class (to, from)
5882 vla_ptr_t *to;
5883 const vla_ptr_t *from;
5885 state_t *class_ptr;
5887 VLA_PTR_NULLIFY (*to);
5888 for (class_ptr = VLA_PTR_BEGIN (*from);
5889 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
5890 class_ptr++)
5891 VLA_PTR_ADD (*to, *class_ptr);
5894 /* The function returns nonzero value if STATE is not equivalent to
5895 another state from the same current partition on equivalence
5896 classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of
5897 output arcs. Iteration of making equivalence partition is defined
5898 by ODD_ITERATION_FLAG. */
5899 static int
5900 state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag)
5901 state_t state;
5902 int original_state_out_arcs_num;
5903 int odd_iteration_flag;
5905 arc_t arc;
5906 int state_out_arcs_num;
5908 state_out_arcs_num = 0;
5909 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5911 state_out_arcs_num++;
5912 if ((odd_iteration_flag
5913 ? arc->to_state->equiv_class_num_1
5914 : arc->to_state->equiv_class_num_2)
5915 != arc->insn->insn_reserv_decl->equiv_class_num
5916 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
5917 return 1;
5919 return state_out_arcs_num != original_state_out_arcs_num;
5922 /* The function makes initial partition of STATES on equivalent
5923 classes. */
5924 static state_t
5925 init_equiv_class (states, states_num)
5926 state_t *states;
5927 int states_num;
5929 state_t *state_ptr;
5930 state_t result_equiv_class;
5932 result_equiv_class = NULL;
5933 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
5935 (*state_ptr)->equiv_class_num_1 = 1;
5936 (*state_ptr)->next_equiv_class_state = result_equiv_class;
5937 result_equiv_class = *state_ptr;
5939 return result_equiv_class;
5942 /* The function processes equivalence class given by its pointer
5943 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
5944 are not equvalent states, the function partitions the class
5945 removing nonequivalent states and placing them in
5946 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5947 assigns it to the state equivalence number. If the class has been
5948 partitioned, the function returns nonzero value. */
5949 static int
5950 partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5951 next_iteration_classes, new_equiv_class_num_ptr)
5952 state_t *equiv_class_ptr;
5953 int odd_iteration_flag;
5954 vla_ptr_t *next_iteration_classes;
5955 int *new_equiv_class_num_ptr;
5957 state_t new_equiv_class;
5958 int partition_p;
5959 state_t first_state;
5960 state_t curr_state;
5961 state_t prev_state;
5962 state_t next_state;
5963 int out_arcs_num;
5965 partition_p = 0;
5966 if (*equiv_class_ptr == NULL)
5967 abort ();
5968 for (first_state = *equiv_class_ptr;
5969 first_state != NULL;
5970 first_state = new_equiv_class)
5972 new_equiv_class = NULL;
5973 if (first_state->next_equiv_class_state != NULL)
5975 /* There are more one states in the class equivalence. */
5976 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
5977 odd_iteration_flag);
5978 for (prev_state = first_state,
5979 curr_state = first_state->next_equiv_class_state;
5980 curr_state != NULL;
5981 curr_state = next_state)
5983 next_state = curr_state->next_equiv_class_state;
5984 if (state_is_differed (curr_state, out_arcs_num,
5985 odd_iteration_flag))
5987 /* Remove curr state from the class equivalence. */
5988 prev_state->next_equiv_class_state = next_state;
5989 /* Add curr state to the new class equivalence. */
5990 curr_state->next_equiv_class_state = new_equiv_class;
5991 if (new_equiv_class == NULL)
5992 (*new_equiv_class_num_ptr)++;
5993 if (odd_iteration_flag)
5994 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5995 else
5996 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5997 new_equiv_class = curr_state;
5998 partition_p = 1;
6000 else
6001 prev_state = curr_state;
6003 clear_arc_insns_equiv_num (first_state);
6005 if (new_equiv_class != NULL)
6006 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
6008 return partition_p;
6011 /* The function finds equivalent states of AUTOMATON. */
6012 static void
6013 evaluate_equiv_classes (automaton, equiv_classes)
6014 automaton_t automaton;
6015 vla_ptr_t *equiv_classes;
6017 state_t new_equiv_class;
6018 int new_equiv_class_num;
6019 int odd_iteration_flag;
6020 int finish_flag;
6021 vla_ptr_t next_iteration_classes;
6022 state_t *equiv_class_ptr;
6023 state_t *state_ptr;
6025 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6026 pass_states (automaton, add_achieved_state);
6027 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6028 VLA_PTR_LENGTH (all_achieved_states));
6029 odd_iteration_flag = 0;
6030 new_equiv_class_num = 1;
6031 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6032 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6035 odd_iteration_flag = !odd_iteration_flag;
6036 finish_flag = 1;
6037 copy_equiv_class (equiv_classes, &next_iteration_classes);
6038 /* Transfer equiv numbers for the next iteration. */
6039 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6040 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6041 state_ptr++)
6042 if (odd_iteration_flag)
6043 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6044 else
6045 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6046 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6047 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6048 equiv_class_ptr++)
6049 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6050 &next_iteration_classes,
6051 &new_equiv_class_num))
6052 finish_flag = 0;
6054 while (!finish_flag);
6055 VLA_PTR_DELETE (next_iteration_classes);
6056 VLA_PTR_DELETE (all_achieved_states);
6059 /* The function merges equivalent states of AUTOMATON. */
6060 static void
6061 merge_states (automaton, equiv_classes)
6062 automaton_t automaton;
6063 vla_ptr_t *equiv_classes;
6065 state_t *equiv_class_ptr;
6066 state_t curr_state;
6067 state_t new_state;
6068 state_t first_class_state;
6069 alt_state_t alt_states;
6070 alt_state_t new_alt_state;
6071 arc_t curr_arc;
6072 arc_t next_arc;
6074 /* Create states corresponding to equivalence classes containing two
6075 or more states. */
6076 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6077 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6078 equiv_class_ptr++)
6079 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6081 /* There are more one states in the class equivalence. */
6082 /* Create new compound state. */
6083 new_state = get_free_state (0, automaton);
6084 alt_states = NULL;
6085 first_class_state = *equiv_class_ptr;
6086 for (curr_state = first_class_state;
6087 curr_state != NULL;
6088 curr_state = curr_state->next_equiv_class_state)
6090 curr_state->equiv_class_state = new_state;
6091 new_alt_state = get_free_alt_state ();
6092 new_alt_state->state = curr_state;
6093 new_alt_state->next_sorted_alt_state = alt_states;
6094 alt_states = new_alt_state;
6096 new_state->component_states = alt_states;
6098 else
6099 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6100 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6101 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6102 equiv_class_ptr++)
6103 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6105 first_class_state = *equiv_class_ptr;
6106 /* Create new arcs output from the state corresponding to
6107 equiv class. */
6108 for (curr_arc = first_out_arc (first_class_state);
6109 curr_arc != NULL;
6110 curr_arc = next_out_arc (curr_arc))
6111 add_arc (first_class_state->equiv_class_state,
6112 curr_arc->to_state->equiv_class_state,
6113 curr_arc->insn, curr_arc->state_alts);
6114 /* Delete output arcs from states of given class equivalence. */
6115 for (curr_state = first_class_state;
6116 curr_state != NULL;
6117 curr_state = curr_state->next_equiv_class_state)
6119 if (automaton->start_state == curr_state)
6120 automaton->start_state = curr_state->equiv_class_state;
6121 /* Delete the state and its output arcs. */
6122 for (curr_arc = first_out_arc (curr_state);
6123 curr_arc != NULL;
6124 curr_arc = next_arc)
6126 next_arc = next_out_arc (curr_arc);
6127 free_arc (curr_arc);
6131 else
6133 /* Change `to_state' of arcs output from the state of given
6134 equivalence class. */
6135 for (curr_arc = first_out_arc (*equiv_class_ptr);
6136 curr_arc != NULL;
6137 curr_arc = next_out_arc (curr_arc))
6138 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6142 /* The function sets up new_cycle_p for states if there is arc to the
6143 state marked by advance_cycle_insn_decl. */
6144 static void
6145 set_new_cycle_flags (state)
6146 state_t state;
6148 arc_t arc;
6150 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6151 if (arc->insn->insn_reserv_decl
6152 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6153 arc->to_state->new_cycle_p = 1;
6156 /* The top level function for minimization of deterministic
6157 AUTOMATON. */
6158 static void
6159 minimize_DFA (automaton)
6160 automaton_t automaton;
6162 vla_ptr_t equiv_classes;
6164 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6165 evaluate_equiv_classes (automaton, &equiv_classes);
6166 merge_states (automaton, &equiv_classes);
6167 pass_states (automaton, set_new_cycle_flags);
6168 VLA_PTR_DELETE (equiv_classes);
6171 /* Values of two variables are counted number of states and arcs in an
6172 automaton. */
6173 static int curr_counted_states_num;
6174 static int curr_counted_arcs_num;
6176 /* The function is called by function `pass_states' to count states
6177 and arcs of an automaton. */
6178 static void
6179 incr_states_and_arcs_nums (state)
6180 state_t state;
6182 arc_t arc;
6184 curr_counted_states_num++;
6185 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6186 curr_counted_arcs_num++;
6189 /* The function counts states and arcs of AUTOMATON. */
6190 static void
6191 count_states_and_arcs (automaton, states_num, arcs_num)
6192 automaton_t automaton;
6193 int *states_num;
6194 int *arcs_num;
6196 curr_counted_states_num = 0;
6197 curr_counted_arcs_num = 0;
6198 pass_states (automaton, incr_states_and_arcs_nums);
6199 *states_num = curr_counted_states_num;
6200 *arcs_num = curr_counted_arcs_num;
6203 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6204 recognition after checking and simplifying IR of the
6205 description. */
6206 static void
6207 build_automaton (automaton)
6208 automaton_t automaton;
6210 int states_num;
6211 int arcs_num;
6213 ticker_on (&NDFA_time);
6214 make_automaton (automaton);
6215 ticker_off (&NDFA_time);
6216 count_states_and_arcs (automaton, &states_num, &arcs_num);
6217 automaton->NDFA_states_num = states_num;
6218 automaton->NDFA_arcs_num = arcs_num;
6219 ticker_on (&NDFA_to_DFA_time);
6220 NDFA_to_DFA (automaton);
6221 ticker_off (&NDFA_to_DFA_time);
6222 count_states_and_arcs (automaton, &states_num, &arcs_num);
6223 automaton->DFA_states_num = states_num;
6224 automaton->DFA_arcs_num = arcs_num;
6225 if (!no_minimization_flag)
6227 ticker_on (&minimize_time);
6228 minimize_DFA (automaton);
6229 ticker_off (&minimize_time);
6230 count_states_and_arcs (automaton, &states_num, &arcs_num);
6231 automaton->minimal_DFA_states_num = states_num;
6232 automaton->minimal_DFA_arcs_num = arcs_num;
6238 /* The page contains code for enumeration of all states of an automaton. */
6240 /* Variable used for enumeration of all states of an automaton. Its
6241 value is current number of automaton states. */
6242 static int curr_state_order_num;
6244 /* The function is called by function `pass_states' for enumerating
6245 states. */
6246 static void
6247 set_order_state_num (state)
6248 state_t state;
6250 state->order_state_num = curr_state_order_num;
6251 curr_state_order_num++;
6254 /* The function enumerates all states of AUTOMATON. */
6255 static void
6256 enumerate_states (automaton)
6257 automaton_t automaton;
6259 curr_state_order_num = 0;
6260 pass_states (automaton, set_order_state_num);
6261 automaton->achieved_states_num = curr_state_order_num;
6266 /* The page contains code for finding equivalent automaton insns
6267 (ainsns). */
6269 /* The function inserts AINSN into cyclic list
6270 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6271 static ainsn_t
6272 insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6273 ainsn_t ainsn;
6274 ainsn_t cyclic_equiv_class_insn_list;
6276 if (cyclic_equiv_class_insn_list == NULL)
6277 ainsn->next_equiv_class_insn = ainsn;
6278 else
6280 ainsn->next_equiv_class_insn
6281 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6282 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6284 return ainsn;
6287 /* The function deletes equiv_class_insn into cyclic list of
6288 equivalent ainsns. */
6289 static void
6290 delete_ainsn_from_equiv_class (equiv_class_insn)
6291 ainsn_t equiv_class_insn;
6293 ainsn_t curr_equiv_class_insn;
6294 ainsn_t prev_equiv_class_insn;
6296 prev_equiv_class_insn = equiv_class_insn;
6297 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6298 curr_equiv_class_insn != equiv_class_insn;
6299 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6300 prev_equiv_class_insn = curr_equiv_class_insn;
6301 if (prev_equiv_class_insn != equiv_class_insn)
6302 prev_equiv_class_insn->next_equiv_class_insn
6303 = equiv_class_insn->next_equiv_class_insn;
6306 /* The function processes AINSN of a state in order to find equivalent
6307 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6308 state. */
6309 static void
6310 process_insn_equiv_class (ainsn, insn_arcs_array)
6311 ainsn_t ainsn;
6312 arc_t *insn_arcs_array;
6314 ainsn_t next_insn;
6315 ainsn_t curr_insn;
6316 ainsn_t cyclic_insn_list;
6317 arc_t arc;
6319 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6320 abort ();
6321 curr_insn = ainsn;
6322 /* New class of ainsns which are not equivalent to given ainsn. */
6323 cyclic_insn_list = NULL;
6326 next_insn = curr_insn->next_equiv_class_insn;
6327 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6328 if (arc == NULL
6329 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6330 != arc->to_state))
6332 delete_ainsn_from_equiv_class (curr_insn);
6333 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6334 cyclic_insn_list);
6336 curr_insn = next_insn;
6338 while (curr_insn != ainsn);
6341 /* The function processes STATE in order to find equivalent ainsns. */
6342 static void
6343 process_state_for_insn_equiv_partition (state)
6344 state_t state;
6346 arc_t arc;
6347 arc_t *insn_arcs_array;
6348 int i;
6349 vla_ptr_t insn_arcs_vect;
6351 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6352 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6353 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6354 /* Process insns of the arcs. */
6355 for (i = 0; i < description->insns_num; i++)
6356 insn_arcs_array [i] = NULL;
6357 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6358 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6359 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6360 process_insn_equiv_class (arc->insn, insn_arcs_array);
6361 VLA_PTR_DELETE (insn_arcs_vect);
6364 /* The function searches for equivalent ainsns of AUTOMATON. */
6365 static void
6366 set_insn_equiv_classes (automaton)
6367 automaton_t automaton;
6369 ainsn_t ainsn;
6370 ainsn_t first_insn;
6371 ainsn_t curr_insn;
6372 ainsn_t cyclic_insn_list;
6373 ainsn_t insn_with_same_reservs;
6374 int equiv_classes_num;
6376 /* All insns are included in one equivalence class. */
6377 cyclic_insn_list = NULL;
6378 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6379 if (ainsn->first_insn_with_same_reservs)
6380 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6381 cyclic_insn_list);
6382 /* Process insns in order to make equivalence partition. */
6383 pass_states (automaton, process_state_for_insn_equiv_partition);
6384 /* Enumerate equiv classes. */
6385 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6386 /* Set undefined value. */
6387 ainsn->insn_equiv_class_num = -1;
6388 equiv_classes_num = 0;
6389 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6390 if (ainsn->insn_equiv_class_num < 0)
6392 first_insn = ainsn;
6393 if (!first_insn->first_insn_with_same_reservs)
6394 abort ();
6395 first_insn->first_ainsn_with_given_equialence_num = 1;
6396 curr_insn = first_insn;
6399 for (insn_with_same_reservs = curr_insn;
6400 insn_with_same_reservs != NULL;
6401 insn_with_same_reservs
6402 = insn_with_same_reservs->next_same_reservs_insn)
6403 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6404 curr_insn = curr_insn->next_equiv_class_insn;
6406 while (curr_insn != first_insn);
6407 equiv_classes_num++;
6409 automaton->insn_equiv_classes_num = equiv_classes_num;
6414 /* This page contains code for creating DFA(s) and calls functions
6415 building them. */
6418 /* The following value is used to prevent floating point overflow for
6419 estimating an automaton bound. The value should be less DBL_MAX on
6420 the host machine. We use here approximate minimum of maximal
6421 double floating point value required by ANSI C standard. It
6422 will work for non ANSI sun compiler too. */
6424 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6426 /* The function estimate size of the single DFA used by PHR (pipeline
6427 hazards recognizer). */
6428 static double
6429 estimate_one_automaton_bound ()
6431 decl_t decl;
6432 double one_automaton_estimation_bound;
6433 double root_value;
6434 int i;
6436 one_automaton_estimation_bound = 1.0;
6437 for (i = 0; i < description->decls_num; i++)
6439 decl = description->decls [i];
6440 if (decl->mode == dm_unit)
6442 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num + 1.0)
6443 / automata_num);
6444 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6445 > one_automaton_estimation_bound)
6446 one_automaton_estimation_bound *= root_value;
6449 return one_automaton_estimation_bound;
6452 /* The function compares unit declarations acoording to their maximal
6453 cycle in reservations. */
6454 static int
6455 compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6456 const void *unit_decl_1;
6457 const void *unit_decl_2;
6459 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6460 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6461 return 1;
6462 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6463 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6464 return 0;
6465 else
6466 return -1;
6469 /* The function makes heuristic assigning automata to units. Actually
6470 efficacy of the algorithm has been checked yet??? */
6471 static void
6472 units_to_automata_heuristic_distr ()
6474 double estimation_bound;
6475 decl_t decl;
6476 decl_t *unit_decl_ptr;
6477 int automaton_num;
6478 int rest_units_num;
6479 double bound_value;
6480 vla_ptr_t unit_decls;
6481 int i;
6483 if (description->units_num == 0)
6484 return;
6485 estimation_bound = estimate_one_automaton_bound ();
6486 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6487 for (i = 0; i < description->decls_num; i++)
6489 decl = description->decls [i];
6490 if (decl->mode == dm_unit)
6491 VLA_PTR_ADD (unit_decls, decl);
6493 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6494 sizeof (decl_t), compare_max_occ_cycle_nums);
6495 automaton_num = 0;
6496 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6497 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6498 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6499 for (unit_decl_ptr++;
6500 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6501 unit_decl_ptr++)
6503 rest_units_num
6504 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6505 if (automata_num - automaton_num - 1 > rest_units_num)
6506 abort ();
6507 if (automaton_num < automata_num - 1
6508 && ((automata_num - automaton_num - 1 == rest_units_num)
6509 || (bound_value
6510 > (estimation_bound
6511 / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6513 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6514 automaton_num++;
6516 else
6517 bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6518 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6520 if (automaton_num != automata_num - 1)
6521 abort ();
6522 VLA_PTR_DELETE (unit_decls);
6525 /* The functions creates automaton insns for each automata. Automaton
6526 insn is simply insn for given automaton which makes reservation
6527 only of units of the automaton. */
6528 static ainsn_t
6529 create_ainsns ()
6531 decl_t decl;
6532 ainsn_t first_ainsn;
6533 ainsn_t curr_ainsn;
6534 ainsn_t prev_ainsn;
6535 int i;
6537 first_ainsn = NULL;
6538 prev_ainsn = NULL;
6539 for (i = 0; i < description->decls_num; i++)
6541 decl = description->decls [i];
6542 if (decl->mode == dm_insn_reserv)
6544 curr_ainsn = create_node (sizeof (struct ainsn));
6545 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6546 curr_ainsn->important_p = FALSE;
6547 curr_ainsn->next_ainsn = NULL;
6548 if (prev_ainsn == NULL)
6549 first_ainsn = curr_ainsn;
6550 else
6551 prev_ainsn->next_ainsn = curr_ainsn;
6552 prev_ainsn = curr_ainsn;
6555 return first_ainsn;
6558 /* The function assigns automata to units according to constructions
6559 `define_automaton' in the description. */
6560 static void
6561 units_to_automata_distr ()
6563 decl_t decl;
6564 int i;
6566 for (i = 0; i < description->decls_num; i++)
6568 decl = description->decls [i];
6569 if (decl->mode == dm_unit)
6571 if (DECL_UNIT (decl)->automaton_decl == NULL
6572 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6573 == NULL))
6574 /* Distribute to the first automaton. */
6575 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6576 else
6577 DECL_UNIT (decl)->corresponding_automaton_num
6578 = (DECL_UNIT (decl)->automaton_decl
6579 ->corresponding_automaton->automaton_order_num);
6584 /* The function creates DFA(s) for fast pipeline hazards recognition
6585 after checking and simplifying IR of the description. */
6586 static void
6587 create_automata ()
6589 automaton_t curr_automaton;
6590 automaton_t prev_automaton;
6591 decl_t decl;
6592 int curr_automaton_num;
6593 int i;
6595 if (automata_num != 0)
6597 units_to_automata_heuristic_distr ();
6598 for (prev_automaton = NULL, curr_automaton_num = 0;
6599 curr_automaton_num < automata_num;
6600 curr_automaton_num++, prev_automaton = curr_automaton)
6602 curr_automaton = create_node (sizeof (struct automaton));
6603 curr_automaton->ainsn_list = create_ainsns ();
6604 curr_automaton->corresponding_automaton_decl = NULL;
6605 curr_automaton->next_automaton = NULL;
6606 curr_automaton->automaton_order_num = curr_automaton_num;
6607 if (prev_automaton == NULL)
6608 description->first_automaton = curr_automaton;
6609 else
6610 prev_automaton->next_automaton = curr_automaton;
6613 else
6615 curr_automaton_num = 0;
6616 prev_automaton = NULL;
6617 for (i = 0; i < description->decls_num; i++)
6619 decl = description->decls [i];
6620 if (decl->mode == dm_automaton
6621 && DECL_AUTOMATON (decl)->automaton_is_used)
6623 curr_automaton = create_node (sizeof (struct automaton));
6624 curr_automaton->ainsn_list = create_ainsns ();
6625 curr_automaton->corresponding_automaton_decl
6626 = DECL_AUTOMATON (decl);
6627 curr_automaton->next_automaton = NULL;
6628 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6629 curr_automaton->automaton_order_num = curr_automaton_num;
6630 if (prev_automaton == NULL)
6631 description->first_automaton = curr_automaton;
6632 else
6633 prev_automaton->next_automaton = curr_automaton;
6634 curr_automaton_num++;
6635 prev_automaton = curr_automaton;
6638 if (curr_automaton_num == 0)
6640 curr_automaton = create_node (sizeof (struct automaton));
6641 curr_automaton->ainsn_list = create_ainsns ();
6642 curr_automaton->corresponding_automaton_decl = NULL;
6643 curr_automaton->next_automaton = NULL;
6644 description->first_automaton = curr_automaton;
6646 units_to_automata_distr ();
6648 NDFA_time = create_ticker ();
6649 ticker_off (&NDFA_time);
6650 NDFA_to_DFA_time = create_ticker ();
6651 ticker_off (&NDFA_to_DFA_time);
6652 minimize_time = create_ticker ();
6653 ticker_off (&minimize_time);
6654 equiv_time = create_ticker ();
6655 ticker_off (&equiv_time);
6656 for (curr_automaton = description->first_automaton;
6657 curr_automaton != NULL;
6658 curr_automaton = curr_automaton->next_automaton)
6660 if (curr_automaton->corresponding_automaton_decl == NULL)
6661 fprintf (stderr, "Create anonymous automaton ...");
6662 else
6663 fprintf (stderr, "Create automaton `%s'...",
6664 curr_automaton->corresponding_automaton_decl->name);
6665 create_alt_states (curr_automaton);
6666 form_ainsn_with_same_reservs (curr_automaton);
6667 build_automaton (curr_automaton);
6668 enumerate_states (curr_automaton);
6669 ticker_on (&equiv_time);
6670 set_insn_equiv_classes (curr_automaton);
6671 ticker_off (&equiv_time);
6672 fprintf (stderr, "done\n");
6678 /* This page contains code for forming string representation of
6679 regexp. The representation is formed on IR obstack. So you should
6680 not work with IR obstack between regexp_representation and
6681 finish_regexp_representation calls. */
6683 /* This recursive function forms string representation of regexp
6684 (without tailing '\0'). */
6685 static void
6686 form_regexp (regexp)
6687 regexp_t regexp;
6689 int i;
6691 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6693 const char *name = (regexp->mode == rm_unit
6694 ? REGEXP_UNIT (regexp)->name
6695 : REGEXP_RESERV (regexp)->name);
6697 obstack_grow (&irp, name, strlen (name));
6699 else if (regexp->mode == rm_sequence)
6700 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6702 if (i != 0)
6703 obstack_1grow (&irp, ',');
6704 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6706 else if (regexp->mode == rm_allof)
6708 obstack_1grow (&irp, '(');
6709 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6711 if (i != 0)
6712 obstack_1grow (&irp, '+');
6713 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6714 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6715 obstack_1grow (&irp, '(');
6716 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6717 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6718 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6719 obstack_1grow (&irp, ')');
6721 obstack_1grow (&irp, ')');
6723 else if (regexp->mode == rm_oneof)
6724 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6726 if (i != 0)
6727 obstack_1grow (&irp, '|');
6728 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6729 obstack_1grow (&irp, '(');
6730 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6731 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6732 obstack_1grow (&irp, ')');
6734 else if (regexp->mode == rm_repeat)
6736 char digits [30];
6738 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6739 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6740 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6741 obstack_1grow (&irp, '(');
6742 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6743 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6744 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6745 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6746 obstack_1grow (&irp, ')');
6747 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6748 obstack_grow (&irp, digits, strlen (digits));
6750 else if (regexp->mode == rm_nothing)
6751 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6752 else
6753 abort ();
6756 /* The function returns string representation of REGEXP on IR
6757 obstack. */
6758 static const char *
6759 regexp_representation (regexp)
6760 regexp_t regexp;
6762 form_regexp (regexp);
6763 obstack_1grow (&irp, '\0');
6764 return obstack_base (&irp);
6767 /* The function frees memory allocated for last formed string
6768 representation of regexp. */
6769 static void
6770 finish_regexp_representation ()
6772 int length = obstack_object_size (&irp);
6774 obstack_blank_fast (&irp, -length);
6779 /* This page contains code for output PHR (pipeline hazards recognizer). */
6781 /* The function outputs minimal C type which is sufficient for
6782 representation numbers in range min_range_value and
6783 max_range_value. Because host machine and build machine may be
6784 different, we use here minimal values required by ANSI C standard
6785 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6786 approximation. */
6788 static void
6789 output_range_type (f, min_range_value, max_range_value)
6790 FILE *f;
6791 long int min_range_value;
6792 long int max_range_value;
6794 if (min_range_value >= 0 && max_range_value <= 255)
6795 fprintf (f, "unsigned char");
6796 else if (min_range_value >= -127 && max_range_value <= 127)
6797 fprintf (f, "signed char");
6798 else if (min_range_value >= 0 && max_range_value <= 65535)
6799 fprintf (f, "unsigned short");
6800 else if (min_range_value >= -32767 && max_range_value <= 32767)
6801 fprintf (f, "short");
6802 else
6803 fprintf (f, "int");
6806 /* The following macro value is used as value of member
6807 `longest_path_length' of state when we are processing path and the
6808 state on the path. */
6810 #define ON_THE_PATH -2
6812 /* The following recursive function searches for the length of the
6813 longest path starting from STATE which does not contain cycles and
6814 `cycle advance' arcs. */
6816 static int
6817 longest_path_length (state)
6818 state_t state;
6820 arc_t arc;
6821 int length, result;
6823 if (state->longest_path_length == ON_THE_PATH)
6824 /* We don't expect the path cycle here. Our graph may contain
6825 only cycles with one state on the path not containing `cycle
6826 advance' arcs -- see comment below. */
6827 abort ();
6828 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6829 /* We alreday visited the state. */
6830 return state->longest_path_length;
6832 result = 0;
6833 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6834 /* Ignore cycles containing one state and `cycle advance' arcs. */
6835 if (arc->to_state != state
6836 && (arc->insn->insn_reserv_decl
6837 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6839 length = longest_path_length (arc->to_state);
6840 if (length > result)
6841 result = length;
6843 state->longest_path_length = result + 1;
6844 return result;
6847 /* The following variable value is value of the corresponding global
6848 variable in the automaton based pipeline interface. */
6850 static int max_dfa_issue_rate;
6852 /* The following function processes the longest path length staring
6853 from STATE to find MAX_DFA_ISSUE_RATE. */
6855 static void
6856 process_state_longest_path_length (state)
6857 state_t state;
6859 int value;
6861 value = longest_path_length (state);
6862 if (value > max_dfa_issue_rate)
6863 max_dfa_issue_rate = value;
6866 /* The following macro value is name of the corresponding global
6867 variable in the automaton based pipeline interface. */
6869 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
6871 /* The following function calculates value of the the corresponding
6872 global variable and outputs its declaration. */
6874 static void
6875 output_dfa_max_issue_rate ()
6877 automaton_t automaton;
6879 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
6880 abort ();
6881 max_dfa_issue_rate = 0;
6882 for (automaton = description->first_automaton;
6883 automaton != NULL;
6884 automaton = automaton->next_automaton)
6885 pass_states (automaton, process_state_longest_path_length);
6886 fprintf (output_file, "\nint %s = %d;\n",
6887 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
6890 /* The function outputs all initialization values of VECT with length
6891 vect_length. */
6892 static void
6893 output_vect (vect, vect_length)
6894 vect_el_t *vect;
6895 int vect_length;
6897 int els_on_line;
6899 els_on_line = 1;
6900 if (vect_length == 0)
6901 fprintf (output_file,
6902 "0 /* This is dummy el because the vect is empty */");
6903 else
6907 fprintf (output_file, "%5ld", (long) *vect);
6908 vect_length--;
6909 if (els_on_line == 10)
6911 els_on_line = 0;
6912 fprintf (output_file, ",\n");
6914 else if (vect_length != 0)
6915 fprintf (output_file, ", ");
6916 els_on_line++;
6917 vect++;
6919 while (vect_length != 0);
6923 /* The following is name of the structure which represents DFA(s) for
6924 PHR. */
6925 #define CHIP_NAME "DFA_chip"
6927 /* The following is name of member which represents state of a DFA for
6928 PHR. */
6929 static void
6930 output_chip_member_name (f, automaton)
6931 FILE *f;
6932 automaton_t automaton;
6934 if (automaton->corresponding_automaton_decl == NULL)
6935 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6936 else
6937 fprintf (f, "%s_automaton_state",
6938 automaton->corresponding_automaton_decl->name);
6941 /* The following is name of temporary variable which stores state of a
6942 DFA for PHR. */
6943 static void
6944 output_temp_chip_member_name (f, automaton)
6945 FILE *f;
6946 automaton_t automaton;
6948 fprintf (f, "_");
6949 output_chip_member_name (f, automaton);
6952 /* This is name of macro value which is code of pseudo_insn
6953 representing advancing cpu cycle. Its value is used as internal
6954 code unknown insn. */
6955 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6957 /* Output name of translate vector for given automaton. */
6958 static void
6959 output_translate_vect_name (f, automaton)
6960 FILE *f;
6961 automaton_t automaton;
6963 if (automaton->corresponding_automaton_decl == NULL)
6964 fprintf (f, "translate_%d", automaton->automaton_order_num);
6965 else
6966 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6969 /* Output name for simple transition table representation. */
6970 static void
6971 output_trans_full_vect_name (f, automaton)
6972 FILE *f;
6973 automaton_t automaton;
6975 if (automaton->corresponding_automaton_decl == NULL)
6976 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6977 else
6978 fprintf (f, "%s_transitions",
6979 automaton->corresponding_automaton_decl->name);
6982 /* Output name of comb vector of the transition table for given
6983 automaton. */
6984 static void
6985 output_trans_comb_vect_name (f, automaton)
6986 FILE *f;
6987 automaton_t automaton;
6989 if (automaton->corresponding_automaton_decl == NULL)
6990 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6991 else
6992 fprintf (f, "%s_transitions",
6993 automaton->corresponding_automaton_decl->name);
6996 /* Output name of check vector of the transition table for given
6997 automaton. */
6998 static void
6999 output_trans_check_vect_name (f, automaton)
7000 FILE *f;
7001 automaton_t automaton;
7003 if (automaton->corresponding_automaton_decl == NULL)
7004 fprintf (f, "check_%d", automaton->automaton_order_num);
7005 else
7006 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7009 /* Output name of base vector of the transition table for given
7010 automaton. */
7011 static void
7012 output_trans_base_vect_name (f, automaton)
7013 FILE *f;
7014 automaton_t automaton;
7016 if (automaton->corresponding_automaton_decl == NULL)
7017 fprintf (f, "base_%d", automaton->automaton_order_num);
7018 else
7019 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7022 /* Output name for simple alternatives number representation. */
7023 static void
7024 output_state_alts_full_vect_name (f, automaton)
7025 FILE *f;
7026 automaton_t automaton;
7028 if (automaton->corresponding_automaton_decl == NULL)
7029 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7030 else
7031 fprintf (f, "%s_state_alts",
7032 automaton->corresponding_automaton_decl->name);
7035 /* Output name of comb vector of the alternatives number table for given
7036 automaton. */
7037 static void
7038 output_state_alts_comb_vect_name (f, automaton)
7039 FILE *f;
7040 automaton_t automaton;
7042 if (automaton->corresponding_automaton_decl == NULL)
7043 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7044 else
7045 fprintf (f, "%s_state_alts",
7046 automaton->corresponding_automaton_decl->name);
7049 /* Output name of check vector of the alternatives number table for given
7050 automaton. */
7051 static void
7052 output_state_alts_check_vect_name (f, automaton)
7053 FILE *f;
7054 automaton_t automaton;
7056 if (automaton->corresponding_automaton_decl == NULL)
7057 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7058 else
7059 fprintf (f, "%s_check_state_alts",
7060 automaton->corresponding_automaton_decl->name);
7063 /* Output name of base vector of the alternatives number table for given
7064 automaton. */
7065 static void
7066 output_state_alts_base_vect_name (f, automaton)
7067 FILE *f;
7068 automaton_t automaton;
7070 if (automaton->corresponding_automaton_decl == NULL)
7071 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7072 else
7073 fprintf (f, "%s_base_state_alts",
7074 automaton->corresponding_automaton_decl->name);
7077 /* Output name of simple min issue delay table representation. */
7078 static void
7079 output_min_issue_delay_vect_name (f, automaton)
7080 FILE *f;
7081 automaton_t automaton;
7083 if (automaton->corresponding_automaton_decl == NULL)
7084 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7085 else
7086 fprintf (f, "%s_min_issue_delay",
7087 automaton->corresponding_automaton_decl->name);
7090 /* Output name of deadlock vector for given automaton. */
7091 static void
7092 output_dead_lock_vect_name (f, automaton)
7093 FILE *f;
7094 automaton_t automaton;
7096 if (automaton->corresponding_automaton_decl == NULL)
7097 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7098 else
7099 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7102 /* Output name of reserved units table for AUTOMATON into file F. */
7103 static void
7104 output_reserved_units_table_name (f, automaton)
7105 FILE *f;
7106 automaton_t automaton;
7108 if (automaton->corresponding_automaton_decl == NULL)
7109 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7110 else
7111 fprintf (f, "%s_reserved_units",
7112 automaton->corresponding_automaton_decl->name);
7115 /* Name of the PHR interface macro. */
7116 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7118 /* Name of the PHR interface macro. */
7119 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7121 /* Names of an internal functions: */
7122 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7124 /* This is external type of DFA(s) state. */
7125 #define STATE_TYPE_NAME "state_t"
7127 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7129 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7131 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7133 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7135 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7137 /* Name of cache of insn dfa codes. */
7138 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7140 /* Name of length of cache of insn dfa codes. */
7141 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7143 /* Names of the PHR interface functions: */
7144 #define SIZE_FUNC_NAME "state_size"
7146 #define TRANSITION_FUNC_NAME "state_transition"
7148 #define STATE_ALTS_FUNC_NAME "state_alts"
7150 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7152 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7154 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7156 #define RESET_FUNC_NAME "state_reset"
7158 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7160 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7162 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7164 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7166 #define DFA_START_FUNC_NAME "dfa_start"
7168 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7170 /* Names of parameters of the PHR interface functions. */
7171 #define STATE_NAME "state"
7173 #define INSN_PARAMETER_NAME "insn"
7175 #define INSN2_PARAMETER_NAME "insn2"
7177 #define CHIP_PARAMETER_NAME "chip"
7179 #define FILE_PARAMETER_NAME "f"
7181 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7183 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7185 /* Names of the variables whose values are internal insn code of rtx
7186 insn. */
7187 #define INTERNAL_INSN_CODE_NAME "insn_code"
7189 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7191 /* Names of temporary variables in some functions. */
7192 #define TEMPORARY_VARIABLE_NAME "temp"
7194 #define I_VARIABLE_NAME "i"
7196 /* Name of result variable in some functions. */
7197 #define RESULT_VARIABLE_NAME "res"
7199 /* Name of function (attribute) to translate insn into number of insn
7200 alternatives reservation. */
7201 #define INSN_ALTS_FUNC_NAME "insn_alts"
7203 /* Name of function (attribute) to translate insn into internal insn
7204 code. */
7205 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7207 /* Name of function (attribute) to translate insn into internal insn
7208 code with caching. */
7209 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7211 /* Name of function (attribute) to translate insn into internal insn
7212 code. */
7213 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7215 /* Name of function (attribute) to translate insn into internal insn
7216 code. */
7217 #define BYPASS_P_FUNC_NAME "bypass_p"
7219 /* Output C type which is used for representation of codes of states
7220 of AUTOMATON. */
7221 static void
7222 output_state_member_type (f, automaton)
7223 FILE *f;
7224 automaton_t automaton;
7226 output_range_type (f, 0, automaton->achieved_states_num);
7229 /* Output definition of the structure representing current DFA(s)
7230 state(s). */
7231 static void
7232 output_chip_definitions ()
7234 automaton_t automaton;
7236 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7237 for (automaton = description->first_automaton;
7238 automaton != NULL;
7239 automaton = automaton->next_automaton)
7241 fprintf (output_file, " ");
7242 output_state_member_type (output_file, automaton);
7243 fprintf (output_file, " ");
7244 output_chip_member_name (output_file, automaton);
7245 fprintf (output_file, ";\n");
7247 fprintf (output_file, "};\n\n");
7248 #if 0
7249 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7250 #endif
7254 /* The function outputs translate vector of internal insn code into
7255 insn equivalence class number. The equivalence class number is
7256 used to access to table and vectors reprewsenting DFA(s). */
7257 static void
7258 output_translate_vect (automaton)
7259 automaton_t automaton;
7261 ainsn_t ainsn;
7262 int insn_value;
7263 vla_hwint_t translate_vect;
7265 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7266 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7267 for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
7268 /* Undefined value */
7269 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7270 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7271 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7272 = ainsn->insn_equiv_class_num;
7273 fprintf (output_file,
7274 "/* Vector translating external insn codes to internal ones.*/\n");
7275 fprintf (output_file, "static const ");
7276 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7277 fprintf (output_file, " ");
7278 output_translate_vect_name (output_file, automaton);
7279 fprintf (output_file, "[] = {\n");
7280 output_vect (VLA_HWINT_BEGIN (translate_vect),
7281 VLA_HWINT_LENGTH (translate_vect));
7282 fprintf (output_file, "};\n\n");
7283 VLA_HWINT_DELETE (translate_vect);
7286 /* The value in a table state x ainsn -> something which represents
7287 undefined value. */
7288 static int undefined_vect_el_value;
7290 /* The following function returns nonzero value if the best
7291 representation of the table is comb vector. */
7292 static int
7293 comb_vect_p (tab)
7294 state_ainsn_table_t tab;
7296 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7297 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7300 /* The following function creates new table for AUTOMATON. */
7301 static state_ainsn_table_t
7302 create_state_ainsn_table (automaton)
7303 automaton_t automaton;
7305 state_ainsn_table_t tab;
7306 int full_vect_length;
7307 int i;
7309 tab = create_node (sizeof (struct state_ainsn_table));
7310 tab->automaton = automaton;
7311 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7312 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7313 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7314 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7315 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7316 full_vect_length = (automaton->insn_equiv_classes_num
7317 * automaton->achieved_states_num);
7318 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7319 for (i = 0; i < full_vect_length; i++)
7320 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7321 tab->min_base_vect_el_value = 0;
7322 tab->max_base_vect_el_value = 0;
7323 tab->min_comb_vect_el_value = 0;
7324 tab->max_comb_vect_el_value = 0;
7325 return tab;
7328 /* The following function outputs the best C representation of the
7329 table TAB of given TABLE_NAME. */
7330 static void
7331 output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7332 output_comb_vect_name_func,
7333 output_check_vect_name_func,
7334 output_base_vect_name_func)
7335 state_ainsn_table_t tab;
7336 char *table_name;
7337 void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7338 void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7339 void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7340 void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7342 if (!comb_vect_p (tab))
7344 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7345 fprintf (output_file, "static const ");
7346 output_range_type (output_file, tab->min_comb_vect_el_value,
7347 tab->max_comb_vect_el_value);
7348 fprintf (output_file, " ");
7349 (*output_full_vect_name_func) (output_file, tab->automaton);
7350 fprintf (output_file, "[] = {\n");
7351 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7352 VLA_HWINT_LENGTH (tab->full_vect));
7353 fprintf (output_file, "};\n\n");
7355 else
7357 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7358 fprintf (output_file, "static const ");
7359 output_range_type (output_file, tab->min_comb_vect_el_value,
7360 tab->max_comb_vect_el_value);
7361 fprintf (output_file, " ");
7362 (*output_comb_vect_name_func) (output_file, tab->automaton);
7363 fprintf (output_file, "[] = {\n");
7364 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7365 VLA_HWINT_LENGTH (tab->comb_vect));
7366 fprintf (output_file, "};\n\n");
7367 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7368 fprintf (output_file, "static const ");
7369 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7370 fprintf (output_file, " ");
7371 (*output_check_vect_name_func) (output_file, tab->automaton);
7372 fprintf (output_file, "[] = {\n");
7373 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7374 VLA_HWINT_LENGTH (tab->check_vect));
7375 fprintf (output_file, "};\n\n");
7376 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7377 fprintf (output_file, "static const ");
7378 output_range_type (output_file, tab->min_base_vect_el_value,
7379 tab->max_base_vect_el_value);
7380 fprintf (output_file, " ");
7381 (*output_base_vect_name_func) (output_file, tab->automaton);
7382 fprintf (output_file, "[] = {\n");
7383 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7384 VLA_HWINT_LENGTH (tab->base_vect));
7385 fprintf (output_file, "};\n\n");
7389 /* The following function adds vector with length VECT_LENGTH and
7390 elements pointed by VECT to table TAB as its line with number
7391 VECT_NUM. */
7392 static void
7393 add_vect (tab, vect_num, vect, vect_length)
7394 state_ainsn_table_t tab;
7395 int vect_num;
7396 vect_el_t *vect;
7397 int vect_length;
7399 int real_vect_length;
7400 vect_el_t *comb_vect_start;
7401 vect_el_t *check_vect_start;
7402 int comb_vect_index;
7403 int comb_vect_els_num;
7404 int vect_index;
7405 int first_unempty_vect_index;
7406 int additional_els_num;
7407 int no_state_value;
7408 vect_el_t vect_el;
7409 int i;
7411 if (vect_length == 0)
7412 abort ();
7413 real_vect_length = tab->automaton->insn_equiv_classes_num;
7414 if (vect [vect_length - 1] == undefined_vect_el_value)
7415 abort ();
7416 /* Form full vector in the table: */
7417 for (i = 0; i < vect_length; i++)
7418 VLA_HWINT (tab->full_vect,
7419 i + tab->automaton->insn_equiv_classes_num * vect_num)
7420 = vect [i];
7421 /* Form comb vector in the table: */
7422 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7423 abort ();
7424 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7425 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7426 for (first_unempty_vect_index = 0;
7427 first_unempty_vect_index < vect_length;
7428 first_unempty_vect_index++)
7429 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7430 break;
7431 /* Search for the place in comb vect for the inserted vect. */
7432 for (comb_vect_index = 0;
7433 comb_vect_index < comb_vect_els_num;
7434 comb_vect_index++)
7436 for (vect_index = first_unempty_vect_index;
7437 vect_index < vect_length
7438 && vect_index + comb_vect_index < comb_vect_els_num;
7439 vect_index++)
7440 if (vect [vect_index] != undefined_vect_el_value
7441 && (comb_vect_start [vect_index + comb_vect_index]
7442 != undefined_vect_el_value))
7443 break;
7444 if (vect_index >= vect_length
7445 || vect_index + comb_vect_index >= comb_vect_els_num)
7446 break;
7448 /* Slot was found. */
7449 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7450 if (additional_els_num < 0)
7451 additional_els_num = 0;
7452 /* Expand comb and check vectors. */
7453 vect_el = undefined_vect_el_value;
7454 no_state_value = tab->automaton->achieved_states_num;
7455 while (additional_els_num > 0)
7457 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7458 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7459 additional_els_num--;
7461 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7462 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7463 if (VLA_HWINT_LENGTH (tab->comb_vect)
7464 < (size_t) (comb_vect_index + real_vect_length))
7465 abort ();
7466 /* Fill comb and check vectors. */
7467 for (vect_index = 0; vect_index < vect_length; vect_index++)
7468 if (vect [vect_index] != undefined_vect_el_value)
7470 if (comb_vect_start [comb_vect_index + vect_index]
7471 != undefined_vect_el_value)
7472 abort ();
7473 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7474 if (vect [vect_index] < 0)
7475 abort ();
7476 if (tab->max_comb_vect_el_value < vect [vect_index])
7477 tab->max_comb_vect_el_value = vect [vect_index];
7478 if (tab->min_comb_vect_el_value > vect [vect_index])
7479 tab->min_comb_vect_el_value = vect [vect_index];
7480 check_vect_start [comb_vect_index + vect_index] = vect_num;
7482 if (tab->max_base_vect_el_value < comb_vect_index)
7483 tab->max_base_vect_el_value = comb_vect_index;
7484 if (tab->min_base_vect_el_value > comb_vect_index)
7485 tab->min_base_vect_el_value = comb_vect_index;
7486 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7489 /* Return number of out arcs of STATE. */
7490 static int
7491 out_state_arcs_num (state)
7492 state_t state;
7494 int result;
7495 arc_t arc;
7497 result = 0;
7498 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7500 if (arc->insn == NULL)
7501 abort ();
7502 if (arc->insn->first_ainsn_with_given_equialence_num)
7503 result++;
7505 return result;
7508 /* Compare number of possible transitions from the states. */
7509 static int
7510 compare_transition_els_num (state_ptr_1, state_ptr_2)
7511 const void *state_ptr_1;
7512 const void *state_ptr_2;
7514 int transition_els_num_1;
7515 int transition_els_num_2;
7517 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7518 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7519 if (transition_els_num_1 < transition_els_num_2)
7520 return 1;
7521 else if (transition_els_num_1 == transition_els_num_2)
7522 return 0;
7523 else
7524 return -1;
7527 /* The function adds element EL_VALUE to vector VECT for a table state
7528 x AINSN. */
7529 static void
7530 add_vect_el (vect, ainsn, el_value)
7531 vla_hwint_t *vect;
7532 ainsn_t ainsn;
7533 int el_value;
7535 int equiv_class_num;
7536 int vect_index;
7538 if (ainsn == NULL)
7539 abort ();
7540 equiv_class_num = ainsn->insn_equiv_class_num;
7541 for (vect_index = VLA_HWINT_LENGTH (*vect);
7542 vect_index <= equiv_class_num;
7543 vect_index++)
7544 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7545 VLA_HWINT (*vect, equiv_class_num) = el_value;
7548 /* This is for forming vector of states of an automaton. */
7549 static vla_ptr_t output_states_vect;
7551 /* The function is called by function pass_states. The function adds
7552 STATE to `output_states_vect'. */
7553 static void
7554 add_states_vect_el (state)
7555 state_t state;
7557 VLA_PTR_ADD (output_states_vect, state);
7560 /* Form and output vectors (comb, check, base or full vector)
7561 representing transition table of AUTOMATON. */
7562 static void
7563 output_trans_table (automaton)
7564 automaton_t automaton;
7566 state_t *state_ptr;
7567 arc_t arc;
7568 vla_hwint_t transition_vect;
7570 undefined_vect_el_value = automaton->achieved_states_num;
7571 automaton->trans_table = create_state_ainsn_table (automaton);
7572 /* Create vect of pointers to states ordered by num of transitions
7573 from the state (state with the maximum num is the first). */
7574 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7575 pass_states (automaton, add_states_vect_el);
7576 qsort (VLA_PTR_BEGIN (output_states_vect),
7577 VLA_PTR_LENGTH (output_states_vect),
7578 sizeof (state_t), compare_transition_els_num);
7579 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7580 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7581 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7582 state_ptr++)
7584 VLA_HWINT_NULLIFY (transition_vect);
7585 for (arc = first_out_arc (*state_ptr);
7586 arc != NULL;
7587 arc = next_out_arc (arc))
7589 if (arc->insn == NULL)
7590 abort ();
7591 if (arc->insn->first_ainsn_with_given_equialence_num)
7592 add_vect_el (&transition_vect, arc->insn,
7593 arc->to_state->order_state_num);
7595 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7596 VLA_HWINT_BEGIN (transition_vect),
7597 VLA_HWINT_LENGTH (transition_vect));
7599 output_state_ainsn_table
7600 (automaton->trans_table, (char *) "state transitions",
7601 output_trans_full_vect_name, output_trans_comb_vect_name,
7602 output_trans_check_vect_name, output_trans_base_vect_name);
7603 VLA_PTR_DELETE (output_states_vect);
7604 VLA_HWINT_DELETE (transition_vect);
7607 /* Form and output vectors (comb, check, base or simple vect)
7608 representing alts number table of AUTOMATON. The table is state x
7609 ainsn -> number of possible alternative reservations by the
7610 ainsn. */
7611 static void
7612 output_state_alts_table (automaton)
7613 automaton_t automaton;
7615 state_t *state_ptr;
7616 arc_t arc;
7617 vla_hwint_t state_alts_vect;
7619 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7620 automaton->state_alts_table = create_state_ainsn_table (automaton);
7621 /* Create vect of pointers to states ordered by num of transitions
7622 from the state (state with the maximum num is the first). */
7623 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7624 pass_states (automaton, add_states_vect_el);
7625 qsort (VLA_PTR_BEGIN (output_states_vect),
7626 VLA_PTR_LENGTH (output_states_vect),
7627 sizeof (state_t), compare_transition_els_num);
7628 /* Create base, comb, and check vectors. */
7629 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7630 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7631 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7632 state_ptr++)
7634 VLA_HWINT_NULLIFY (state_alts_vect);
7635 for (arc = first_out_arc (*state_ptr);
7636 arc != NULL;
7637 arc = next_out_arc (arc))
7639 if (arc->insn == NULL)
7640 abort ();
7641 if (arc->insn->first_ainsn_with_given_equialence_num)
7642 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7644 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7645 VLA_HWINT_BEGIN (state_alts_vect),
7646 VLA_HWINT_LENGTH (state_alts_vect));
7648 output_state_ainsn_table
7649 (automaton->state_alts_table, (char *) "state insn alternatives",
7650 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7651 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7652 VLA_PTR_DELETE (output_states_vect);
7653 VLA_HWINT_DELETE (state_alts_vect);
7656 /* The current number of passing states to find minimal issue delay
7657 value for an ainsn and state. */
7658 static int curr_state_pass_num;
7661 /* This recursive function passes states to find minimal issue delay
7662 value for AINSN. The state being visited is STATE. The function
7663 returns minimal issue delay value for AINSN in STATE or -1 if we
7664 enter into a loop. */
7665 static int
7666 min_issue_delay_pass_states (state, ainsn)
7667 state_t state;
7668 ainsn_t ainsn;
7670 arc_t arc;
7671 int min_insn_issue_delay, insn_issue_delay;
7673 if (state->state_pass_num == curr_state_pass_num
7674 || state->min_insn_issue_delay != -1)
7675 /* We've entered into a loop or already have the correct value for
7676 given state and ainsn. */
7677 return state->min_insn_issue_delay;
7678 state->state_pass_num = curr_state_pass_num;
7679 min_insn_issue_delay = -1;
7680 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7681 if (arc->insn == ainsn)
7683 min_insn_issue_delay = 0;
7684 break;
7686 else
7688 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7689 if (insn_issue_delay != -1)
7691 if (arc->insn->insn_reserv_decl
7692 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7693 insn_issue_delay++;
7694 if (min_insn_issue_delay == -1
7695 || min_insn_issue_delay > insn_issue_delay)
7697 min_insn_issue_delay = insn_issue_delay;
7698 if (insn_issue_delay == 0)
7699 break;
7703 return min_insn_issue_delay;
7706 /* The function searches minimal issue delay value for AINSN in STATE.
7707 The function can return negative value if we can not issue AINSN. We
7708 will report about it later. */
7709 static int
7710 min_issue_delay (state, ainsn)
7711 state_t state;
7712 ainsn_t ainsn;
7714 curr_state_pass_num++;
7715 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7716 return state->min_insn_issue_delay;
7719 /* The function initiates code for finding minimal issue delay values.
7720 It should be called only once. */
7721 static void
7722 initiate_min_issue_delay_pass_states ()
7724 curr_state_pass_num = 0;
7727 /* Form and output vectors representing minimal issue delay table of
7728 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7729 the ainsn. */
7730 static void
7731 output_min_issue_delay_table (automaton)
7732 automaton_t automaton;
7734 vla_hwint_t min_issue_delay_vect;
7735 vla_hwint_t compressed_min_issue_delay_vect;
7736 vect_el_t min_delay;
7737 ainsn_t ainsn;
7738 state_t *state_ptr;
7739 int i;
7741 /* Create vect of pointers to states ordered by num of transitions
7742 from the state (state with the maximum num is the first). */
7743 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7744 pass_states (automaton, add_states_vect_el);
7745 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7746 VLA_HWINT_EXPAND (min_issue_delay_vect,
7747 VLA_HWINT_LENGTH (output_states_vect)
7748 * automaton->insn_equiv_classes_num);
7749 for (i = 0;
7750 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7751 * automaton->insn_equiv_classes_num);
7752 i++)
7753 VLA_HWINT (min_issue_delay_vect, i) = 0;
7754 automaton->max_min_delay = 0;
7755 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7756 if (ainsn->first_ainsn_with_given_equialence_num)
7758 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7759 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7760 state_ptr++)
7761 (*state_ptr)->min_insn_issue_delay = -1;
7762 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7763 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7764 state_ptr++)
7766 min_delay = min_issue_delay (*state_ptr, ainsn);
7767 if (automaton->max_min_delay < min_delay)
7768 automaton->max_min_delay = min_delay;
7769 VLA_HWINT (min_issue_delay_vect,
7770 (*state_ptr)->order_state_num
7771 * automaton->insn_equiv_classes_num
7772 + ainsn->insn_equiv_class_num) = min_delay;
7775 fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
7776 fprintf (output_file, "static const ");
7777 output_range_type (output_file, 0, automaton->max_min_delay);
7778 fprintf (output_file, " ");
7779 output_min_issue_delay_vect_name (output_file, automaton);
7780 fprintf (output_file, "[] = {\n");
7781 /* Compress the vector */
7782 if (automaton->max_min_delay < 2)
7783 automaton->min_issue_delay_table_compression_factor = 8;
7784 else if (automaton->max_min_delay < 4)
7785 automaton->min_issue_delay_table_compression_factor = 4;
7786 else if (automaton->max_min_delay < 16)
7787 automaton->min_issue_delay_table_compression_factor = 2;
7788 else
7789 automaton->min_issue_delay_table_compression_factor = 1;
7790 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7791 "compressed min issue delay vector");
7792 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7793 (VLA_HWINT_LENGTH (min_issue_delay_vect)
7794 + automaton->min_issue_delay_table_compression_factor
7795 - 1)
7796 / automaton->min_issue_delay_table_compression_factor);
7797 for (i = 0;
7798 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7799 i++)
7800 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7801 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7802 VLA_HWINT (compressed_min_issue_delay_vect,
7803 i / automaton->min_issue_delay_table_compression_factor)
7804 |= (VLA_HWINT (min_issue_delay_vect, i)
7805 << (8 - (i % automaton->min_issue_delay_table_compression_factor
7806 + 1)
7807 * (8 / automaton->min_issue_delay_table_compression_factor)));
7808 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7809 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7810 fprintf (output_file, "};\n\n");
7811 VLA_PTR_DELETE (output_states_vect);
7812 VLA_HWINT_DELETE (min_issue_delay_vect);
7813 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7816 #ifndef NDEBUG
7817 /* Number of states which contains transition only by advancing cpu
7818 cycle. */
7819 static int locked_states_num;
7820 #endif
7822 /* Form and output vector representing the locked states of
7823 AUTOMATON. */
7824 static void
7825 output_dead_lock_vect (automaton)
7826 automaton_t automaton;
7828 state_t *state_ptr;
7829 arc_t arc;
7830 vla_hwint_t dead_lock_vect;
7832 /* Create vect of pointers to states ordered by num of
7833 transitions from the state (state with the maximum num is the
7834 first). */
7835 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7836 pass_states (automaton, add_states_vect_el);
7837 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7838 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7839 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7840 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7841 state_ptr++)
7843 arc = first_out_arc (*state_ptr);
7844 if (arc == NULL)
7845 abort ();
7846 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
7847 = (next_out_arc (arc) == NULL
7848 && (arc->insn->insn_reserv_decl
7849 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
7850 #ifndef NDEBUG
7851 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
7852 locked_states_num++;
7853 #endif
7855 fprintf (output_file, "/* Vector for locked state flags. */\n");
7856 fprintf (output_file, "static const ");
7857 output_range_type (output_file, 0, 1);
7858 fprintf (output_file, " ");
7859 output_dead_lock_vect_name (output_file, automaton);
7860 fprintf (output_file, "[] = {\n");
7861 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
7862 VLA_HWINT_LENGTH (dead_lock_vect));
7863 fprintf (output_file, "};\n\n");
7864 VLA_HWINT_DELETE (dead_lock_vect);
7865 VLA_PTR_DELETE (output_states_vect);
7868 /* Form and output vector representing reserved units of the states of
7869 AUTOMATON. */
7870 static void
7871 output_reserved_units_table (automaton)
7872 automaton_t automaton;
7874 state_t *curr_state_ptr;
7875 vla_hwint_t reserved_units_table;
7876 size_t state_byte_size;
7877 int i;
7879 /* Create vect of pointers to states. */
7880 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7881 pass_states (automaton, add_states_vect_el);
7882 /* Create vector. */
7883 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
7884 state_byte_size = (description->query_units_num + 7) / 8;
7885 VLA_HWINT_EXPAND (reserved_units_table,
7886 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7887 for (i = 0;
7888 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7889 i++)
7890 VLA_HWINT (reserved_units_table, i) = 0;
7891 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
7892 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7893 curr_state_ptr++)
7895 for (i = 0; i < description->units_num; i++)
7896 if (units_array [i]->query_p)
7898 if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i))
7899 VLA_HWINT (reserved_units_table,
7900 (*curr_state_ptr)->order_state_num * state_byte_size
7901 + units_array [i]->query_num / 8)
7902 += (1 << (units_array [i]->query_num % 8));
7905 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7906 fprintf (output_file, "static const ");
7907 output_range_type (output_file, 0, 255);
7908 fprintf (output_file, " ");
7909 output_reserved_units_table_name (output_file, automaton);
7910 fprintf (output_file, "[] = {\n");
7911 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
7912 VLA_HWINT_LENGTH (reserved_units_table));
7913 fprintf (output_file, "};\n\n");
7914 VLA_HWINT_DELETE (reserved_units_table);
7915 VLA_PTR_DELETE (output_states_vect);
7918 /* The function outputs all tables representing DFA(s) used for fast
7919 pipeline hazards recognition. */
7920 static void
7921 output_tables ()
7923 automaton_t automaton;
7925 #ifndef NDEBUG
7926 locked_states_num = 0;
7927 #endif
7928 initiate_min_issue_delay_pass_states ();
7929 for (automaton = description->first_automaton;
7930 automaton != NULL;
7931 automaton = automaton->next_automaton)
7933 output_translate_vect (automaton);
7934 output_trans_table (automaton);
7935 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
7936 output_state_alts_table (automaton);
7937 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7938 AUTOMATON_STATE_ALTS_MACRO_NAME);
7939 output_min_issue_delay_table (automaton);
7940 output_dead_lock_vect (automaton);
7941 if (no_minimization_flag)
7943 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
7944 output_reserved_units_table (automaton);
7945 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7946 CPU_UNITS_QUERY_MACRO_NAME);
7949 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7950 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7953 /* The function outputs definition and value of PHR interface variable
7954 `max_insn_queue_index'. Its value is not less than maximal queue
7955 length needed for the insn scheduler. */
7956 static void
7957 output_max_insn_queue_index_def ()
7959 int i, max, latency;
7960 decl_t decl;
7962 max = description->max_insn_reserv_cycles;
7963 for (i = 0; i < description->decls_num; i++)
7965 decl = description->decls [i];
7966 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7968 latency = DECL_INSN_RESERV (decl)->default_latency;
7969 if (latency > max)
7970 max = latency;
7972 else if (decl->mode == dm_bypass)
7974 latency = DECL_BYPASS (decl)->latency;
7975 if (latency > max)
7976 max = latency;
7979 for (i = 0; (1 << i) <= max; i++)
7981 if (i < 0)
7982 abort ();
7983 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
7987 /* The function outputs switch cases for insn reseravtions using
7988 function *output_automata_list_code. */
7989 static void
7990 output_insn_code_cases (output_automata_list_code)
7991 void (*output_automata_list_code) (automata_list_el_t);
7993 decl_t decl, decl2;
7994 int i, j;
7996 for (i = 0; i < description->decls_num; i++)
7998 decl = description->decls [i];
7999 if (decl->mode == dm_insn_reserv)
8000 DECL_INSN_RESERV (decl)->processed_p = FALSE;
8002 for (i = 0; i < description->decls_num; i++)
8004 decl = description->decls [i];
8005 if (decl->mode == dm_insn_reserv
8006 && !DECL_INSN_RESERV (decl)->processed_p)
8008 for (j = i; j < description->decls_num; j++)
8010 decl2 = description->decls [j];
8011 if (decl2->mode == dm_insn_reserv
8012 && (DECL_INSN_RESERV (decl2)->important_automata_list
8013 == DECL_INSN_RESERV (decl)->important_automata_list))
8015 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8016 fprintf (output_file, " case %d: /* %s */\n",
8017 DECL_INSN_RESERV (decl2)->insn_num,
8018 DECL_INSN_RESERV (decl2)->name);
8021 (*output_automata_list_code)
8022 (DECL_INSN_RESERV (decl)->important_automata_list);
8028 /* The function outputs a code for evaluation of a minimal delay of
8029 issue of insns which have reservations in given AUTOMATA_LIST. */
8030 static void
8031 output_automata_list_min_issue_delay_code (automata_list)
8032 automata_list_el_t automata_list;
8034 automata_list_el_t el;
8035 automaton_t automaton;
8037 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8039 automaton = el->automaton;
8040 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8041 output_min_issue_delay_vect_name (output_file, automaton);
8042 fprintf (output_file,
8043 (automaton->min_issue_delay_table_compression_factor != 1
8044 ? " [(" : " ["));
8045 output_translate_vect_name (output_file, automaton);
8046 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8047 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8048 output_chip_member_name (output_file, automaton);
8049 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8050 if (automaton->min_issue_delay_table_compression_factor == 1)
8051 fprintf (output_file, "];\n");
8052 else
8054 fprintf (output_file, ") / %d];\n",
8055 automaton->min_issue_delay_table_compression_factor);
8056 fprintf (output_file, " %s = (%s >> (8 - (",
8057 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8058 output_translate_vect_name (output_file, automaton);
8059 fprintf
8060 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8061 INTERNAL_INSN_CODE_NAME,
8062 automaton->min_issue_delay_table_compression_factor,
8063 8 / automaton->min_issue_delay_table_compression_factor,
8064 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8065 - 1);
8067 if (el == automata_list)
8068 fprintf (output_file, " %s = %s;\n",
8069 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8070 else
8072 fprintf (output_file, " if (%s > %s)\n",
8073 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8074 fprintf (output_file, " %s = %s;\n",
8075 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8078 fprintf (output_file, " break;\n\n");
8081 /* Output function `internal_min_issue_delay'. */
8082 static void
8083 output_internal_min_issue_delay_func ()
8085 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8086 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
8087 fprintf (output_file,
8088 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8089 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8090 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8091 CHIP_PARAMETER_NAME);
8092 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s;\n",
8093 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8094 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8095 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8096 fprintf (output_file,
8097 "\n default:\n %s = -1;\n break;\n }\n",
8098 RESULT_VARIABLE_NAME);
8099 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8100 fprintf (output_file, "}\n\n");
8103 /* The function outputs a code changing state after issue of insns
8104 which have reservations in given AUTOMATA_LIST. */
8105 static void
8106 output_automata_list_transition_code (automata_list)
8107 automata_list_el_t automata_list;
8109 automata_list_el_t el, next_el;
8111 fprintf (output_file, " {\n");
8112 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8113 for (el = automata_list;; el = next_el)
8115 next_el = el->next_automata_list_el;
8116 if (next_el == NULL)
8117 break;
8118 fprintf (output_file, " ");
8119 output_state_member_type (output_file, el->automaton);
8120 fprintf (output_file, " ");
8121 output_temp_chip_member_name (output_file, el->automaton);
8122 fprintf (output_file, ";\n");
8124 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8125 if (comb_vect_p (el->automaton->trans_table))
8127 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8128 output_trans_base_vect_name (output_file, el->automaton);
8129 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8130 output_chip_member_name (output_file, el->automaton);
8131 fprintf (output_file, "] + ");
8132 output_translate_vect_name (output_file, el->automaton);
8133 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8134 fprintf (output_file, " if (");
8135 output_trans_check_vect_name (output_file, el->automaton);
8136 fprintf (output_file, " [%s] != %s->",
8137 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8138 output_chip_member_name (output_file, el->automaton);
8139 fprintf (output_file, ")\n");
8140 fprintf (output_file, " return %s (%s, %s);\n",
8141 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8142 CHIP_PARAMETER_NAME);
8143 fprintf (output_file, " else\n");
8144 fprintf (output_file, " ");
8145 if (el->next_automata_list_el != NULL)
8146 output_temp_chip_member_name (output_file, el->automaton);
8147 else
8149 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8150 output_chip_member_name (output_file, el->automaton);
8152 fprintf (output_file, " = ");
8153 output_trans_comb_vect_name (output_file, el->automaton);
8154 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8156 else
8158 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8159 output_trans_full_vect_name (output_file, el->automaton);
8160 fprintf (output_file, " [");
8161 output_translate_vect_name (output_file, el->automaton);
8162 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8163 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8164 output_chip_member_name (output_file, el->automaton);
8165 fprintf (output_file, " * %d];\n",
8166 el->automaton->insn_equiv_classes_num);
8167 fprintf (output_file, " if (%s >= %d)\n",
8168 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8169 fprintf (output_file, " return %s (%s, %s);\n",
8170 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8171 CHIP_PARAMETER_NAME);
8172 fprintf (output_file, " else\n ");
8173 if (el->next_automata_list_el != NULL)
8174 output_temp_chip_member_name (output_file, el->automaton);
8175 else
8177 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8178 output_chip_member_name (output_file, el->automaton);
8180 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8182 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8183 for (el = automata_list;; el = next_el)
8185 next_el = el->next_automata_list_el;
8186 if (next_el == NULL)
8187 break;
8188 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8189 output_chip_member_name (output_file, el->automaton);
8190 fprintf (output_file, " = ");
8191 output_temp_chip_member_name (output_file, el->automaton);
8192 fprintf (output_file, ";\n");
8194 fprintf (output_file, " return -1;\n");
8195 fprintf (output_file, " }\n");
8198 /* Output function `internal_state_transition'. */
8199 static void
8200 output_internal_trans_func ()
8202 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8203 INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
8204 fprintf (output_file,
8205 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8206 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8207 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
8208 CHIP_NAME, CHIP_PARAMETER_NAME);
8209 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8210 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8211 output_insn_code_cases (output_automata_list_transition_code);
8212 fprintf (output_file, "\n default:\n return -1;\n }\n");
8213 fprintf (output_file, "}\n\n");
8216 /* Output code
8218 if (insn != 0)
8220 insn_code = dfa_insn_code (insn);
8221 if (insn_code > DFA__ADVANCE_CYCLE)
8222 return code;
8224 else
8225 insn_code = DFA__ADVANCE_CYCLE;
8227 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8228 code denotes CODE. */
8229 static void
8230 output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
8231 const char *insn_name;
8232 const char *insn_code_name;
8233 int code;
8235 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8236 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8237 DFA_INSN_CODE_FUNC_NAME, insn_name);
8238 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8239 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8240 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8241 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8245 /* The function outputs function `dfa_insn_code'. */
8246 static void
8247 output_dfa_insn_code_func ()
8249 fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n");
8250 fprintf (output_file, "static int %s PARAMS ((rtx));\n",
8251 DFA_INSN_CODE_FUNC_NAME);
8252 fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
8253 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
8254 fprintf (output_file, "{\n int %s;\n int %s;\n\n",
8255 INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
8256 fprintf (output_file, " if (INSN_UID (%s) >= %s)\n {\n",
8257 INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8258 fprintf (output_file, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
8259 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8260 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
8261 fprintf (output_file, " %s = xrealloc (%s, %s * sizeof (int));\n",
8262 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8263 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8264 fprintf (output_file,
8265 " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
8266 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8267 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8268 TEMPORARY_VARIABLE_NAME);
8269 fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
8270 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8271 INSN_PARAMETER_NAME);
8272 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8273 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8274 fprintf (output_file, " %s [INSN_UID (%s)] = %s;\n",
8275 DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME,
8276 INTERNAL_INSN_CODE_NAME);
8277 fprintf (output_file, " }\n return %s;\n}\n\n",
8278 INTERNAL_INSN_CODE_NAME);
8281 /* The function outputs PHR interface function `state_transition'. */
8282 static void
8283 output_trans_func ()
8285 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8286 TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8287 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8288 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8289 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8290 INTERNAL_INSN_CODE_NAME, -1);
8291 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8292 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8295 /* The function outputs a code for evaluation of alternative states
8296 number for insns which have reservations in given AUTOMATA_LIST. */
8297 static void
8298 output_automata_list_state_alts_code (automata_list)
8299 automata_list_el_t automata_list;
8301 automata_list_el_t el;
8302 automaton_t automaton;
8304 fprintf (output_file, " {\n");
8305 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8306 if (comb_vect_p (el->automaton->state_alts_table))
8308 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8309 break;
8311 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8313 automaton = el->automaton;
8314 if (comb_vect_p (automaton->state_alts_table))
8316 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8317 output_state_alts_base_vect_name (output_file, automaton);
8318 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8319 output_chip_member_name (output_file, automaton);
8320 fprintf (output_file, "] + ");
8321 output_translate_vect_name (output_file, automaton);
8322 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8323 fprintf (output_file, " if (");
8324 output_state_alts_check_vect_name (output_file, automaton);
8325 fprintf (output_file, " [%s] != %s->",
8326 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8327 output_chip_member_name (output_file, automaton);
8328 fprintf (output_file, ")\n");
8329 fprintf (output_file, " return 0;\n");
8330 fprintf (output_file, " else\n");
8331 fprintf (output_file,
8332 (el == automata_list
8333 ? " %s = " : " %s += "),
8334 RESULT_VARIABLE_NAME);
8335 output_state_alts_comb_vect_name (output_file, automaton);
8336 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8338 else
8340 fprintf (output_file,
8341 (el == automata_list
8342 ? "\n %s = " : " %s += "),
8343 RESULT_VARIABLE_NAME);
8344 output_state_alts_full_vect_name (output_file, automaton);
8345 fprintf (output_file, " [");
8346 output_translate_vect_name (output_file, automaton);
8347 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8348 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8349 output_chip_member_name (output_file, automaton);
8350 fprintf (output_file, " * %d];\n",
8351 automaton->insn_equiv_classes_num);
8354 fprintf (output_file, " break;\n }\n\n");
8357 /* Output function `internal_state_alts'. */
8358 static void
8359 output_internal_state_alts_func ()
8361 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8362 INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8363 fprintf (output_file,
8364 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8365 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8366 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8367 CHIP_PARAMETER_NAME);
8368 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8369 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8370 output_insn_code_cases (output_automata_list_state_alts_code);
8371 fprintf (output_file,
8372 "\n default:\n %s = 0;\n break;\n }\n",
8373 RESULT_VARIABLE_NAME);
8374 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8375 fprintf (output_file, "}\n\n");
8378 /* The function outputs PHR interface function `state_alts'. */
8379 static void
8380 output_state_alts_func ()
8382 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8383 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8384 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8385 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8386 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8387 INTERNAL_INSN_CODE_NAME, 0);
8388 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8389 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8392 /* Output function `min_issue_delay'. */
8393 static void
8394 output_min_issue_delay_func ()
8396 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8397 MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8398 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8399 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8400 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8401 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8402 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8403 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8404 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8405 fprintf (output_file, " }\n else\n %s = %s;\n",
8406 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8407 fprintf (output_file, "\n return %s (%s, %s);\n",
8408 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8409 STATE_NAME);
8410 fprintf (output_file, "}\n\n");
8413 /* Output function `internal_dead_lock'. */
8414 static void
8415 output_internal_dead_lock_func ()
8417 automaton_t automaton;
8419 fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8420 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8421 fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8422 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8423 CHIP_PARAMETER_NAME);
8424 fprintf (output_file, "{\n");
8425 for (automaton = description->first_automaton;
8426 automaton != NULL;
8427 automaton = automaton->next_automaton)
8429 fprintf (output_file, " if (");
8430 output_dead_lock_vect_name (output_file, automaton);
8431 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8432 output_chip_member_name (output_file, automaton);
8433 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8435 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8438 /* The function outputs PHR interface function `state_dead_lock_p'. */
8439 static void
8440 output_dead_lock_func ()
8442 fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8443 DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8444 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8445 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8448 /* Output function `internal_reset'. */
8449 static void
8450 output_internal_reset_func ()
8452 fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8453 INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8454 fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8455 INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8456 CHIP_NAME, CHIP_PARAMETER_NAME);
8457 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8458 CHIP_PARAMETER_NAME, CHIP_NAME);
8461 /* The function outputs PHR interface function `state_size'. */
8462 static void
8463 output_size_func ()
8465 fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8466 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8469 /* The function outputs PHR interface function `state_reset'. */
8470 static void
8471 output_reset_func ()
8473 fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8474 RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8475 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8476 STATE_NAME);
8479 /* Output function `min_insn_conflict_delay'. */
8480 static void
8481 output_min_insn_conflict_delay_func ()
8483 fprintf (output_file,
8484 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8485 MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8486 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8487 STATE_TYPE_NAME, STATE_NAME,
8488 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8489 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8490 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8491 INTERNAL_INSN2_CODE_NAME);
8492 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8493 INTERNAL_INSN_CODE_NAME, 0);
8494 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8495 INTERNAL_INSN2_CODE_NAME, 0);
8496 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8497 CHIP_NAME, STATE_NAME, CHIP_NAME);
8498 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8499 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8500 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8501 fprintf (output_file, " return %s (%s, &%s);\n",
8502 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8503 CHIP_NAME);
8504 fprintf (output_file, "}\n\n");
8507 /* Output function `internal_insn_latency'. */
8508 static void
8509 output_internal_insn_latency_func ()
8511 decl_t decl;
8512 struct bypass_decl *bypass;
8513 int i;
8515 fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8516 INTERNAL_INSN_LATENCY_FUNC_NAME);
8517 fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8518 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8519 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8520 INSN2_PARAMETER_NAME);
8521 fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
8522 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8523 fprintf (output_file,
8524 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
8525 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8526 fprintf (output_file, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8527 for (i = 0; i < description->decls_num; i++)
8529 decl = description->decls [i];
8530 if (decl->mode == dm_insn_reserv)
8532 fprintf (output_file, " case %d:\n",
8533 DECL_INSN_RESERV (decl)->insn_num);
8534 if (DECL_INSN_RESERV (decl)->bypass_list == NULL)
8535 fprintf (output_file, " return (%s != %s ? %d : 0);\n",
8536 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8537 DECL_INSN_RESERV (decl)->default_latency);
8538 else
8540 fprintf (output_file, " switch (%s)\n {\n",
8541 INTERNAL_INSN2_CODE_NAME);
8542 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8543 bypass != NULL;
8544 bypass = bypass->next)
8546 fprintf (output_file, " case %d:\n",
8547 bypass->in_insn_reserv->insn_num);
8548 if (bypass->bypass_guard_name == NULL)
8549 fprintf (output_file, " return %d;\n",
8550 bypass->latency);
8551 else
8552 fprintf (output_file,
8553 " return (%s (%s, %s) ? %d : %d);\n",
8554 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8555 INSN2_PARAMETER_NAME, bypass->latency,
8556 DECL_INSN_RESERV (decl)->default_latency);
8558 fprintf (output_file, " default:\n");
8559 fprintf (output_file,
8560 " return (%s != %s ? %d : 0);\n }\n",
8561 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8562 DECL_INSN_RESERV (decl)->default_latency);
8567 fprintf (output_file, " default:\n return 0;\n }\n}\n\n");
8570 /* The function outputs PHR interface function `insn_latency'. */
8571 static void
8572 output_insn_latency_func ()
8574 fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
8575 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8576 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8577 fprintf (output_file, "{\n int %s, %s;\n",
8578 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8579 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8580 INTERNAL_INSN_CODE_NAME, 0);
8581 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8582 INTERNAL_INSN2_CODE_NAME, 0);
8583 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8584 INTERNAL_INSN_LATENCY_FUNC_NAME,
8585 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8586 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8589 /* The function outputs PHR interface function `print_reservation'. */
8590 static void
8591 output_print_reservation_func ()
8593 decl_t decl;
8594 int i;
8596 fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
8597 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8598 INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
8599 INSN_PARAMETER_NAME);
8600 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8601 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8602 fprintf (output_file, " %s = %s (%s);\n",
8603 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8604 INSN_PARAMETER_NAME);
8605 fprintf (output_file, " if (%s > %s)\n",
8606 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8607 fprintf (output_file, " {\n fprintf (%s, \"%s\");\n",
8608 FILE_PARAMETER_NAME, NOTHING_NAME);
8609 fprintf (output_file, " return;\n }\n");
8610 fprintf (output_file, " }\n else\n");
8611 fprintf (output_file,
8612 " {\n fprintf (%s, \"%s\");\n return;\n }\n",
8613 FILE_PARAMETER_NAME, NOTHING_NAME);
8614 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8615 for (i = 0; i < description->decls_num; i++)
8617 decl = description->decls [i];
8618 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8620 fprintf (output_file,
8621 " case %d:\n", DECL_INSN_RESERV (decl)->insn_num);
8622 fprintf (output_file,
8623 " fprintf (%s, \"%s\");\n break;\n",
8624 FILE_PARAMETER_NAME,
8625 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8626 finish_regexp_representation ();
8629 fprintf (output_file, " default:\n fprintf (%s, \"%s\");\n }\n",
8630 FILE_PARAMETER_NAME, NOTHING_NAME);
8631 fprintf (output_file, "}\n\n");
8634 /* The following function is used to sort unit declaration by their
8635 names. */
8636 static int
8637 units_cmp (unit1, unit2)
8638 const void *unit1, *unit2;
8640 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8641 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8643 return strcmp (u1->name, u2->name);
8646 /* The following macro value is name of struct containing unit name
8647 and unit code. */
8648 #define NAME_CODE_STRUCT_NAME "name_code"
8650 /* The following macro value is name of table of struct name_code. */
8651 #define NAME_CODE_TABLE_NAME "name_code_table"
8653 /* The following macro values are member names for struct name_code. */
8654 #define NAME_MEMBER_NAME "name"
8655 #define CODE_MEMBER_NAME "code"
8657 /* The following macro values are local variable names for function
8658 `get_cpu_unit_code'. */
8659 #define CMP_VARIABLE_NAME "cmp"
8660 #define LOW_VARIABLE_NAME "l"
8661 #define MIDDLE_VARIABLE_NAME "m"
8662 #define HIGH_VARIABLE_NAME "h"
8664 /* The following function outputs function to obtain internal cpu unit
8665 code by the cpu unit name. */
8666 static void
8667 output_get_cpu_unit_code_func ()
8669 int i;
8670 unit_decl_t *units;
8672 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8673 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8674 CPU_UNIT_NAME_PARAMETER_NAME);
8675 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8676 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8677 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8678 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8679 fprintf (output_file, " static struct %s %s [] =\n {\n",
8680 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8681 units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
8682 * description->units_num);
8683 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8684 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8685 for (i = 0; i < description->units_num; i++)
8686 if (units [i]->query_p)
8687 fprintf (output_file, " {\"%s\", %d},\n",
8688 units[i]->name, units[i]->query_num);
8689 fprintf (output_file, " };\n\n");
8690 fprintf (output_file, " /* The following is binary search: */\n");
8691 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8692 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8693 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8694 fprintf (output_file, " while (%s <= %s)\n {\n",
8695 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8696 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8697 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8698 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8699 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8700 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8701 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8702 fprintf (output_file, " %s = %s - 1;\n",
8703 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8704 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8705 fprintf (output_file, " %s = %s + 1;\n",
8706 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8707 fprintf (output_file, " else\n");
8708 fprintf (output_file, " return %s [%s].%s;\n }\n",
8709 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8710 fprintf (output_file, " return -1;\n}\n\n");
8711 free (units);
8714 /* The following function outputs function to check reservation of cpu
8715 unit (its internal code will be passed as the function argument) in
8716 given cpu state. */
8717 static void
8718 output_cpu_unit_reservation_p ()
8720 automaton_t automaton;
8722 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8723 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8724 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8725 CPU_CODE_PARAMETER_NAME);
8726 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8727 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8728 description->query_units_num);
8729 for (automaton = description->first_automaton;
8730 automaton != NULL;
8731 automaton = automaton->next_automaton)
8733 fprintf (output_file, " if ((");
8734 output_reserved_units_table_name (output_file, automaton);
8735 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8736 output_chip_member_name (output_file, automaton);
8737 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8738 (description->query_units_num + 7) / 8,
8739 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8740 fprintf (output_file, " return 1;\n");
8742 fprintf (output_file, " return 0;\n}\n\n");
8745 /* The function outputs PHR interface function `dfa_start'. */
8746 static void
8747 output_dfa_start_func ()
8749 fprintf (output_file,
8750 "void\n%s ()\n{\n int %s;\n\n %s = get_max_uid ();\n",
8751 DFA_START_FUNC_NAME, I_VARIABLE_NAME,
8752 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8753 fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
8754 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8755 fprintf (output_file,
8756 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8757 I_VARIABLE_NAME, I_VARIABLE_NAME,
8758 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8759 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8762 /* The function outputs PHR interface function `dfa_finish'. */
8763 static void
8764 output_dfa_finish_func ()
8766 fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
8767 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8772 /* The page contains code for output description file (readable
8773 representation of original description and generated DFA(s). */
8775 /* The function outputs string representation of IR reservation. */
8776 static void
8777 output_regexp (regexp)
8778 regexp_t regexp;
8780 fprintf (output_description_file, "%s", regexp_representation (regexp));
8781 finish_regexp_representation ();
8784 /* Output names of units in LIST separated by comma. */
8785 static void
8786 output_unit_set_el_list (list)
8787 unit_set_el_t list;
8789 unit_set_el_t el;
8791 for (el = list; el != NULL; el = el->next_unit_set_el)
8793 if (el != list)
8794 fprintf (output_description_file, ",");
8795 fprintf (output_description_file, "%s", el->unit_decl->name);
8799 /* The function outputs string representation of IR define_reservation
8800 and define_insn_reservation. */
8801 static void
8802 output_description ()
8804 decl_t decl;
8805 int i;
8807 for (i = 0; i < description->decls_num; i++)
8809 decl = description->decls [i];
8810 if (decl->mode == dm_unit)
8812 if (DECL_UNIT (decl)->excl_list != NULL)
8814 fprintf (output_description_file, "unit %s exlusion_set: ",
8815 DECL_UNIT (decl)->name);
8816 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8817 fprintf (output_description_file, "\n");
8819 if (DECL_UNIT (decl)->presence_list != NULL)
8821 fprintf (output_description_file, "unit %s presence_set: ",
8822 DECL_UNIT (decl)->name);
8823 output_unit_set_el_list (DECL_UNIT (decl)->presence_list);
8824 fprintf (output_description_file, "\n");
8826 if (DECL_UNIT (decl)->absence_list != NULL)
8828 fprintf (output_description_file, "unit %s absence_set: ",
8829 DECL_UNIT (decl)->name);
8830 output_unit_set_el_list (DECL_UNIT (decl)->absence_list);
8831 fprintf (output_description_file, "\n");
8835 fprintf (output_description_file, "\n");
8836 for (i = 0; i < description->decls_num; i++)
8838 decl = description->decls [i];
8839 if (decl->mode == dm_reserv)
8841 fprintf (output_description_file, "reservation ");
8842 fprintf (output_description_file, DECL_RESERV (decl)->name);
8843 fprintf (output_description_file, ": ");
8844 output_regexp (DECL_RESERV (decl)->regexp);
8845 fprintf (output_description_file, "\n");
8847 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8849 fprintf (output_description_file, "insn reservation %s ",
8850 DECL_INSN_RESERV (decl)->name);
8851 print_rtl (output_description_file,
8852 DECL_INSN_RESERV (decl)->condexp);
8853 fprintf (output_description_file, ": ");
8854 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8855 fprintf (output_description_file, "\n");
8857 else if (decl->mode == dm_bypass)
8858 fprintf (output_description_file, "bypass %d %s %s\n",
8859 DECL_BYPASS (decl)->latency,
8860 DECL_BYPASS (decl)->out_insn_name,
8861 DECL_BYPASS (decl)->in_insn_name);
8863 fprintf (output_description_file, "\n\f\n");
8866 /* The function outputs name of AUTOMATON. */
8867 static void
8868 output_automaton_name (f, automaton)
8869 FILE *f;
8870 automaton_t automaton;
8872 if (automaton->corresponding_automaton_decl == NULL)
8873 fprintf (f, "#%d", automaton->automaton_order_num);
8874 else
8875 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8878 /* Maximal length of line for pretty printing into description
8879 file. */
8880 #define MAX_LINE_LENGTH 70
8882 /* The function outputs units name belonging to AUTOMATON. */
8883 static void
8884 output_automaton_units (automaton)
8885 automaton_t automaton;
8887 decl_t decl;
8888 char *name;
8889 int curr_line_length;
8890 int there_is_an_automaton_unit;
8891 int i;
8893 fprintf (output_description_file, "\n Coresponding units:\n");
8894 fprintf (output_description_file, " ");
8895 curr_line_length = 4;
8896 there_is_an_automaton_unit = 0;
8897 for (i = 0; i < description->decls_num; i++)
8899 decl = description->decls [i];
8900 if (decl->mode == dm_unit
8901 && (DECL_UNIT (decl)->corresponding_automaton_num
8902 == automaton->automaton_order_num))
8904 there_is_an_automaton_unit = 1;
8905 name = DECL_UNIT (decl)->name;
8906 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8908 curr_line_length = strlen (name) + 4;
8909 fprintf (output_description_file, "\n ");
8911 else
8913 curr_line_length += strlen (name) + 1;
8914 fprintf (output_description_file, " ");
8916 fprintf (output_description_file, name);
8919 if (!there_is_an_automaton_unit)
8920 fprintf (output_description_file, "<None>");
8921 fprintf (output_description_file, "\n\n");
8924 /* The following variable is used for forming array of all possible cpu unit
8925 reservations described by the current DFA state. */
8926 static vla_ptr_t state_reservs;
8928 /* The function forms `state_reservs' for STATE. */
8929 static void
8930 add_state_reservs (state)
8931 state_t state;
8933 alt_state_t curr_alt_state;
8934 reserv_sets_t reservs;
8936 if (state->component_states != NULL)
8937 for (curr_alt_state = state->component_states;
8938 curr_alt_state != NULL;
8939 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8940 add_state_reservs (curr_alt_state->state);
8941 else
8943 reservs = state->reservs;
8944 VLA_PTR_ADD (state_reservs, reservs);
8948 /* The function outputs readable represenatation of all out arcs of
8949 STATE. */
8950 static void
8951 output_state_arcs (state)
8952 state_t state;
8954 arc_t arc;
8955 ainsn_t ainsn;
8956 char *insn_name;
8957 int curr_line_length;
8959 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8961 ainsn = arc->insn;
8962 if (!ainsn->first_insn_with_same_reservs)
8963 abort ();
8964 fprintf (output_description_file, " ");
8965 curr_line_length = 7;
8966 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8969 insn_name = ainsn->insn_reserv_decl->name;
8970 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8972 if (ainsn != arc->insn)
8974 fprintf (output_description_file, ",\n ");
8975 curr_line_length = strlen (insn_name) + 6;
8977 else
8978 curr_line_length += strlen (insn_name);
8980 else
8982 curr_line_length += strlen (insn_name);
8983 if (ainsn != arc->insn)
8985 curr_line_length += 2;
8986 fprintf (output_description_file, ", ");
8989 fprintf (output_description_file, insn_name);
8990 ainsn = ainsn->next_same_reservs_insn;
8992 while (ainsn != NULL);
8993 fprintf (output_description_file, " %d (%d)\n",
8994 arc->to_state->order_state_num, arc->state_alts);
8996 fprintf (output_description_file, "\n");
8999 /* The following function is used for sorting possible cpu unit
9000 reservation of a DFA state. */
9001 static int
9002 state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
9003 const void *reservs_ptr_1;
9004 const void *reservs_ptr_2;
9006 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9007 *(reserv_sets_t *) reservs_ptr_2);
9010 /* The following function is used for sorting possible cpu unit
9011 reservation of a DFA state. */
9012 static void
9013 remove_state_duplicate_reservs ()
9015 reserv_sets_t *reservs_ptr;
9016 reserv_sets_t *last_formed_reservs_ptr;
9018 last_formed_reservs_ptr = NULL;
9019 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9020 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9021 reservs_ptr++)
9022 if (last_formed_reservs_ptr == NULL)
9023 last_formed_reservs_ptr = reservs_ptr;
9024 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9026 ++last_formed_reservs_ptr;
9027 *last_formed_reservs_ptr = *reservs_ptr;
9029 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9032 /* The following function output readable representation of DFA(s)
9033 state used for fast recognition of pipeline hazards. State is
9034 described by possible (current and scehduled) cpu unit
9035 reservations. */
9036 static void
9037 output_state (state)
9038 state_t state;
9040 reserv_sets_t *reservs_ptr;
9042 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9043 fprintf (output_description_file, " State #%d", state->order_state_num);
9044 fprintf (output_description_file,
9045 state->new_cycle_p ? " (new cycle)\n" : "\n");
9046 add_state_reservs (state);
9047 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9048 sizeof (reserv_sets_t), state_reservs_cmp);
9049 remove_state_duplicate_reservs ();
9050 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9051 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9052 reservs_ptr++)
9054 fprintf (output_description_file, " ");
9055 output_reserv_sets (output_description_file, *reservs_ptr);
9056 fprintf (output_description_file, "\n");
9058 fprintf (output_description_file, "\n");
9059 output_state_arcs (state);
9060 VLA_PTR_DELETE (state_reservs);
9063 /* The following function output readable representation of
9064 DFAs used for fast recognition of pipeline hazards. */
9065 static void
9066 output_automaton_descriptions ()
9068 automaton_t automaton;
9070 for (automaton = description->first_automaton;
9071 automaton != NULL;
9072 automaton = automaton->next_automaton)
9074 fprintf (output_description_file, "\nAutomaton ");
9075 output_automaton_name (output_description_file, automaton);
9076 fprintf (output_description_file, "\n");
9077 output_automaton_units (automaton);
9078 pass_states (automaton, output_state);
9084 /* The page contains top level function for generation DFA(s) used for
9085 PHR. */
9087 /* The function outputs statistics about work of different phases of
9088 DFA generator. */
9089 static void
9090 output_statistics (f)
9091 FILE *f;
9093 automaton_t automaton;
9094 #ifndef NDEBUG
9095 int transition_comb_vect_els = 0;
9096 int transition_full_vect_els = 0;
9097 int state_alts_comb_vect_els = 0;
9098 int state_alts_full_vect_els = 0;
9099 int min_issue_delay_vect_els = 0;
9100 #endif
9102 for (automaton = description->first_automaton;
9103 automaton != NULL;
9104 automaton = automaton->next_automaton)
9106 fprintf (f, "\nAutomaton ");
9107 output_automaton_name (f, automaton);
9108 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9109 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9110 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9111 automaton->DFA_states_num, automaton->DFA_arcs_num);
9112 if (!no_minimization_flag)
9113 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9114 automaton->minimal_DFA_states_num,
9115 automaton->minimal_DFA_arcs_num);
9116 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9117 description->insns_num, automaton->insn_equiv_classes_num);
9118 #ifndef NDEBUG
9119 fprintf
9120 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9121 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9122 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9123 (comb_vect_p (automaton->trans_table)
9124 ? "use comb vect" : "use simple vect"));
9125 fprintf
9126 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9127 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9128 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9129 (comb_vect_p (automaton->state_alts_table)
9130 ? "use comb vect" : "use simple vect"));
9131 fprintf
9132 (f, "%5ld min delay table els, compression factor %d\n",
9133 (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num,
9134 automaton->min_issue_delay_table_compression_factor);
9135 transition_comb_vect_els
9136 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9137 transition_full_vect_els
9138 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9139 state_alts_comb_vect_els
9140 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9141 state_alts_full_vect_els
9142 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9143 min_issue_delay_vect_els
9144 += automaton->DFA_states_num * automaton->insn_equiv_classes_num;
9145 #endif
9147 #ifndef NDEBUG
9148 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9149 allocated_states_num, allocated_arcs_num);
9150 fprintf (f, "%5d all allocated alternative states\n",
9151 allocated_alt_states_num);
9152 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9153 transition_comb_vect_els, transition_full_vect_els);
9154 fprintf
9155 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9156 state_alts_comb_vect_els, state_alts_full_vect_els);
9157 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9158 fprintf (f, "%5d locked states num\n", locked_states_num);
9159 #endif
9162 /* The function output times of work of different phases of DFA
9163 generator. */
9164 static void
9165 output_time_statistics (f)
9166 FILE *f;
9168 fprintf (f, "\n transformation: ");
9169 print_active_time (f, transform_time);
9170 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9171 print_active_time (f, NDFA_time);
9172 if (ndfa_flag)
9174 fprintf (f, ", NDFA -> DFA: ");
9175 print_active_time (f, NDFA_to_DFA_time);
9177 fprintf (f, "\n DFA minimization: ");
9178 print_active_time (f, minimize_time);
9179 fprintf (f, ", making insn equivalence: ");
9180 print_active_time (f, equiv_time);
9181 fprintf (f, "\n all automaton generation: ");
9182 print_active_time (f, automaton_generation_time);
9183 fprintf (f, ", output: ");
9184 print_active_time (f, output_time);
9185 fprintf (f, "\n");
9188 /* The function generates DFA (deterministic finate state automaton)
9189 for fast recognition of pipeline hazards. No errors during
9190 checking must be fixed before this function call. */
9191 static void
9192 generate ()
9194 automata_num = split_argument;
9195 if (description->units_num < automata_num)
9196 automata_num = description->units_num;
9197 initiate_states ();
9198 initiate_arcs ();
9199 initiate_automata_lists ();
9200 initiate_pass_states ();
9201 initiate_excl_sets ();
9202 initiate_presence_absence_sets ();
9203 automaton_generation_time = create_ticker ();
9204 create_automata ();
9205 ticker_off (&automaton_generation_time);
9210 /* The following function creates insn attribute whose values are
9211 number alternatives in insn reservations. */
9212 static void
9213 make_insn_alts_attr ()
9215 int i, insn_num;
9216 decl_t decl;
9217 rtx condexp;
9219 condexp = rtx_alloc (COND);
9220 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9221 XEXP (condexp, 1) = make_numeric_value (0);
9222 for (i = insn_num = 0; i < description->decls_num; i++)
9224 decl = description->decls [i];
9225 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9227 XVECEXP (condexp, 0, 2 * insn_num)
9228 = DECL_INSN_RESERV (decl)->condexp;
9229 XVECEXP (condexp, 0, 2 * insn_num + 1)
9230 = make_numeric_value
9231 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9232 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9233 ->transformed_regexp)->regexps_num);
9234 insn_num++;
9237 if (description->insns_num != insn_num + 1)
9238 abort ();
9239 make_internal_attr (attr_printf (sizeof ("*")
9240 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9241 "*%s", INSN_ALTS_FUNC_NAME),
9242 condexp, 0);
9247 /* The following function creates attribute which is order number of
9248 insn in pipeline hazard description translator. */
9249 static void
9250 make_internal_dfa_insn_code_attr ()
9252 int i, insn_num;
9253 decl_t decl;
9254 rtx condexp;
9256 condexp = rtx_alloc (COND);
9257 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9258 XEXP (condexp, 1)
9259 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9260 ->insn_num + 1);
9261 for (i = insn_num = 0; i < description->decls_num; i++)
9263 decl = description->decls [i];
9264 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9266 XVECEXP (condexp, 0, 2 * insn_num)
9267 = DECL_INSN_RESERV (decl)->condexp;
9268 XVECEXP (condexp, 0, 2 * insn_num + 1)
9269 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9270 insn_num++;
9273 if (description->insns_num != insn_num + 1)
9274 abort ();
9275 make_internal_attr
9276 (attr_printf (sizeof ("*")
9277 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9278 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9279 condexp, 0);
9284 /* The following function creates attribute which order number of insn
9285 in pipeline hazard description translator. */
9286 static void
9287 make_default_insn_latency_attr ()
9289 int i, insn_num;
9290 decl_t decl;
9291 rtx condexp;
9293 condexp = rtx_alloc (COND);
9294 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9295 XEXP (condexp, 1) = make_numeric_value (0);
9296 for (i = insn_num = 0; i < description->decls_num; i++)
9298 decl = description->decls [i];
9299 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9301 XVECEXP (condexp, 0, 2 * insn_num)
9302 = DECL_INSN_RESERV (decl)->condexp;
9303 XVECEXP (condexp, 0, 2 * insn_num + 1)
9304 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9305 insn_num++;
9308 if (description->insns_num != insn_num + 1)
9309 abort ();
9310 make_internal_attr (attr_printf (sizeof ("*")
9311 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9312 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9313 condexp, 0);
9318 /* The following function creates attribute which returns 1 if given
9319 output insn has bypassing and 0 otherwise. */
9320 static void
9321 make_bypass_attr ()
9323 int i, bypass_insn;
9324 int bypass_insns_num = 0;
9325 decl_t decl;
9326 rtx result_rtx;
9328 for (i = 0; i < description->decls_num; i++)
9330 decl = description->decls [i];
9331 if (decl->mode == dm_insn_reserv
9332 && DECL_INSN_RESERV (decl)->condexp != NULL
9333 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9334 bypass_insns_num++;
9336 if (bypass_insns_num == 0)
9337 result_rtx = make_numeric_value (0);
9338 else
9340 result_rtx = rtx_alloc (COND);
9341 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9342 XEXP (result_rtx, 1) = make_numeric_value (0);
9344 for (i = bypass_insn = 0; i < description->decls_num; i++)
9346 decl = description->decls [i];
9347 if (decl->mode == dm_insn_reserv
9348 && DECL_INSN_RESERV (decl)->condexp != NULL
9349 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9351 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9352 = DECL_INSN_RESERV (decl)->condexp;
9353 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9354 = make_numeric_value (1);
9355 bypass_insn++;
9359 make_internal_attr (attr_printf (sizeof ("*")
9360 + strlen (BYPASS_P_FUNC_NAME) + 1,
9361 "*%s", BYPASS_P_FUNC_NAME),
9362 result_rtx, 0);
9367 /* This page mainly contains top level functions of pipeline hazards
9368 description translator. */
9370 /* The following macro value is suffix of name of description file of
9371 pipeline hazards description translator. */
9372 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9374 /* The function returns suffix of given file name. The returned
9375 string can not be changed. */
9376 static const char *
9377 file_name_suffix (file_name)
9378 const char *file_name;
9380 const char *last_period;
9382 for (last_period = NULL; *file_name != '\0'; file_name++)
9383 if (*file_name == '.')
9384 last_period = file_name;
9385 return (last_period == NULL ? file_name : last_period);
9388 /* The function returns base name of given file name, i.e. pointer to
9389 first char after last `/' (or `\' for WIN32) in given file name,
9390 given file name itself if the directory name is absent. The
9391 returned string can not be changed. */
9392 static const char *
9393 base_file_name (file_name)
9394 const char *file_name;
9396 int directory_name_length;
9398 directory_name_length = strlen (file_name);
9399 #ifdef WIN32
9400 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9401 && file_name[directory_name_length] != '\\')
9402 #else
9403 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9404 #endif
9405 directory_name_length--;
9406 return file_name + directory_name_length + 1;
9409 /* The following is top level function to initialize the work of
9410 pipeline hazards description translator. */
9411 void
9412 initiate_automaton_gen (argc, argv)
9413 int argc;
9414 char **argv;
9416 const char *base_name;
9417 int i;
9419 ndfa_flag = 0;
9420 split_argument = 0; /* default value */
9421 no_minimization_flag = 0;
9422 time_flag = 0;
9423 v_flag = 0;
9424 w_flag = 0;
9425 for (i = 2; i < argc; i++)
9426 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9427 no_minimization_flag = 1;
9428 else if (strcmp (argv [i], TIME_OPTION) == 0)
9429 time_flag = 1;
9430 else if (strcmp (argv [i], V_OPTION) == 0)
9431 v_flag = 1;
9432 else if (strcmp (argv [i], W_OPTION) == 0)
9433 w_flag = 1;
9434 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9435 ndfa_flag = 1;
9436 else if (strcmp (argv [i], "-split") == 0)
9438 if (i + 1 >= argc)
9439 fatal ("-split has no argument.");
9440 fatal ("option `-split' has not been implemented yet\n");
9441 /* split_argument = atoi (argument_vect [i + 1]); */
9443 VLA_PTR_CREATE (decls, 150, "decls");
9444 /* Initialize IR storage. */
9445 obstack_init (&irp);
9446 initiate_automaton_decl_table ();
9447 initiate_insn_decl_table ();
9448 initiate_decl_table ();
9449 output_file = stdout;
9450 output_description_file = NULL;
9451 base_name = base_file_name (argv[1]);
9452 obstack_grow (&irp, base_name,
9453 strlen (base_name) - strlen (file_name_suffix (base_name)));
9454 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9455 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9456 obstack_1grow (&irp, '\0');
9457 output_description_file_name = obstack_base (&irp);
9458 obstack_finish (&irp);
9461 /* The following function checks existence at least one arc marked by
9462 each insn. */
9463 static void
9464 check_automata_insn_issues ()
9466 automaton_t automaton;
9467 ainsn_t ainsn, reserv_ainsn;
9469 for (automaton = description->first_automaton;
9470 automaton != NULL;
9471 automaton = automaton->next_automaton)
9473 for (ainsn = automaton->ainsn_list;
9474 ainsn != NULL;
9475 ainsn = ainsn->next_ainsn)
9476 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9478 for (reserv_ainsn = ainsn;
9479 reserv_ainsn != NULL;
9480 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9481 if (automaton->corresponding_automaton_decl != NULL)
9483 if (!w_flag)
9484 error ("Automaton `%s': Insn `%s' will never be issued",
9485 automaton->corresponding_automaton_decl->name,
9486 reserv_ainsn->insn_reserv_decl->name);
9487 else
9488 warning
9489 ("Automaton `%s': Insn `%s' will never be issued",
9490 automaton->corresponding_automaton_decl->name,
9491 reserv_ainsn->insn_reserv_decl->name);
9493 else
9495 if (!w_flag)
9496 error ("Insn `%s' will never be issued",
9497 reserv_ainsn->insn_reserv_decl->name);
9498 else
9499 warning ("Insn `%s' will never be issued",
9500 reserv_ainsn->insn_reserv_decl->name);
9506 /* The following vla is used for storing pointers to all achieved
9507 states. */
9508 static vla_ptr_t automaton_states;
9510 /* This function is called by function pass_states to add an achieved
9511 STATE. */
9512 static void
9513 add_automaton_state (state)
9514 state_t state;
9516 VLA_PTR_ADD (automaton_states, state);
9519 /* The following function forms list of important automata (whose
9520 states may be changed after the insn issue) for each insn. */
9521 static void
9522 form_important_insn_automata_lists ()
9524 automaton_t automaton;
9525 state_t *state_ptr;
9526 decl_t decl;
9527 ainsn_t ainsn;
9528 arc_t arc;
9529 int i;
9531 VLA_PTR_CREATE (automaton_states, 1500,
9532 "automaton states for forming important insn automata sets");
9533 /* Mark important ainsns. */
9534 for (automaton = description->first_automaton;
9535 automaton != NULL;
9536 automaton = automaton->next_automaton)
9538 VLA_PTR_NULLIFY (automaton_states);
9539 pass_states (automaton, add_automaton_state);
9540 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9541 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9542 state_ptr++)
9544 for (arc = first_out_arc (*state_ptr);
9545 arc != NULL;
9546 arc = next_out_arc (arc))
9547 if (arc->to_state != *state_ptr)
9549 if (!arc->insn->first_insn_with_same_reservs)
9550 abort ();
9551 for (ainsn = arc->insn;
9552 ainsn != NULL;
9553 ainsn = ainsn->next_same_reservs_insn)
9554 ainsn->important_p = TRUE;
9558 VLA_PTR_DELETE (automaton_states);
9559 /* Create automata sets for the insns. */
9560 for (i = 0; i < description->decls_num; i++)
9562 decl = description->decls [i];
9563 if (decl->mode == dm_insn_reserv)
9565 automata_list_start ();
9566 for (automaton = description->first_automaton;
9567 automaton != NULL;
9568 automaton = automaton->next_automaton)
9569 for (ainsn = automaton->ainsn_list;
9570 ainsn != NULL;
9571 ainsn = ainsn->next_ainsn)
9572 if (ainsn->important_p
9573 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9575 automata_list_add (automaton);
9576 break;
9578 DECL_INSN_RESERV (decl)->important_automata_list
9579 = automata_list_finish ();
9585 /* The following is top level function to generate automat(a,on) for
9586 fast recognition of pipeline hazards. */
9587 void
9588 expand_automata ()
9590 int i;
9592 description = create_node (sizeof (struct description)
9593 /* One entry for cycle advancing insn. */
9594 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9595 description->decls_num = VLA_PTR_LENGTH (decls);
9596 description->query_units_num = 0;
9597 for (i = 0; i < description->decls_num; i++)
9599 description->decls [i] = VLA_PTR (decls, i);
9600 if (description->decls [i]->mode == dm_unit
9601 && DECL_UNIT (description->decls [i])->query_p)
9602 DECL_UNIT (description->decls [i])->query_num
9603 = description->query_units_num++;
9605 all_time = create_ticker ();
9606 check_time = create_ticker ();
9607 fprintf (stderr, "Check description...");
9608 fflush (stderr);
9609 check_all_description ();
9610 fprintf (stderr, "done\n");
9611 ticker_off (&check_time);
9612 generation_time = create_ticker ();
9613 if (!have_error)
9615 transform_insn_regexps ();
9616 check_unit_distributions_to_automata ();
9618 if (!have_error)
9620 generate ();
9621 check_automata_insn_issues ();
9623 if (!have_error)
9625 form_important_insn_automata_lists ();
9626 fprintf (stderr, "Generation of attributes...");
9627 fflush (stderr);
9628 make_internal_dfa_insn_code_attr ();
9629 make_insn_alts_attr ();
9630 make_default_insn_latency_attr ();
9631 make_bypass_attr ();
9632 fprintf (stderr, "done\n");
9634 ticker_off (&generation_time);
9635 ticker_off (&all_time);
9636 fprintf (stderr, "All other genattrtab stuff...");
9637 fflush (stderr);
9640 /* The following is top level function to output PHR and to finish
9641 work with pipeline description translator. */
9642 void
9643 write_automata ()
9645 fprintf (stderr, "done\n");
9646 if (have_error)
9647 fatal ("Errors in DFA description");
9648 ticker_on (&all_time);
9649 output_time = create_ticker ();
9650 fprintf (stderr, "Forming and outputing automata tables...");
9651 fflush (stderr);
9652 output_dfa_max_issue_rate ();
9653 output_tables ();
9654 fprintf (stderr, "done\n");
9655 fprintf (stderr, "Output functions to work with automata...");
9656 fflush (stderr);
9657 output_chip_definitions ();
9658 output_max_insn_queue_index_def ();
9659 output_internal_min_issue_delay_func ();
9660 output_internal_trans_func ();
9661 /* Cache of insn dfa codes: */
9662 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9663 fprintf (output_file, "\nstatic int %s;\n\n",
9664 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9665 output_dfa_insn_code_func ();
9666 output_trans_func ();
9667 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9668 output_internal_state_alts_func ();
9669 output_state_alts_func ();
9670 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9671 AUTOMATON_STATE_ALTS_MACRO_NAME);
9672 output_min_issue_delay_func ();
9673 output_internal_dead_lock_func ();
9674 output_dead_lock_func ();
9675 output_size_func ();
9676 output_internal_reset_func ();
9677 output_reset_func ();
9678 output_min_insn_conflict_delay_func ();
9679 output_internal_insn_latency_func ();
9680 output_insn_latency_func ();
9681 output_print_reservation_func ();
9682 if (no_minimization_flag)
9684 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9685 output_get_cpu_unit_code_func ();
9686 output_cpu_unit_reservation_p ();
9687 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9688 CPU_UNITS_QUERY_MACRO_NAME);
9690 output_dfa_start_func ();
9691 output_dfa_finish_func ();
9692 fprintf (stderr, "done\n");
9693 if (v_flag)
9695 output_description_file = fopen (output_description_file_name, "w");
9696 if (output_description_file == NULL)
9698 perror (output_description_file_name);
9699 exit (FATAL_EXIT_CODE);
9701 fprintf (stderr, "Output automata description...");
9702 fflush (stderr);
9703 output_description ();
9704 output_automaton_descriptions ();
9705 fprintf (stderr, "done\n");
9706 output_statistics (output_description_file);
9708 output_statistics (stderr);
9709 ticker_off (&output_time);
9710 output_time_statistics (stderr);
9711 finish_states ();
9712 finish_arcs ();
9713 finish_automata_lists ();
9714 if (time_flag)
9716 fprintf (stderr, "Summary:\n");
9717 fprintf (stderr, " check time ");
9718 print_active_time (stderr, check_time);
9719 fprintf (stderr, ", generation time ");
9720 print_active_time (stderr, generation_time);
9721 fprintf (stderr, ", all time ");
9722 print_active_time (stderr, all_time);
9723 fprintf (stderr, "\n");
9725 /* Finish all work. */
9726 if (output_description_file != NULL)
9728 fflush (output_description_file);
9729 if (ferror (stdout) != 0)
9730 fatal ("Error in writing DFA description file %s",
9731 output_description_file_name);
9732 fclose (output_description_file);
9734 finish_automaton_decl_table ();
9735 finish_insn_decl_table ();
9736 finish_decl_table ();
9737 obstack_free (&irp, NULL);
9738 if (have_error && output_description_file != NULL)
9739 remove (output_description_file_name);