Add x prefix to v850e case for handling --with-cpu=v850e.
[official-gcc.git] / gcc / genautomata.c
blobbbb2b9698762d606b3af1d6c3c34316c06dcdc2b
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++)
4987 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
4989 seq = REGEXP_ALLOF (regexp)->regexps [i];
4990 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4991 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4993 else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit)
4995 max_seq_length = 0;
4996 break;
4999 if (max_seq_length != 0)
5001 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5002 abort ();
5003 result = create_node (sizeof (struct regexp)
5004 + sizeof (regexp_t) * (max_seq_length - 1));
5005 result->mode = rm_sequence;
5006 result->pos = regexp->pos;
5007 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5008 for (i = 0; i < max_seq_length; i++)
5010 allof_length = 0;
5011 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5012 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5013 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5014 ->regexps [j])->regexps_num)))
5016 allof_op
5017 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5018 ->regexps [i]);
5019 allof_length++;
5021 else if (i == 0
5022 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5023 == rm_unit))
5025 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5026 allof_length++;
5028 if (allof_length == 1)
5029 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5030 else
5032 allof = create_node (sizeof (struct regexp)
5033 + sizeof (regexp_t)
5034 * (allof_length - 1));
5035 allof->mode = rm_allof;
5036 allof->pos = regexp->pos;
5037 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5038 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5039 allof_length = 0;
5040 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5041 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5042 && (i <
5043 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5044 ->regexps [j])->regexps_num)))
5046 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5047 ->regexps [j])
5048 ->regexps [i]);
5049 REGEXP_ALLOF (allof)->regexps [allof_length]
5050 = allof_op;
5051 allof_length++;
5053 else if (i == 0
5054 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5055 == rm_unit))
5057 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5058 REGEXP_ALLOF (allof)->regexps [allof_length]
5059 = allof_op;
5060 allof_length++;
5064 regexp_transformed_p = 1;
5065 regexp = result;
5068 return regexp;
5071 /* The function traverses IR of reservation and applies transformations
5072 implemented by FUNC. */
5073 static regexp_t
5074 regexp_transform_func (regexp, func)
5075 regexp_t regexp;
5076 regexp_t (*func) PARAMS ((regexp_t regexp));
5078 int i;
5080 if (regexp->mode == rm_sequence)
5081 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5082 REGEXP_SEQUENCE (regexp)->regexps [i]
5083 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5084 else if (regexp->mode == rm_allof)
5085 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5086 REGEXP_ALLOF (regexp)->regexps [i]
5087 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5088 else if (regexp->mode == rm_oneof)
5089 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5090 REGEXP_ONEOF (regexp)->regexps [i]
5091 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5092 else if (regexp->mode == rm_repeat)
5093 REGEXP_REPEAT (regexp)->regexp
5094 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5095 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5096 abort ();
5097 return (*func) (regexp);
5100 /* The function applies all transformations for IR representation of
5101 reservation REGEXP. */
5102 static regexp_t
5103 transform_regexp (regexp)
5104 regexp_t regexp;
5106 regexp = regexp_transform_func (regexp, transform_1);
5109 regexp_transformed_p = 0;
5110 regexp = regexp_transform_func (regexp, transform_2);
5111 regexp = regexp_transform_func (regexp, transform_3);
5113 while (regexp_transformed_p);
5114 return regexp;
5117 /* The function applys all transformations for reservations of all
5118 insn declarations. */
5119 static void
5120 transform_insn_regexps ()
5122 decl_t decl;
5123 int i;
5125 transform_time = create_ticker ();
5126 add_advance_cycle_insn_decl ();
5127 fprintf (stderr, "Reservation transformation...");
5128 fflush (stderr);
5129 for (i = 0; i < description->decls_num; i++)
5131 decl = description->decls [i];
5132 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5133 DECL_INSN_RESERV (decl)->transformed_regexp
5134 = transform_regexp (copy_insn_regexp
5135 (DECL_INSN_RESERV (decl)->regexp));
5137 fprintf (stderr, "done\n");
5138 ticker_off (&transform_time);
5139 fflush (stderr);
5144 /* The following variable is an array indexed by cycle. Each element
5145 contains cyclic list of units which should be in the same cycle. */
5146 static unit_decl_t *the_same_automaton_lists;
5148 /* The function processes all alternative reservations on CYCLE in
5149 given REGEXP to check the UNIT is not reserved on the all
5150 alternatives. If it is true, the unit should be in the same
5151 automaton with other analogous units reserved on CYCLE in given
5152 REGEXP. */
5153 static void
5154 process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
5155 regexp_t unit;
5156 regexp_t regexp;
5157 int cycle;
5159 int i, k;
5160 regexp_t seq, allof;
5161 unit_decl_t unit_decl, last;
5163 if (regexp == NULL || regexp->mode != rm_oneof)
5164 abort ();
5165 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5166 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5168 seq = REGEXP_ONEOF (regexp)->regexps [i];
5169 if (seq->mode == rm_sequence)
5171 if (cycle >= REGEXP_SEQUENCE (seq)->regexps_num)
5172 break;
5173 allof = REGEXP_SEQUENCE (seq)->regexps [cycle];
5174 if (allof->mode == rm_allof)
5176 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5177 if (REGEXP_ALLOF (allof)->regexps [k]->mode == rm_unit
5178 && (REGEXP_UNIT (REGEXP_ALLOF (allof)->regexps [k])
5179 ->unit_decl == unit_decl))
5180 break;
5181 if (k >= REGEXP_ALLOF (allof)->regexps_num)
5182 break;
5184 else if (allof->mode == rm_unit
5185 && REGEXP_UNIT (allof)->unit_decl != unit_decl)
5186 break;
5188 else if (cycle != 0)
5189 break;
5190 else if (seq->mode == rm_allof)
5192 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5193 if (REGEXP_ALLOF (seq)->regexps [k]->mode == rm_unit
5194 && (REGEXP_UNIT (REGEXP_ALLOF (seq)->regexps [k])->unit_decl
5195 == unit_decl))
5196 break;
5197 if (k >= REGEXP_ALLOF (seq)->regexps_num)
5198 break;
5200 else if (seq->mode == rm_unit
5201 && REGEXP_UNIT (seq)->unit_decl != unit_decl)
5202 break;
5204 if (i >= 0)
5206 if (the_same_automaton_lists [cycle] == NULL)
5207 the_same_automaton_lists [cycle] = unit_decl;
5208 else
5210 for (last = the_same_automaton_lists [cycle];;)
5212 if (last == unit_decl)
5213 return;
5214 if (last->the_same_automaton_unit
5215 == the_same_automaton_lists [cycle])
5216 break;
5217 last = last->the_same_automaton_unit;
5219 last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
5220 unit_decl->the_same_automaton_unit
5221 = the_same_automaton_lists [cycle];
5226 /* The function processes given REGEXP to find units which should be
5227 in the same automaton. */
5228 static void
5229 form_the_same_automaton_unit_lists_from_regexp (regexp)
5230 regexp_t regexp;
5232 int i, j, k;
5233 regexp_t seq, allof, unit;
5235 if (regexp == NULL || regexp->mode != rm_oneof)
5236 return;
5237 for (i = 0; i < description->max_insn_reserv_cycles; i++)
5238 the_same_automaton_lists [i] = NULL;
5239 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5241 seq = REGEXP_ONEOF (regexp)->regexps [i];
5242 if (seq->mode == rm_sequence)
5243 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5245 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5246 if (allof->mode == rm_allof)
5247 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5249 unit = REGEXP_ALLOF (allof)->regexps [k];
5250 if (unit->mode == rm_unit)
5251 process_unit_to_form_the_same_automaton_unit_lists
5252 (unit, regexp, j);
5253 else if (unit->mode != rm_nothing)
5254 abort ();
5256 else if (allof->mode == rm_unit)
5257 process_unit_to_form_the_same_automaton_unit_lists
5258 (allof, regexp, j);
5259 else if (allof->mode != rm_nothing)
5260 abort ();
5262 else if (seq->mode == rm_allof)
5263 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5265 unit = REGEXP_ALLOF (seq)->regexps [k];
5266 if (unit->mode == rm_unit)
5267 process_unit_to_form_the_same_automaton_unit_lists
5268 (unit, regexp, 0);
5269 else if (unit->mode != rm_nothing)
5270 abort ();
5272 else if (seq->mode == rm_unit)
5273 process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
5274 else if (seq->mode != rm_nothing)
5275 abort ();
5279 /* The function initializes data to search for units which should be
5280 in the same automaton and call function
5281 `form_the_same_automaton_unit_lists_from_regexp' for each insn
5282 reservation regexp. */
5283 static void
5284 form_the_same_automaton_unit_lists ()
5286 decl_t decl;
5287 int i;
5289 the_same_automaton_lists
5290 = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
5291 * sizeof (unit_decl_t));
5292 for (i = 0; i < description->decls_num; i++)
5294 decl = description->decls [i];
5295 if (decl->mode == dm_unit)
5297 DECL_UNIT (decl)->the_same_automaton_message_reported_p = FALSE;
5298 DECL_UNIT (decl)->the_same_automaton_unit = DECL_UNIT (decl);
5301 for (i = 0; i < description->decls_num; i++)
5303 decl = description->decls [i];
5304 if (decl->mode == dm_insn_reserv)
5305 form_the_same_automaton_unit_lists_from_regexp
5306 (DECL_INSN_RESERV (decl)->transformed_regexp);
5308 free (the_same_automaton_lists);
5311 /* The function finds units which should be in the same automaton and,
5312 if they are not, reports about it. */
5313 static void
5314 check_unit_distributions_to_automata ()
5316 decl_t decl;
5317 unit_decl_t start_unit_decl, unit_decl;
5318 int i;
5320 form_the_same_automaton_unit_lists ();
5321 for (i = 0; i < description->decls_num; i++)
5323 decl = description->decls [i];
5324 if (decl->mode == dm_unit)
5326 start_unit_decl = DECL_UNIT (decl);
5327 if (!start_unit_decl->the_same_automaton_message_reported_p)
5328 for (unit_decl = start_unit_decl->the_same_automaton_unit;
5329 unit_decl != start_unit_decl;
5330 unit_decl = unit_decl->the_same_automaton_unit)
5331 if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
5333 error ("Units `%s' and `%s' should be in the same automaton",
5334 start_unit_decl->name, unit_decl->name);
5335 unit_decl->the_same_automaton_message_reported_p = TRUE;
5343 /* The page contains code for building alt_states (see comments for
5344 IR) describing all possible insns reservations of an automaton. */
5346 /* Current state being formed for which the current alt_state
5347 refers. */
5348 static state_t state_being_formed;
5350 /* Current alt_state being formed. */
5351 static alt_state_t alt_state_being_formed;
5353 /* This recursive function processes `,' and units in reservation
5354 REGEXP for forming alt_states of AUTOMATON. It is believed that
5355 CURR_CYCLE is start cycle of all reservation REGEXP. */
5356 static int
5357 process_seq_for_forming_states (regexp, automaton, curr_cycle)
5358 regexp_t regexp;
5359 automaton_t automaton;
5360 int curr_cycle;
5362 int i;
5364 if (regexp == NULL)
5365 return curr_cycle;
5366 else if (regexp->mode == rm_unit)
5368 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5369 == automaton->automaton_order_num)
5370 set_state_reserv (state_being_formed, curr_cycle,
5371 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5372 return curr_cycle;
5374 else if (regexp->mode == rm_sequence)
5376 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5377 curr_cycle
5378 = process_seq_for_forming_states
5379 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5380 return curr_cycle;
5382 else if (regexp->mode == rm_allof)
5384 int finish_cycle = 0;
5385 int cycle;
5387 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5389 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5390 ->regexps [i],
5391 automaton, curr_cycle);
5392 if (finish_cycle < cycle)
5393 finish_cycle = cycle;
5395 return finish_cycle;
5397 else
5399 if (regexp->mode != rm_nothing)
5400 abort ();
5401 return curr_cycle;
5405 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5406 inserts alt_state into the table. */
5407 static void
5408 finish_forming_alt_state (alt_state, automaton)
5409 alt_state_t alt_state;
5410 automaton_t automaton ATTRIBUTE_UNUSED;
5412 state_t state_in_table;
5413 state_t corresponding_state;
5415 corresponding_state = alt_state->state;
5416 state_in_table = insert_state (corresponding_state);
5417 if (state_in_table != corresponding_state)
5419 free_state (corresponding_state);
5420 alt_state->state = state_in_table;
5424 /* The following variable value is current automaton insn for whose
5425 reservation the alt states are created. */
5426 static ainsn_t curr_ainsn;
5428 /* This recursive function processes `|' in reservation REGEXP for
5429 forming alt_states of AUTOMATON. List of the alt states should
5430 have the same order as in the description. */
5431 static void
5432 process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5433 regexp_t regexp;
5434 automaton_t automaton;
5435 int inside_oneof_p;
5437 int i;
5439 if (regexp->mode != rm_oneof)
5441 alt_state_being_formed = get_free_alt_state ();
5442 state_being_formed = get_free_state (1, automaton);
5443 alt_state_being_formed->state = state_being_formed;
5444 /* We inserts in reverse order but we process alternatives also
5445 in reverse order. So we have the same order of alternative
5446 as in the description. */
5447 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5448 curr_ainsn->alt_states = alt_state_being_formed;
5449 (void) process_seq_for_forming_states (regexp, automaton, 0);
5450 finish_forming_alt_state (alt_state_being_formed, automaton);
5452 else
5454 if (inside_oneof_p)
5455 abort ();
5456 /* We processes it in reverse order to get list with the same
5457 order as in the description. See also the previous
5458 commentary. */
5459 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5460 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5461 automaton, 1);
5465 /* Create nodes alt_state for all AUTOMATON insns. */
5466 static void
5467 create_alt_states (automaton)
5468 automaton_t automaton;
5470 struct insn_reserv_decl *reserv_decl;
5472 for (curr_ainsn = automaton->ainsn_list;
5473 curr_ainsn != NULL;
5474 curr_ainsn = curr_ainsn->next_ainsn)
5476 reserv_decl = curr_ainsn->insn_reserv_decl;
5477 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5479 curr_ainsn->alt_states = NULL;
5480 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5481 automaton, 0);
5482 curr_ainsn->sorted_alt_states
5483 = uniq_sort_alt_states (curr_ainsn->alt_states);
5490 /* The page contains major code for building DFA(s) for fast pipeline
5491 hazards recognition. */
5493 /* The function forms list of ainsns of AUTOMATON with the same
5494 reservation. */
5495 static void
5496 form_ainsn_with_same_reservs (automaton)
5497 automaton_t automaton;
5499 ainsn_t curr_ainsn;
5500 size_t i;
5501 vla_ptr_t first_insns;
5502 vla_ptr_t last_insns;
5504 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5505 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5506 for (curr_ainsn = automaton->ainsn_list;
5507 curr_ainsn != NULL;
5508 curr_ainsn = curr_ainsn->next_ainsn)
5509 if (curr_ainsn->insn_reserv_decl
5510 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5512 curr_ainsn->next_same_reservs_insn = NULL;
5513 curr_ainsn->first_insn_with_same_reservs = 1;
5515 else
5517 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5518 if (alt_states_eq
5519 (curr_ainsn->sorted_alt_states,
5520 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5521 break;
5522 curr_ainsn->next_same_reservs_insn = NULL;
5523 if (i < VLA_PTR_LENGTH (first_insns))
5525 curr_ainsn->first_insn_with_same_reservs = 0;
5526 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5527 = curr_ainsn;
5528 VLA_PTR (last_insns, i) = curr_ainsn;
5530 else
5532 VLA_PTR_ADD (first_insns, curr_ainsn);
5533 VLA_PTR_ADD (last_insns, curr_ainsn);
5534 curr_ainsn->first_insn_with_same_reservs = 1;
5537 VLA_PTR_DELETE (first_insns);
5538 VLA_PTR_DELETE (last_insns);
5541 /* The following function creates all states of nondeterministic (if
5542 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5543 static void
5544 make_automaton (automaton)
5545 automaton_t automaton;
5547 ainsn_t ainsn;
5548 struct insn_reserv_decl *insn_reserv_decl;
5549 alt_state_t alt_state;
5550 state_t state;
5551 state_t start_state;
5552 state_t state2;
5553 ainsn_t advance_cycle_ainsn;
5554 arc_t added_arc;
5555 vla_ptr_t state_stack;
5557 VLA_PTR_CREATE (state_stack, 150, "state stack");
5558 /* Create the start state (empty state). */
5559 start_state = insert_state (get_free_state (1, automaton));
5560 automaton->start_state = start_state;
5561 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5562 VLA_PTR_ADD (state_stack, start_state);
5563 while (VLA_PTR_LENGTH (state_stack) != 0)
5565 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5566 VLA_PTR_SHORTEN (state_stack, 1);
5567 advance_cycle_ainsn = NULL;
5568 for (ainsn = automaton->ainsn_list;
5569 ainsn != NULL;
5570 ainsn = ainsn->next_ainsn)
5571 if (ainsn->first_insn_with_same_reservs)
5573 insn_reserv_decl = ainsn->insn_reserv_decl;
5574 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5576 /* We process alt_states in the same order as they are
5577 present in the description. */
5578 added_arc = NULL;
5579 for (alt_state = ainsn->alt_states;
5580 alt_state != NULL;
5581 alt_state = alt_state->next_alt_state)
5583 state2 = alt_state->state;
5584 if (!intersected_state_reservs_p (state, state2))
5586 state2 = states_union (state, state2);
5587 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5589 state2->it_was_placed_in_stack_for_NDFA_forming
5590 = 1;
5591 VLA_PTR_ADD (state_stack, state2);
5593 added_arc = add_arc (state, state2, ainsn, 1);
5594 if (!ndfa_flag)
5595 break;
5598 if (!ndfa_flag && added_arc != NULL)
5600 added_arc->state_alts = 0;
5601 for (alt_state = ainsn->alt_states;
5602 alt_state != NULL;
5603 alt_state = alt_state->next_alt_state)
5605 state2 = alt_state->state;
5606 if (!intersected_state_reservs_p (state, state2))
5607 added_arc->state_alts++;
5611 else
5612 advance_cycle_ainsn = ainsn;
5614 /* Add transition to advance cycle. */
5615 state2 = state_shift (state);
5616 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5618 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5619 VLA_PTR_ADD (state_stack, state2);
5621 if (advance_cycle_ainsn == NULL)
5622 abort ();
5623 add_arc (state, state2, advance_cycle_ainsn, 1);
5625 VLA_PTR_DELETE (state_stack);
5628 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5629 static void
5630 form_arcs_marked_by_insn (state)
5631 state_t state;
5633 decl_t decl;
5634 arc_t arc;
5635 int i;
5637 for (i = 0; i < description->decls_num; i++)
5639 decl = description->decls [i];
5640 if (decl->mode == dm_insn_reserv)
5641 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5643 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5645 if (arc->insn == NULL)
5646 abort ();
5647 arc->next_arc_marked_by_insn
5648 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5649 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5653 /* The function creates composed state (see comments for IR) from
5654 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5655 same insn. If the composed state is not in STATE_STACK yet, it is
5656 popped to STATE_STACK. */
5657 static void
5658 create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5659 state_t original_state;
5660 arc_t arcs_marked_by_insn;
5661 vla_ptr_t *state_stack;
5663 state_t state;
5664 alt_state_t curr_alt_state;
5665 alt_state_t new_alt_state;
5666 arc_t curr_arc;
5667 arc_t next_arc;
5668 state_t state_in_table;
5669 state_t temp_state;
5670 alt_state_t canonical_alt_states_list;
5671 int alts_number;
5673 if (arcs_marked_by_insn == NULL)
5674 return;
5675 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5676 state = arcs_marked_by_insn->to_state;
5677 else
5679 if (!ndfa_flag)
5680 abort ();
5681 /* Create composed state. */
5682 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5683 curr_alt_state = NULL;
5684 for (curr_arc = arcs_marked_by_insn;
5685 curr_arc != NULL;
5686 curr_arc = curr_arc->next_arc_marked_by_insn)
5688 new_alt_state = get_free_alt_state ();
5689 new_alt_state->next_alt_state = curr_alt_state;
5690 new_alt_state->state = curr_arc->to_state;
5691 if (curr_arc->to_state->component_states != NULL)
5692 abort ();
5693 curr_alt_state = new_alt_state;
5695 /* There are not identical sets in the alt state list. */
5696 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5697 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5699 temp_state = state;
5700 state = canonical_alt_states_list->state;
5701 free_state (temp_state);
5703 else
5705 state->component_states = canonical_alt_states_list;
5706 state_in_table = insert_state (state);
5707 if (state_in_table != state)
5709 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5710 abort ();
5711 free_state (state);
5712 state = state_in_table;
5714 else
5716 if (state->it_was_placed_in_stack_for_DFA_forming)
5717 abort ();
5718 for (curr_alt_state = state->component_states;
5719 curr_alt_state != NULL;
5720 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5721 for (curr_arc = first_out_arc (curr_alt_state->state);
5722 curr_arc != NULL;
5723 curr_arc = next_out_arc (curr_arc))
5724 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5726 arcs_marked_by_insn->to_state = state;
5727 for (alts_number = 0,
5728 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5729 curr_arc != NULL;
5730 curr_arc = next_arc)
5732 next_arc = curr_arc->next_arc_marked_by_insn;
5733 remove_arc (original_state, curr_arc);
5734 alts_number++;
5736 arcs_marked_by_insn->state_alts = alts_number;
5739 if (!state->it_was_placed_in_stack_for_DFA_forming)
5741 state->it_was_placed_in_stack_for_DFA_forming = 1;
5742 VLA_PTR_ADD (*state_stack, state);
5746 /* The function transformes nondeterminstic AUTOMATON into
5747 deterministic. */
5748 static void
5749 NDFA_to_DFA (automaton)
5750 automaton_t automaton;
5752 state_t start_state;
5753 state_t state;
5754 decl_t decl;
5755 vla_ptr_t state_stack;
5756 int i;
5758 VLA_PTR_CREATE (state_stack, 150, "state stack");
5759 /* Create the start state (empty state). */
5760 start_state = automaton->start_state;
5761 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5762 VLA_PTR_ADD (state_stack, start_state);
5763 while (VLA_PTR_LENGTH (state_stack) != 0)
5765 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5766 VLA_PTR_SHORTEN (state_stack, 1);
5767 form_arcs_marked_by_insn (state);
5768 for (i = 0; i < description->decls_num; i++)
5770 decl = description->decls [i];
5771 if (decl->mode == dm_insn_reserv)
5772 create_composed_state
5773 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5774 &state_stack);
5777 VLA_PTR_DELETE (state_stack);
5780 /* The following variable value is current number (1, 2, ...) of passing
5781 graph of states. */
5782 static int curr_state_graph_pass_num;
5784 /* This recursive function passes all states achieved from START_STATE
5785 and applies APPLIED_FUNC to them. */
5786 static void
5787 pass_state_graph (start_state, applied_func)
5788 state_t start_state;
5789 void (*applied_func) PARAMS ((state_t state));
5791 arc_t arc;
5793 if (start_state->pass_num == curr_state_graph_pass_num)
5794 return;
5795 start_state->pass_num = curr_state_graph_pass_num;
5796 (*applied_func) (start_state);
5797 for (arc = first_out_arc (start_state);
5798 arc != NULL;
5799 arc = next_out_arc (arc))
5800 pass_state_graph (arc->to_state, applied_func);
5803 /* This recursive function passes all states of AUTOMATON and applies
5804 APPLIED_FUNC to them. */
5805 static void
5806 pass_states (automaton, applied_func)
5807 automaton_t automaton;
5808 void (*applied_func) PARAMS ((state_t state));
5810 curr_state_graph_pass_num++;
5811 pass_state_graph (automaton->start_state, applied_func);
5814 /* The function initializes code for passing of all states. */
5815 static void
5816 initiate_pass_states ()
5818 curr_state_graph_pass_num = 0;
5821 /* The following vla is used for storing pointers to all achieved
5822 states. */
5823 static vla_ptr_t all_achieved_states;
5825 /* This function is called by function pass_states to add an achieved
5826 STATE. */
5827 static void
5828 add_achieved_state (state)
5829 state_t state;
5831 VLA_PTR_ADD (all_achieved_states, state);
5834 /* The function sets up equivalence numbers of insns which mark all
5835 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5836 nonzero value) or by equiv_class_num_2 of the destination state.
5837 The function returns number of out arcs of STATE. */
5838 static int
5839 set_out_arc_insns_equiv_num (state, odd_iteration_flag)
5840 state_t state;
5841 int odd_iteration_flag;
5843 int state_out_arcs_num;
5844 arc_t arc;
5846 state_out_arcs_num = 0;
5847 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5849 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
5850 || arc->insn->insn_reserv_decl->state_alts != 0)
5851 abort ();
5852 state_out_arcs_num++;
5853 arc->insn->insn_reserv_decl->equiv_class_num
5854 = (odd_iteration_flag
5855 ? arc->to_state->equiv_class_num_1
5856 : arc->to_state->equiv_class_num_2);
5857 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
5858 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
5859 || arc->insn->insn_reserv_decl->state_alts <= 0)
5860 abort ();
5862 return state_out_arcs_num;
5865 /* The function clears equivalence numbers and alt_states in all insns
5866 which mark all out arcs of STATE. */
5867 static void
5868 clear_arc_insns_equiv_num (state)
5869 state_t state;
5871 arc_t arc;
5873 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5875 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5876 arc->insn->insn_reserv_decl->state_alts = 0;
5880 /* The function copies pointers to equivalent states from vla FROM
5881 into vla TO. */
5882 static void
5883 copy_equiv_class (to, from)
5884 vla_ptr_t *to;
5885 const vla_ptr_t *from;
5887 state_t *class_ptr;
5889 VLA_PTR_NULLIFY (*to);
5890 for (class_ptr = VLA_PTR_BEGIN (*from);
5891 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
5892 class_ptr++)
5893 VLA_PTR_ADD (*to, *class_ptr);
5896 /* The function returns nonzero value if STATE is not equivalent to
5897 another state from the same current partition on equivalence
5898 classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of
5899 output arcs. Iteration of making equivalence partition is defined
5900 by ODD_ITERATION_FLAG. */
5901 static int
5902 state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag)
5903 state_t state;
5904 int original_state_out_arcs_num;
5905 int odd_iteration_flag;
5907 arc_t arc;
5908 int state_out_arcs_num;
5910 state_out_arcs_num = 0;
5911 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5913 state_out_arcs_num++;
5914 if ((odd_iteration_flag
5915 ? arc->to_state->equiv_class_num_1
5916 : arc->to_state->equiv_class_num_2)
5917 != arc->insn->insn_reserv_decl->equiv_class_num
5918 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
5919 return 1;
5921 return state_out_arcs_num != original_state_out_arcs_num;
5924 /* The function makes initial partition of STATES on equivalent
5925 classes. */
5926 static state_t
5927 init_equiv_class (states, states_num)
5928 state_t *states;
5929 int states_num;
5931 state_t *state_ptr;
5932 state_t result_equiv_class;
5934 result_equiv_class = NULL;
5935 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
5937 (*state_ptr)->equiv_class_num_1 = 1;
5938 (*state_ptr)->next_equiv_class_state = result_equiv_class;
5939 result_equiv_class = *state_ptr;
5941 return result_equiv_class;
5944 /* The function processes equivalence class given by its pointer
5945 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
5946 are not equvalent states, the function partitions the class
5947 removing nonequivalent states and placing them in
5948 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5949 assigns it to the state equivalence number. If the class has been
5950 partitioned, the function returns nonzero value. */
5951 static int
5952 partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5953 next_iteration_classes, new_equiv_class_num_ptr)
5954 state_t *equiv_class_ptr;
5955 int odd_iteration_flag;
5956 vla_ptr_t *next_iteration_classes;
5957 int *new_equiv_class_num_ptr;
5959 state_t new_equiv_class;
5960 int partition_p;
5961 state_t first_state;
5962 state_t curr_state;
5963 state_t prev_state;
5964 state_t next_state;
5965 int out_arcs_num;
5967 partition_p = 0;
5968 if (*equiv_class_ptr == NULL)
5969 abort ();
5970 for (first_state = *equiv_class_ptr;
5971 first_state != NULL;
5972 first_state = new_equiv_class)
5974 new_equiv_class = NULL;
5975 if (first_state->next_equiv_class_state != NULL)
5977 /* There are more one states in the class equivalence. */
5978 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
5979 odd_iteration_flag);
5980 for (prev_state = first_state,
5981 curr_state = first_state->next_equiv_class_state;
5982 curr_state != NULL;
5983 curr_state = next_state)
5985 next_state = curr_state->next_equiv_class_state;
5986 if (state_is_differed (curr_state, out_arcs_num,
5987 odd_iteration_flag))
5989 /* Remove curr state from the class equivalence. */
5990 prev_state->next_equiv_class_state = next_state;
5991 /* Add curr state to the new class equivalence. */
5992 curr_state->next_equiv_class_state = new_equiv_class;
5993 if (new_equiv_class == NULL)
5994 (*new_equiv_class_num_ptr)++;
5995 if (odd_iteration_flag)
5996 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5997 else
5998 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5999 new_equiv_class = curr_state;
6000 partition_p = 1;
6002 else
6003 prev_state = curr_state;
6005 clear_arc_insns_equiv_num (first_state);
6007 if (new_equiv_class != NULL)
6008 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
6010 return partition_p;
6013 /* The function finds equivalent states of AUTOMATON. */
6014 static void
6015 evaluate_equiv_classes (automaton, equiv_classes)
6016 automaton_t automaton;
6017 vla_ptr_t *equiv_classes;
6019 state_t new_equiv_class;
6020 int new_equiv_class_num;
6021 int odd_iteration_flag;
6022 int finish_flag;
6023 vla_ptr_t next_iteration_classes;
6024 state_t *equiv_class_ptr;
6025 state_t *state_ptr;
6027 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6028 pass_states (automaton, add_achieved_state);
6029 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6030 VLA_PTR_LENGTH (all_achieved_states));
6031 odd_iteration_flag = 0;
6032 new_equiv_class_num = 1;
6033 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6034 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6037 odd_iteration_flag = !odd_iteration_flag;
6038 finish_flag = 1;
6039 copy_equiv_class (equiv_classes, &next_iteration_classes);
6040 /* Transfer equiv numbers for the next iteration. */
6041 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6042 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6043 state_ptr++)
6044 if (odd_iteration_flag)
6045 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6046 else
6047 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6048 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6049 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6050 equiv_class_ptr++)
6051 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6052 &next_iteration_classes,
6053 &new_equiv_class_num))
6054 finish_flag = 0;
6056 while (!finish_flag);
6057 VLA_PTR_DELETE (next_iteration_classes);
6058 VLA_PTR_DELETE (all_achieved_states);
6061 /* The function merges equivalent states of AUTOMATON. */
6062 static void
6063 merge_states (automaton, equiv_classes)
6064 automaton_t automaton;
6065 vla_ptr_t *equiv_classes;
6067 state_t *equiv_class_ptr;
6068 state_t curr_state;
6069 state_t new_state;
6070 state_t first_class_state;
6071 alt_state_t alt_states;
6072 alt_state_t new_alt_state;
6073 arc_t curr_arc;
6074 arc_t next_arc;
6076 /* Create states corresponding to equivalence classes containing two
6077 or more states. */
6078 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6079 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6080 equiv_class_ptr++)
6081 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6083 /* There are more one states in the class equivalence. */
6084 /* Create new compound state. */
6085 new_state = get_free_state (0, automaton);
6086 alt_states = NULL;
6087 first_class_state = *equiv_class_ptr;
6088 for (curr_state = first_class_state;
6089 curr_state != NULL;
6090 curr_state = curr_state->next_equiv_class_state)
6092 curr_state->equiv_class_state = new_state;
6093 new_alt_state = get_free_alt_state ();
6094 new_alt_state->state = curr_state;
6095 new_alt_state->next_sorted_alt_state = alt_states;
6096 alt_states = new_alt_state;
6098 new_state->component_states = alt_states;
6100 else
6101 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6102 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6103 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6104 equiv_class_ptr++)
6105 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6107 first_class_state = *equiv_class_ptr;
6108 /* Create new arcs output from the state corresponding to
6109 equiv class. */
6110 for (curr_arc = first_out_arc (first_class_state);
6111 curr_arc != NULL;
6112 curr_arc = next_out_arc (curr_arc))
6113 add_arc (first_class_state->equiv_class_state,
6114 curr_arc->to_state->equiv_class_state,
6115 curr_arc->insn, curr_arc->state_alts);
6116 /* Delete output arcs from states of given class equivalence. */
6117 for (curr_state = first_class_state;
6118 curr_state != NULL;
6119 curr_state = curr_state->next_equiv_class_state)
6121 if (automaton->start_state == curr_state)
6122 automaton->start_state = curr_state->equiv_class_state;
6123 /* Delete the state and its output arcs. */
6124 for (curr_arc = first_out_arc (curr_state);
6125 curr_arc != NULL;
6126 curr_arc = next_arc)
6128 next_arc = next_out_arc (curr_arc);
6129 free_arc (curr_arc);
6133 else
6135 /* Change `to_state' of arcs output from the state of given
6136 equivalence class. */
6137 for (curr_arc = first_out_arc (*equiv_class_ptr);
6138 curr_arc != NULL;
6139 curr_arc = next_out_arc (curr_arc))
6140 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6144 /* The function sets up new_cycle_p for states if there is arc to the
6145 state marked by advance_cycle_insn_decl. */
6146 static void
6147 set_new_cycle_flags (state)
6148 state_t state;
6150 arc_t arc;
6152 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6153 if (arc->insn->insn_reserv_decl
6154 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6155 arc->to_state->new_cycle_p = 1;
6158 /* The top level function for minimization of deterministic
6159 AUTOMATON. */
6160 static void
6161 minimize_DFA (automaton)
6162 automaton_t automaton;
6164 vla_ptr_t equiv_classes;
6166 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6167 evaluate_equiv_classes (automaton, &equiv_classes);
6168 merge_states (automaton, &equiv_classes);
6169 pass_states (automaton, set_new_cycle_flags);
6170 VLA_PTR_DELETE (equiv_classes);
6173 /* Values of two variables are counted number of states and arcs in an
6174 automaton. */
6175 static int curr_counted_states_num;
6176 static int curr_counted_arcs_num;
6178 /* The function is called by function `pass_states' to count states
6179 and arcs of an automaton. */
6180 static void
6181 incr_states_and_arcs_nums (state)
6182 state_t state;
6184 arc_t arc;
6186 curr_counted_states_num++;
6187 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6188 curr_counted_arcs_num++;
6191 /* The function counts states and arcs of AUTOMATON. */
6192 static void
6193 count_states_and_arcs (automaton, states_num, arcs_num)
6194 automaton_t automaton;
6195 int *states_num;
6196 int *arcs_num;
6198 curr_counted_states_num = 0;
6199 curr_counted_arcs_num = 0;
6200 pass_states (automaton, incr_states_and_arcs_nums);
6201 *states_num = curr_counted_states_num;
6202 *arcs_num = curr_counted_arcs_num;
6205 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6206 recognition after checking and simplifying IR of the
6207 description. */
6208 static void
6209 build_automaton (automaton)
6210 automaton_t automaton;
6212 int states_num;
6213 int arcs_num;
6215 ticker_on (&NDFA_time);
6216 make_automaton (automaton);
6217 ticker_off (&NDFA_time);
6218 count_states_and_arcs (automaton, &states_num, &arcs_num);
6219 automaton->NDFA_states_num = states_num;
6220 automaton->NDFA_arcs_num = arcs_num;
6221 ticker_on (&NDFA_to_DFA_time);
6222 NDFA_to_DFA (automaton);
6223 ticker_off (&NDFA_to_DFA_time);
6224 count_states_and_arcs (automaton, &states_num, &arcs_num);
6225 automaton->DFA_states_num = states_num;
6226 automaton->DFA_arcs_num = arcs_num;
6227 if (!no_minimization_flag)
6229 ticker_on (&minimize_time);
6230 minimize_DFA (automaton);
6231 ticker_off (&minimize_time);
6232 count_states_and_arcs (automaton, &states_num, &arcs_num);
6233 automaton->minimal_DFA_states_num = states_num;
6234 automaton->minimal_DFA_arcs_num = arcs_num;
6240 /* The page contains code for enumeration of all states of an automaton. */
6242 /* Variable used for enumeration of all states of an automaton. Its
6243 value is current number of automaton states. */
6244 static int curr_state_order_num;
6246 /* The function is called by function `pass_states' for enumerating
6247 states. */
6248 static void
6249 set_order_state_num (state)
6250 state_t state;
6252 state->order_state_num = curr_state_order_num;
6253 curr_state_order_num++;
6256 /* The function enumerates all states of AUTOMATON. */
6257 static void
6258 enumerate_states (automaton)
6259 automaton_t automaton;
6261 curr_state_order_num = 0;
6262 pass_states (automaton, set_order_state_num);
6263 automaton->achieved_states_num = curr_state_order_num;
6268 /* The page contains code for finding equivalent automaton insns
6269 (ainsns). */
6271 /* The function inserts AINSN into cyclic list
6272 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6273 static ainsn_t
6274 insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6275 ainsn_t ainsn;
6276 ainsn_t cyclic_equiv_class_insn_list;
6278 if (cyclic_equiv_class_insn_list == NULL)
6279 ainsn->next_equiv_class_insn = ainsn;
6280 else
6282 ainsn->next_equiv_class_insn
6283 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6284 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6286 return ainsn;
6289 /* The function deletes equiv_class_insn into cyclic list of
6290 equivalent ainsns. */
6291 static void
6292 delete_ainsn_from_equiv_class (equiv_class_insn)
6293 ainsn_t equiv_class_insn;
6295 ainsn_t curr_equiv_class_insn;
6296 ainsn_t prev_equiv_class_insn;
6298 prev_equiv_class_insn = equiv_class_insn;
6299 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6300 curr_equiv_class_insn != equiv_class_insn;
6301 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6302 prev_equiv_class_insn = curr_equiv_class_insn;
6303 if (prev_equiv_class_insn != equiv_class_insn)
6304 prev_equiv_class_insn->next_equiv_class_insn
6305 = equiv_class_insn->next_equiv_class_insn;
6308 /* The function processes AINSN of a state in order to find equivalent
6309 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6310 state. */
6311 static void
6312 process_insn_equiv_class (ainsn, insn_arcs_array)
6313 ainsn_t ainsn;
6314 arc_t *insn_arcs_array;
6316 ainsn_t next_insn;
6317 ainsn_t curr_insn;
6318 ainsn_t cyclic_insn_list;
6319 arc_t arc;
6321 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6322 abort ();
6323 curr_insn = ainsn;
6324 /* New class of ainsns which are not equivalent to given ainsn. */
6325 cyclic_insn_list = NULL;
6328 next_insn = curr_insn->next_equiv_class_insn;
6329 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6330 if (arc == NULL
6331 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6332 != arc->to_state))
6334 delete_ainsn_from_equiv_class (curr_insn);
6335 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6336 cyclic_insn_list);
6338 curr_insn = next_insn;
6340 while (curr_insn != ainsn);
6343 /* The function processes STATE in order to find equivalent ainsns. */
6344 static void
6345 process_state_for_insn_equiv_partition (state)
6346 state_t state;
6348 arc_t arc;
6349 arc_t *insn_arcs_array;
6350 int i;
6351 vla_ptr_t insn_arcs_vect;
6353 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6354 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6355 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6356 /* Process insns of the arcs. */
6357 for (i = 0; i < description->insns_num; i++)
6358 insn_arcs_array [i] = NULL;
6359 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6360 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6361 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6362 process_insn_equiv_class (arc->insn, insn_arcs_array);
6363 VLA_PTR_DELETE (insn_arcs_vect);
6366 /* The function searches for equivalent ainsns of AUTOMATON. */
6367 static void
6368 set_insn_equiv_classes (automaton)
6369 automaton_t automaton;
6371 ainsn_t ainsn;
6372 ainsn_t first_insn;
6373 ainsn_t curr_insn;
6374 ainsn_t cyclic_insn_list;
6375 ainsn_t insn_with_same_reservs;
6376 int equiv_classes_num;
6378 /* All insns are included in one equivalence class. */
6379 cyclic_insn_list = NULL;
6380 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6381 if (ainsn->first_insn_with_same_reservs)
6382 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6383 cyclic_insn_list);
6384 /* Process insns in order to make equivalence partition. */
6385 pass_states (automaton, process_state_for_insn_equiv_partition);
6386 /* Enumerate equiv classes. */
6387 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6388 /* Set undefined value. */
6389 ainsn->insn_equiv_class_num = -1;
6390 equiv_classes_num = 0;
6391 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6392 if (ainsn->insn_equiv_class_num < 0)
6394 first_insn = ainsn;
6395 if (!first_insn->first_insn_with_same_reservs)
6396 abort ();
6397 first_insn->first_ainsn_with_given_equialence_num = 1;
6398 curr_insn = first_insn;
6401 for (insn_with_same_reservs = curr_insn;
6402 insn_with_same_reservs != NULL;
6403 insn_with_same_reservs
6404 = insn_with_same_reservs->next_same_reservs_insn)
6405 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6406 curr_insn = curr_insn->next_equiv_class_insn;
6408 while (curr_insn != first_insn);
6409 equiv_classes_num++;
6411 automaton->insn_equiv_classes_num = equiv_classes_num;
6416 /* This page contains code for creating DFA(s) and calls functions
6417 building them. */
6420 /* The following value is used to prevent floating point overflow for
6421 estimating an automaton bound. The value should be less DBL_MAX on
6422 the host machine. We use here approximate minimum of maximal
6423 double floating point value required by ANSI C standard. It
6424 will work for non ANSI sun compiler too. */
6426 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6428 /* The function estimate size of the single DFA used by PHR (pipeline
6429 hazards recognizer). */
6430 static double
6431 estimate_one_automaton_bound ()
6433 decl_t decl;
6434 double one_automaton_estimation_bound;
6435 double root_value;
6436 int i;
6438 one_automaton_estimation_bound = 1.0;
6439 for (i = 0; i < description->decls_num; i++)
6441 decl = description->decls [i];
6442 if (decl->mode == dm_unit)
6444 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num + 1.0)
6445 / automata_num);
6446 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6447 > one_automaton_estimation_bound)
6448 one_automaton_estimation_bound *= root_value;
6451 return one_automaton_estimation_bound;
6454 /* The function compares unit declarations acoording to their maximal
6455 cycle in reservations. */
6456 static int
6457 compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6458 const void *unit_decl_1;
6459 const void *unit_decl_2;
6461 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6462 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6463 return 1;
6464 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6465 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6466 return 0;
6467 else
6468 return -1;
6471 /* The function makes heuristic assigning automata to units. Actually
6472 efficacy of the algorithm has been checked yet??? */
6473 static void
6474 units_to_automata_heuristic_distr ()
6476 double estimation_bound;
6477 decl_t decl;
6478 decl_t *unit_decl_ptr;
6479 int automaton_num;
6480 int rest_units_num;
6481 double bound_value;
6482 vla_ptr_t unit_decls;
6483 int i;
6485 if (description->units_num == 0)
6486 return;
6487 estimation_bound = estimate_one_automaton_bound ();
6488 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6489 for (i = 0; i < description->decls_num; i++)
6491 decl = description->decls [i];
6492 if (decl->mode == dm_unit)
6493 VLA_PTR_ADD (unit_decls, decl);
6495 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6496 sizeof (decl_t), compare_max_occ_cycle_nums);
6497 automaton_num = 0;
6498 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6499 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6500 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6501 for (unit_decl_ptr++;
6502 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6503 unit_decl_ptr++)
6505 rest_units_num
6506 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6507 if (automata_num - automaton_num - 1 > rest_units_num)
6508 abort ();
6509 if (automaton_num < automata_num - 1
6510 && ((automata_num - automaton_num - 1 == rest_units_num)
6511 || (bound_value
6512 > (estimation_bound
6513 / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6515 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6516 automaton_num++;
6518 else
6519 bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6520 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6522 if (automaton_num != automata_num - 1)
6523 abort ();
6524 VLA_PTR_DELETE (unit_decls);
6527 /* The functions creates automaton insns for each automata. Automaton
6528 insn is simply insn for given automaton which makes reservation
6529 only of units of the automaton. */
6530 static ainsn_t
6531 create_ainsns ()
6533 decl_t decl;
6534 ainsn_t first_ainsn;
6535 ainsn_t curr_ainsn;
6536 ainsn_t prev_ainsn;
6537 int i;
6539 first_ainsn = NULL;
6540 prev_ainsn = NULL;
6541 for (i = 0; i < description->decls_num; i++)
6543 decl = description->decls [i];
6544 if (decl->mode == dm_insn_reserv)
6546 curr_ainsn = create_node (sizeof (struct ainsn));
6547 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6548 curr_ainsn->important_p = FALSE;
6549 curr_ainsn->next_ainsn = NULL;
6550 if (prev_ainsn == NULL)
6551 first_ainsn = curr_ainsn;
6552 else
6553 prev_ainsn->next_ainsn = curr_ainsn;
6554 prev_ainsn = curr_ainsn;
6557 return first_ainsn;
6560 /* The function assigns automata to units according to constructions
6561 `define_automaton' in the description. */
6562 static void
6563 units_to_automata_distr ()
6565 decl_t decl;
6566 int i;
6568 for (i = 0; i < description->decls_num; i++)
6570 decl = description->decls [i];
6571 if (decl->mode == dm_unit)
6573 if (DECL_UNIT (decl)->automaton_decl == NULL
6574 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6575 == NULL))
6576 /* Distribute to the first automaton. */
6577 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6578 else
6579 DECL_UNIT (decl)->corresponding_automaton_num
6580 = (DECL_UNIT (decl)->automaton_decl
6581 ->corresponding_automaton->automaton_order_num);
6586 /* The function creates DFA(s) for fast pipeline hazards recognition
6587 after checking and simplifying IR of the description. */
6588 static void
6589 create_automata ()
6591 automaton_t curr_automaton;
6592 automaton_t prev_automaton;
6593 decl_t decl;
6594 int curr_automaton_num;
6595 int i;
6597 if (automata_num != 0)
6599 units_to_automata_heuristic_distr ();
6600 for (prev_automaton = NULL, curr_automaton_num = 0;
6601 curr_automaton_num < automata_num;
6602 curr_automaton_num++, prev_automaton = curr_automaton)
6604 curr_automaton = create_node (sizeof (struct automaton));
6605 curr_automaton->ainsn_list = create_ainsns ();
6606 curr_automaton->corresponding_automaton_decl = NULL;
6607 curr_automaton->next_automaton = NULL;
6608 curr_automaton->automaton_order_num = curr_automaton_num;
6609 if (prev_automaton == NULL)
6610 description->first_automaton = curr_automaton;
6611 else
6612 prev_automaton->next_automaton = curr_automaton;
6615 else
6617 curr_automaton_num = 0;
6618 prev_automaton = NULL;
6619 for (i = 0; i < description->decls_num; i++)
6621 decl = description->decls [i];
6622 if (decl->mode == dm_automaton
6623 && DECL_AUTOMATON (decl)->automaton_is_used)
6625 curr_automaton = create_node (sizeof (struct automaton));
6626 curr_automaton->ainsn_list = create_ainsns ();
6627 curr_automaton->corresponding_automaton_decl
6628 = DECL_AUTOMATON (decl);
6629 curr_automaton->next_automaton = NULL;
6630 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6631 curr_automaton->automaton_order_num = curr_automaton_num;
6632 if (prev_automaton == NULL)
6633 description->first_automaton = curr_automaton;
6634 else
6635 prev_automaton->next_automaton = curr_automaton;
6636 curr_automaton_num++;
6637 prev_automaton = curr_automaton;
6640 if (curr_automaton_num == 0)
6642 curr_automaton = create_node (sizeof (struct automaton));
6643 curr_automaton->ainsn_list = create_ainsns ();
6644 curr_automaton->corresponding_automaton_decl = NULL;
6645 curr_automaton->next_automaton = NULL;
6646 description->first_automaton = curr_automaton;
6648 units_to_automata_distr ();
6650 NDFA_time = create_ticker ();
6651 ticker_off (&NDFA_time);
6652 NDFA_to_DFA_time = create_ticker ();
6653 ticker_off (&NDFA_to_DFA_time);
6654 minimize_time = create_ticker ();
6655 ticker_off (&minimize_time);
6656 equiv_time = create_ticker ();
6657 ticker_off (&equiv_time);
6658 for (curr_automaton = description->first_automaton;
6659 curr_automaton != NULL;
6660 curr_automaton = curr_automaton->next_automaton)
6662 if (curr_automaton->corresponding_automaton_decl == NULL)
6663 fprintf (stderr, "Create anonymous automaton ...");
6664 else
6665 fprintf (stderr, "Create automaton `%s'...",
6666 curr_automaton->corresponding_automaton_decl->name);
6667 create_alt_states (curr_automaton);
6668 form_ainsn_with_same_reservs (curr_automaton);
6669 build_automaton (curr_automaton);
6670 enumerate_states (curr_automaton);
6671 ticker_on (&equiv_time);
6672 set_insn_equiv_classes (curr_automaton);
6673 ticker_off (&equiv_time);
6674 fprintf (stderr, "done\n");
6680 /* This page contains code for forming string representation of
6681 regexp. The representation is formed on IR obstack. So you should
6682 not work with IR obstack between regexp_representation and
6683 finish_regexp_representation calls. */
6685 /* This recursive function forms string representation of regexp
6686 (without tailing '\0'). */
6687 static void
6688 form_regexp (regexp)
6689 regexp_t regexp;
6691 int i;
6693 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6695 const char *name = (regexp->mode == rm_unit
6696 ? REGEXP_UNIT (regexp)->name
6697 : REGEXP_RESERV (regexp)->name);
6699 obstack_grow (&irp, name, strlen (name));
6701 else if (regexp->mode == rm_sequence)
6702 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6704 if (i != 0)
6705 obstack_1grow (&irp, ',');
6706 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6708 else if (regexp->mode == rm_allof)
6710 obstack_1grow (&irp, '(');
6711 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6713 if (i != 0)
6714 obstack_1grow (&irp, '+');
6715 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6716 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6717 obstack_1grow (&irp, '(');
6718 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6719 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6720 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6721 obstack_1grow (&irp, ')');
6723 obstack_1grow (&irp, ')');
6725 else if (regexp->mode == rm_oneof)
6726 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6728 if (i != 0)
6729 obstack_1grow (&irp, '|');
6730 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6731 obstack_1grow (&irp, '(');
6732 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6733 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6734 obstack_1grow (&irp, ')');
6736 else if (regexp->mode == rm_repeat)
6738 char digits [30];
6740 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6741 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6742 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6743 obstack_1grow (&irp, '(');
6744 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6745 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6746 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6747 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6748 obstack_1grow (&irp, ')');
6749 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6750 obstack_grow (&irp, digits, strlen (digits));
6752 else if (regexp->mode == rm_nothing)
6753 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6754 else
6755 abort ();
6758 /* The function returns string representation of REGEXP on IR
6759 obstack. */
6760 static const char *
6761 regexp_representation (regexp)
6762 regexp_t regexp;
6764 form_regexp (regexp);
6765 obstack_1grow (&irp, '\0');
6766 return obstack_base (&irp);
6769 /* The function frees memory allocated for last formed string
6770 representation of regexp. */
6771 static void
6772 finish_regexp_representation ()
6774 int length = obstack_object_size (&irp);
6776 obstack_blank_fast (&irp, -length);
6781 /* This page contains code for output PHR (pipeline hazards recognizer). */
6783 /* The function outputs minimal C type which is sufficient for
6784 representation numbers in range min_range_value and
6785 max_range_value. Because host machine and build machine may be
6786 different, we use here minimal values required by ANSI C standard
6787 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6788 approximation. */
6790 static void
6791 output_range_type (f, min_range_value, max_range_value)
6792 FILE *f;
6793 long int min_range_value;
6794 long int max_range_value;
6796 if (min_range_value >= 0 && max_range_value <= 255)
6797 fprintf (f, "unsigned char");
6798 else if (min_range_value >= -127 && max_range_value <= 127)
6799 fprintf (f, "signed char");
6800 else if (min_range_value >= 0 && max_range_value <= 65535)
6801 fprintf (f, "unsigned short");
6802 else if (min_range_value >= -32767 && max_range_value <= 32767)
6803 fprintf (f, "short");
6804 else
6805 fprintf (f, "int");
6808 /* The following macro value is used as value of member
6809 `longest_path_length' of state when we are processing path and the
6810 state on the path. */
6812 #define ON_THE_PATH -2
6814 /* The following recursive function searches for the length of the
6815 longest path starting from STATE which does not contain cycles and
6816 `cycle advance' arcs. */
6818 static int
6819 longest_path_length (state)
6820 state_t state;
6822 arc_t arc;
6823 int length, result;
6825 if (state->longest_path_length == ON_THE_PATH)
6826 /* We don't expect the path cycle here. Our graph may contain
6827 only cycles with one state on the path not containing `cycle
6828 advance' arcs -- see comment below. */
6829 abort ();
6830 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6831 /* We alreday visited the state. */
6832 return state->longest_path_length;
6834 result = 0;
6835 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6836 /* Ignore cycles containing one state and `cycle advance' arcs. */
6837 if (arc->to_state != state
6838 && (arc->insn->insn_reserv_decl
6839 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6841 length = longest_path_length (arc->to_state);
6842 if (length > result)
6843 result = length;
6845 state->longest_path_length = result + 1;
6846 return result;
6849 /* The following variable value is value of the corresponding global
6850 variable in the automaton based pipeline interface. */
6852 static int max_dfa_issue_rate;
6854 /* The following function processes the longest path length staring
6855 from STATE to find MAX_DFA_ISSUE_RATE. */
6857 static void
6858 process_state_longest_path_length (state)
6859 state_t state;
6861 int value;
6863 value = longest_path_length (state);
6864 if (value > max_dfa_issue_rate)
6865 max_dfa_issue_rate = value;
6868 /* The following macro value is name of the corresponding global
6869 variable in the automaton based pipeline interface. */
6871 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
6873 /* The following function calculates value of the corresponding
6874 global variable and outputs its declaration. */
6876 static void
6877 output_dfa_max_issue_rate ()
6879 automaton_t automaton;
6881 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
6882 abort ();
6883 max_dfa_issue_rate = 0;
6884 for (automaton = description->first_automaton;
6885 automaton != NULL;
6886 automaton = automaton->next_automaton)
6887 pass_states (automaton, process_state_longest_path_length);
6888 fprintf (output_file, "\nint %s = %d;\n",
6889 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
6892 /* The function outputs all initialization values of VECT with length
6893 vect_length. */
6894 static void
6895 output_vect (vect, vect_length)
6896 vect_el_t *vect;
6897 int vect_length;
6899 int els_on_line;
6901 els_on_line = 1;
6902 if (vect_length == 0)
6903 fprintf (output_file,
6904 "0 /* This is dummy el because the vect is empty */");
6905 else
6909 fprintf (output_file, "%5ld", (long) *vect);
6910 vect_length--;
6911 if (els_on_line == 10)
6913 els_on_line = 0;
6914 fprintf (output_file, ",\n");
6916 else if (vect_length != 0)
6917 fprintf (output_file, ", ");
6918 els_on_line++;
6919 vect++;
6921 while (vect_length != 0);
6925 /* The following is name of the structure which represents DFA(s) for
6926 PHR. */
6927 #define CHIP_NAME "DFA_chip"
6929 /* The following is name of member which represents state of a DFA for
6930 PHR. */
6931 static void
6932 output_chip_member_name (f, automaton)
6933 FILE *f;
6934 automaton_t automaton;
6936 if (automaton->corresponding_automaton_decl == NULL)
6937 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6938 else
6939 fprintf (f, "%s_automaton_state",
6940 automaton->corresponding_automaton_decl->name);
6943 /* The following is name of temporary variable which stores state of a
6944 DFA for PHR. */
6945 static void
6946 output_temp_chip_member_name (f, automaton)
6947 FILE *f;
6948 automaton_t automaton;
6950 fprintf (f, "_");
6951 output_chip_member_name (f, automaton);
6954 /* This is name of macro value which is code of pseudo_insn
6955 representing advancing cpu cycle. Its value is used as internal
6956 code unknown insn. */
6957 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6959 /* Output name of translate vector for given automaton. */
6960 static void
6961 output_translate_vect_name (f, automaton)
6962 FILE *f;
6963 automaton_t automaton;
6965 if (automaton->corresponding_automaton_decl == NULL)
6966 fprintf (f, "translate_%d", automaton->automaton_order_num);
6967 else
6968 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6971 /* Output name for simple transition table representation. */
6972 static void
6973 output_trans_full_vect_name (f, automaton)
6974 FILE *f;
6975 automaton_t automaton;
6977 if (automaton->corresponding_automaton_decl == NULL)
6978 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6979 else
6980 fprintf (f, "%s_transitions",
6981 automaton->corresponding_automaton_decl->name);
6984 /* Output name of comb vector of the transition table for given
6985 automaton. */
6986 static void
6987 output_trans_comb_vect_name (f, automaton)
6988 FILE *f;
6989 automaton_t automaton;
6991 if (automaton->corresponding_automaton_decl == NULL)
6992 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6993 else
6994 fprintf (f, "%s_transitions",
6995 automaton->corresponding_automaton_decl->name);
6998 /* Output name of check vector of the transition table for given
6999 automaton. */
7000 static void
7001 output_trans_check_vect_name (f, automaton)
7002 FILE *f;
7003 automaton_t automaton;
7005 if (automaton->corresponding_automaton_decl == NULL)
7006 fprintf (f, "check_%d", automaton->automaton_order_num);
7007 else
7008 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7011 /* Output name of base vector of the transition table for given
7012 automaton. */
7013 static void
7014 output_trans_base_vect_name (f, automaton)
7015 FILE *f;
7016 automaton_t automaton;
7018 if (automaton->corresponding_automaton_decl == NULL)
7019 fprintf (f, "base_%d", automaton->automaton_order_num);
7020 else
7021 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7024 /* Output name for simple alternatives number representation. */
7025 static void
7026 output_state_alts_full_vect_name (f, automaton)
7027 FILE *f;
7028 automaton_t automaton;
7030 if (automaton->corresponding_automaton_decl == NULL)
7031 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7032 else
7033 fprintf (f, "%s_state_alts",
7034 automaton->corresponding_automaton_decl->name);
7037 /* Output name of comb vector of the alternatives number table for given
7038 automaton. */
7039 static void
7040 output_state_alts_comb_vect_name (f, automaton)
7041 FILE *f;
7042 automaton_t automaton;
7044 if (automaton->corresponding_automaton_decl == NULL)
7045 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7046 else
7047 fprintf (f, "%s_state_alts",
7048 automaton->corresponding_automaton_decl->name);
7051 /* Output name of check vector of the alternatives number table for given
7052 automaton. */
7053 static void
7054 output_state_alts_check_vect_name (f, automaton)
7055 FILE *f;
7056 automaton_t automaton;
7058 if (automaton->corresponding_automaton_decl == NULL)
7059 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7060 else
7061 fprintf (f, "%s_check_state_alts",
7062 automaton->corresponding_automaton_decl->name);
7065 /* Output name of base vector of the alternatives number table for given
7066 automaton. */
7067 static void
7068 output_state_alts_base_vect_name (f, automaton)
7069 FILE *f;
7070 automaton_t automaton;
7072 if (automaton->corresponding_automaton_decl == NULL)
7073 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7074 else
7075 fprintf (f, "%s_base_state_alts",
7076 automaton->corresponding_automaton_decl->name);
7079 /* Output name of simple min issue delay table representation. */
7080 static void
7081 output_min_issue_delay_vect_name (f, automaton)
7082 FILE *f;
7083 automaton_t automaton;
7085 if (automaton->corresponding_automaton_decl == NULL)
7086 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7087 else
7088 fprintf (f, "%s_min_issue_delay",
7089 automaton->corresponding_automaton_decl->name);
7092 /* Output name of deadlock vector for given automaton. */
7093 static void
7094 output_dead_lock_vect_name (f, automaton)
7095 FILE *f;
7096 automaton_t automaton;
7098 if (automaton->corresponding_automaton_decl == NULL)
7099 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7100 else
7101 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7104 /* Output name of reserved units table for AUTOMATON into file F. */
7105 static void
7106 output_reserved_units_table_name (f, automaton)
7107 FILE *f;
7108 automaton_t automaton;
7110 if (automaton->corresponding_automaton_decl == NULL)
7111 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7112 else
7113 fprintf (f, "%s_reserved_units",
7114 automaton->corresponding_automaton_decl->name);
7117 /* Name of the PHR interface macro. */
7118 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7120 /* Name of the PHR interface macro. */
7121 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7123 /* Names of an internal functions: */
7124 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7126 /* This is external type of DFA(s) state. */
7127 #define STATE_TYPE_NAME "state_t"
7129 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7131 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7133 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7135 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7137 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7139 /* Name of cache of insn dfa codes. */
7140 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7142 /* Name of length of cache of insn dfa codes. */
7143 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7145 /* Names of the PHR interface functions: */
7146 #define SIZE_FUNC_NAME "state_size"
7148 #define TRANSITION_FUNC_NAME "state_transition"
7150 #define STATE_ALTS_FUNC_NAME "state_alts"
7152 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7154 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7156 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7158 #define RESET_FUNC_NAME "state_reset"
7160 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7162 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7164 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7166 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7168 #define DFA_START_FUNC_NAME "dfa_start"
7170 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7172 /* Names of parameters of the PHR interface functions. */
7173 #define STATE_NAME "state"
7175 #define INSN_PARAMETER_NAME "insn"
7177 #define INSN2_PARAMETER_NAME "insn2"
7179 #define CHIP_PARAMETER_NAME "chip"
7181 #define FILE_PARAMETER_NAME "f"
7183 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7185 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7187 /* Names of the variables whose values are internal insn code of rtx
7188 insn. */
7189 #define INTERNAL_INSN_CODE_NAME "insn_code"
7191 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7193 /* Names of temporary variables in some functions. */
7194 #define TEMPORARY_VARIABLE_NAME "temp"
7196 #define I_VARIABLE_NAME "i"
7198 /* Name of result variable in some functions. */
7199 #define RESULT_VARIABLE_NAME "res"
7201 /* Name of function (attribute) to translate insn into number of insn
7202 alternatives reservation. */
7203 #define INSN_ALTS_FUNC_NAME "insn_alts"
7205 /* Name of function (attribute) to translate insn into internal insn
7206 code. */
7207 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7209 /* Name of function (attribute) to translate insn into internal insn
7210 code with caching. */
7211 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7213 /* Name of function (attribute) to translate insn into internal insn
7214 code. */
7215 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7217 /* Name of function (attribute) to translate insn into internal insn
7218 code. */
7219 #define BYPASS_P_FUNC_NAME "bypass_p"
7221 /* Output C type which is used for representation of codes of states
7222 of AUTOMATON. */
7223 static void
7224 output_state_member_type (f, automaton)
7225 FILE *f;
7226 automaton_t automaton;
7228 output_range_type (f, 0, automaton->achieved_states_num);
7231 /* Output definition of the structure representing current DFA(s)
7232 state(s). */
7233 static void
7234 output_chip_definitions ()
7236 automaton_t automaton;
7238 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7239 for (automaton = description->first_automaton;
7240 automaton != NULL;
7241 automaton = automaton->next_automaton)
7243 fprintf (output_file, " ");
7244 output_state_member_type (output_file, automaton);
7245 fprintf (output_file, " ");
7246 output_chip_member_name (output_file, automaton);
7247 fprintf (output_file, ";\n");
7249 fprintf (output_file, "};\n\n");
7250 #if 0
7251 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7252 #endif
7256 /* The function outputs translate vector of internal insn code into
7257 insn equivalence class number. The equivalence class number is
7258 used to access to table and vectors reprewsenting DFA(s). */
7259 static void
7260 output_translate_vect (automaton)
7261 automaton_t automaton;
7263 ainsn_t ainsn;
7264 int insn_value;
7265 vla_hwint_t translate_vect;
7267 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7268 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7269 for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
7270 /* Undefined value */
7271 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7272 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7273 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7274 = ainsn->insn_equiv_class_num;
7275 fprintf (output_file,
7276 "/* Vector translating external insn codes to internal ones.*/\n");
7277 fprintf (output_file, "static const ");
7278 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7279 fprintf (output_file, " ");
7280 output_translate_vect_name (output_file, automaton);
7281 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7282 output_vect (VLA_HWINT_BEGIN (translate_vect),
7283 VLA_HWINT_LENGTH (translate_vect));
7284 fprintf (output_file, "};\n\n");
7285 VLA_HWINT_DELETE (translate_vect);
7288 /* The value in a table state x ainsn -> something which represents
7289 undefined value. */
7290 static int undefined_vect_el_value;
7292 /* The following function returns nonzero value if the best
7293 representation of the table is comb vector. */
7294 static int
7295 comb_vect_p (tab)
7296 state_ainsn_table_t tab;
7298 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7299 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7302 /* The following function creates new table for AUTOMATON. */
7303 static state_ainsn_table_t
7304 create_state_ainsn_table (automaton)
7305 automaton_t automaton;
7307 state_ainsn_table_t tab;
7308 int full_vect_length;
7309 int i;
7311 tab = create_node (sizeof (struct state_ainsn_table));
7312 tab->automaton = automaton;
7313 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7314 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7315 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7316 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7317 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7318 full_vect_length = (automaton->insn_equiv_classes_num
7319 * automaton->achieved_states_num);
7320 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7321 for (i = 0; i < full_vect_length; i++)
7322 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7323 tab->min_base_vect_el_value = 0;
7324 tab->max_base_vect_el_value = 0;
7325 tab->min_comb_vect_el_value = 0;
7326 tab->max_comb_vect_el_value = 0;
7327 return tab;
7330 /* The following function outputs the best C representation of the
7331 table TAB of given TABLE_NAME. */
7332 static void
7333 output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7334 output_comb_vect_name_func,
7335 output_check_vect_name_func,
7336 output_base_vect_name_func)
7337 state_ainsn_table_t tab;
7338 char *table_name;
7339 void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7340 void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7341 void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7342 void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7344 if (!comb_vect_p (tab))
7346 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7347 fprintf (output_file, "static const ");
7348 output_range_type (output_file, tab->min_comb_vect_el_value,
7349 tab->max_comb_vect_el_value);
7350 fprintf (output_file, " ");
7351 (*output_full_vect_name_func) (output_file, tab->automaton);
7352 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7353 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7354 VLA_HWINT_LENGTH (tab->full_vect));
7355 fprintf (output_file, "};\n\n");
7357 else
7359 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7360 fprintf (output_file, "static const ");
7361 output_range_type (output_file, tab->min_comb_vect_el_value,
7362 tab->max_comb_vect_el_value);
7363 fprintf (output_file, " ");
7364 (*output_comb_vect_name_func) (output_file, tab->automaton);
7365 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7366 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7367 VLA_HWINT_LENGTH (tab->comb_vect));
7368 fprintf (output_file, "};\n\n");
7369 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7370 fprintf (output_file, "static const ");
7371 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7372 fprintf (output_file, " ");
7373 (*output_check_vect_name_func) (output_file, tab->automaton);
7374 fprintf (output_file, "[] = {\n");
7375 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7376 VLA_HWINT_LENGTH (tab->check_vect));
7377 fprintf (output_file, "};\n\n");
7378 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7379 fprintf (output_file, "static const ");
7380 output_range_type (output_file, tab->min_base_vect_el_value,
7381 tab->max_base_vect_el_value);
7382 fprintf (output_file, " ");
7383 (*output_base_vect_name_func) (output_file, tab->automaton);
7384 fprintf (output_file, "[] = {\n");
7385 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7386 VLA_HWINT_LENGTH (tab->base_vect));
7387 fprintf (output_file, "};\n\n");
7391 /* The following function adds vector with length VECT_LENGTH and
7392 elements pointed by VECT to table TAB as its line with number
7393 VECT_NUM. */
7394 static void
7395 add_vect (tab, vect_num, vect, vect_length)
7396 state_ainsn_table_t tab;
7397 int vect_num;
7398 vect_el_t *vect;
7399 int vect_length;
7401 int real_vect_length;
7402 vect_el_t *comb_vect_start;
7403 vect_el_t *check_vect_start;
7404 int comb_vect_index;
7405 int comb_vect_els_num;
7406 int vect_index;
7407 int first_unempty_vect_index;
7408 int additional_els_num;
7409 int no_state_value;
7410 vect_el_t vect_el;
7411 int i;
7413 if (vect_length == 0)
7414 abort ();
7415 real_vect_length = tab->automaton->insn_equiv_classes_num;
7416 if (vect [vect_length - 1] == undefined_vect_el_value)
7417 abort ();
7418 /* Form full vector in the table: */
7419 for (i = 0; i < vect_length; i++)
7420 VLA_HWINT (tab->full_vect,
7421 i + tab->automaton->insn_equiv_classes_num * vect_num)
7422 = vect [i];
7423 /* Form comb vector in the table: */
7424 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7425 abort ();
7426 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7427 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7428 for (first_unempty_vect_index = 0;
7429 first_unempty_vect_index < vect_length;
7430 first_unempty_vect_index++)
7431 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7432 break;
7433 /* Search for the place in comb vect for the inserted vect. */
7434 for (comb_vect_index = 0;
7435 comb_vect_index < comb_vect_els_num;
7436 comb_vect_index++)
7438 for (vect_index = first_unempty_vect_index;
7439 vect_index < vect_length
7440 && vect_index + comb_vect_index < comb_vect_els_num;
7441 vect_index++)
7442 if (vect [vect_index] != undefined_vect_el_value
7443 && (comb_vect_start [vect_index + comb_vect_index]
7444 != undefined_vect_el_value))
7445 break;
7446 if (vect_index >= vect_length
7447 || vect_index + comb_vect_index >= comb_vect_els_num)
7448 break;
7450 /* Slot was found. */
7451 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7452 if (additional_els_num < 0)
7453 additional_els_num = 0;
7454 /* Expand comb and check vectors. */
7455 vect_el = undefined_vect_el_value;
7456 no_state_value = tab->automaton->achieved_states_num;
7457 while (additional_els_num > 0)
7459 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7460 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7461 additional_els_num--;
7463 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7464 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7465 if (VLA_HWINT_LENGTH (tab->comb_vect)
7466 < (size_t) (comb_vect_index + real_vect_length))
7467 abort ();
7468 /* Fill comb and check vectors. */
7469 for (vect_index = 0; vect_index < vect_length; vect_index++)
7470 if (vect [vect_index] != undefined_vect_el_value)
7472 if (comb_vect_start [comb_vect_index + vect_index]
7473 != undefined_vect_el_value)
7474 abort ();
7475 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7476 if (vect [vect_index] < 0)
7477 abort ();
7478 if (tab->max_comb_vect_el_value < vect [vect_index])
7479 tab->max_comb_vect_el_value = vect [vect_index];
7480 if (tab->min_comb_vect_el_value > vect [vect_index])
7481 tab->min_comb_vect_el_value = vect [vect_index];
7482 check_vect_start [comb_vect_index + vect_index] = vect_num;
7484 if (tab->max_base_vect_el_value < comb_vect_index)
7485 tab->max_base_vect_el_value = comb_vect_index;
7486 if (tab->min_base_vect_el_value > comb_vect_index)
7487 tab->min_base_vect_el_value = comb_vect_index;
7488 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7491 /* Return number of out arcs of STATE. */
7492 static int
7493 out_state_arcs_num (state)
7494 state_t state;
7496 int result;
7497 arc_t arc;
7499 result = 0;
7500 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7502 if (arc->insn == NULL)
7503 abort ();
7504 if (arc->insn->first_ainsn_with_given_equialence_num)
7505 result++;
7507 return result;
7510 /* Compare number of possible transitions from the states. */
7511 static int
7512 compare_transition_els_num (state_ptr_1, state_ptr_2)
7513 const void *state_ptr_1;
7514 const void *state_ptr_2;
7516 int transition_els_num_1;
7517 int transition_els_num_2;
7519 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7520 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7521 if (transition_els_num_1 < transition_els_num_2)
7522 return 1;
7523 else if (transition_els_num_1 == transition_els_num_2)
7524 return 0;
7525 else
7526 return -1;
7529 /* The function adds element EL_VALUE to vector VECT for a table state
7530 x AINSN. */
7531 static void
7532 add_vect_el (vect, ainsn, el_value)
7533 vla_hwint_t *vect;
7534 ainsn_t ainsn;
7535 int el_value;
7537 int equiv_class_num;
7538 int vect_index;
7540 if (ainsn == NULL)
7541 abort ();
7542 equiv_class_num = ainsn->insn_equiv_class_num;
7543 for (vect_index = VLA_HWINT_LENGTH (*vect);
7544 vect_index <= equiv_class_num;
7545 vect_index++)
7546 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7547 VLA_HWINT (*vect, equiv_class_num) = el_value;
7550 /* This is for forming vector of states of an automaton. */
7551 static vla_ptr_t output_states_vect;
7553 /* The function is called by function pass_states. The function adds
7554 STATE to `output_states_vect'. */
7555 static void
7556 add_states_vect_el (state)
7557 state_t state;
7559 VLA_PTR_ADD (output_states_vect, state);
7562 /* Form and output vectors (comb, check, base or full vector)
7563 representing transition table of AUTOMATON. */
7564 static void
7565 output_trans_table (automaton)
7566 automaton_t automaton;
7568 state_t *state_ptr;
7569 arc_t arc;
7570 vla_hwint_t transition_vect;
7572 undefined_vect_el_value = automaton->achieved_states_num;
7573 automaton->trans_table = create_state_ainsn_table (automaton);
7574 /* Create vect of pointers to states ordered by num of transitions
7575 from the state (state with the maximum num is the first). */
7576 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7577 pass_states (automaton, add_states_vect_el);
7578 qsort (VLA_PTR_BEGIN (output_states_vect),
7579 VLA_PTR_LENGTH (output_states_vect),
7580 sizeof (state_t), compare_transition_els_num);
7581 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7582 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7583 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7584 state_ptr++)
7586 VLA_HWINT_NULLIFY (transition_vect);
7587 for (arc = first_out_arc (*state_ptr);
7588 arc != NULL;
7589 arc = next_out_arc (arc))
7591 if (arc->insn == NULL)
7592 abort ();
7593 if (arc->insn->first_ainsn_with_given_equialence_num)
7594 add_vect_el (&transition_vect, arc->insn,
7595 arc->to_state->order_state_num);
7597 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7598 VLA_HWINT_BEGIN (transition_vect),
7599 VLA_HWINT_LENGTH (transition_vect));
7601 output_state_ainsn_table
7602 (automaton->trans_table, (char *) "state transitions",
7603 output_trans_full_vect_name, output_trans_comb_vect_name,
7604 output_trans_check_vect_name, output_trans_base_vect_name);
7605 VLA_PTR_DELETE (output_states_vect);
7606 VLA_HWINT_DELETE (transition_vect);
7609 /* Form and output vectors (comb, check, base or simple vect)
7610 representing alts number table of AUTOMATON. The table is state x
7611 ainsn -> number of possible alternative reservations by the
7612 ainsn. */
7613 static void
7614 output_state_alts_table (automaton)
7615 automaton_t automaton;
7617 state_t *state_ptr;
7618 arc_t arc;
7619 vla_hwint_t state_alts_vect;
7621 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7622 automaton->state_alts_table = create_state_ainsn_table (automaton);
7623 /* Create vect of pointers to states ordered by num of transitions
7624 from the state (state with the maximum num is the first). */
7625 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7626 pass_states (automaton, add_states_vect_el);
7627 qsort (VLA_PTR_BEGIN (output_states_vect),
7628 VLA_PTR_LENGTH (output_states_vect),
7629 sizeof (state_t), compare_transition_els_num);
7630 /* Create base, comb, and check vectors. */
7631 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7632 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7633 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7634 state_ptr++)
7636 VLA_HWINT_NULLIFY (state_alts_vect);
7637 for (arc = first_out_arc (*state_ptr);
7638 arc != NULL;
7639 arc = next_out_arc (arc))
7641 if (arc->insn == NULL)
7642 abort ();
7643 if (arc->insn->first_ainsn_with_given_equialence_num)
7644 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7646 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7647 VLA_HWINT_BEGIN (state_alts_vect),
7648 VLA_HWINT_LENGTH (state_alts_vect));
7650 output_state_ainsn_table
7651 (automaton->state_alts_table, (char *) "state insn alternatives",
7652 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7653 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7654 VLA_PTR_DELETE (output_states_vect);
7655 VLA_HWINT_DELETE (state_alts_vect);
7658 /* The current number of passing states to find minimal issue delay
7659 value for an ainsn and state. */
7660 static int curr_state_pass_num;
7663 /* This recursive function passes states to find minimal issue delay
7664 value for AINSN. The state being visited is STATE. The function
7665 returns minimal issue delay value for AINSN in STATE or -1 if we
7666 enter into a loop. */
7667 static int
7668 min_issue_delay_pass_states (state, ainsn)
7669 state_t state;
7670 ainsn_t ainsn;
7672 arc_t arc;
7673 int min_insn_issue_delay, insn_issue_delay;
7675 if (state->state_pass_num == curr_state_pass_num
7676 || state->min_insn_issue_delay != -1)
7677 /* We've entered into a loop or already have the correct value for
7678 given state and ainsn. */
7679 return state->min_insn_issue_delay;
7680 state->state_pass_num = curr_state_pass_num;
7681 min_insn_issue_delay = -1;
7682 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7683 if (arc->insn == ainsn)
7685 min_insn_issue_delay = 0;
7686 break;
7688 else
7690 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7691 if (insn_issue_delay != -1)
7693 if (arc->insn->insn_reserv_decl
7694 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7695 insn_issue_delay++;
7696 if (min_insn_issue_delay == -1
7697 || min_insn_issue_delay > insn_issue_delay)
7699 min_insn_issue_delay = insn_issue_delay;
7700 if (insn_issue_delay == 0)
7701 break;
7705 return min_insn_issue_delay;
7708 /* The function searches minimal issue delay value for AINSN in STATE.
7709 The function can return negative value if we can not issue AINSN. We
7710 will report about it later. */
7711 static int
7712 min_issue_delay (state, ainsn)
7713 state_t state;
7714 ainsn_t ainsn;
7716 curr_state_pass_num++;
7717 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7718 return state->min_insn_issue_delay;
7721 /* The function initiates code for finding minimal issue delay values.
7722 It should be called only once. */
7723 static void
7724 initiate_min_issue_delay_pass_states ()
7726 curr_state_pass_num = 0;
7729 /* Form and output vectors representing minimal issue delay table of
7730 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7731 the ainsn. */
7732 static void
7733 output_min_issue_delay_table (automaton)
7734 automaton_t automaton;
7736 vla_hwint_t min_issue_delay_vect;
7737 vla_hwint_t compressed_min_issue_delay_vect;
7738 vect_el_t min_delay;
7739 ainsn_t ainsn;
7740 state_t *state_ptr;
7741 int i;
7743 /* Create vect of pointers to states ordered by num of transitions
7744 from the state (state with the maximum num is the first). */
7745 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7746 pass_states (automaton, add_states_vect_el);
7747 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7748 VLA_HWINT_EXPAND (min_issue_delay_vect,
7749 VLA_HWINT_LENGTH (output_states_vect)
7750 * automaton->insn_equiv_classes_num);
7751 for (i = 0;
7752 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7753 * automaton->insn_equiv_classes_num);
7754 i++)
7755 VLA_HWINT (min_issue_delay_vect, i) = 0;
7756 automaton->max_min_delay = 0;
7757 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7758 if (ainsn->first_ainsn_with_given_equialence_num)
7760 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7761 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7762 state_ptr++)
7763 (*state_ptr)->min_insn_issue_delay = -1;
7764 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7765 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7766 state_ptr++)
7768 min_delay = min_issue_delay (*state_ptr, ainsn);
7769 if (automaton->max_min_delay < min_delay)
7770 automaton->max_min_delay = min_delay;
7771 VLA_HWINT (min_issue_delay_vect,
7772 (*state_ptr)->order_state_num
7773 * automaton->insn_equiv_classes_num
7774 + ainsn->insn_equiv_class_num) = min_delay;
7777 fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
7778 fprintf (output_file, "static const ");
7779 output_range_type (output_file, 0, automaton->max_min_delay);
7780 fprintf (output_file, " ");
7781 output_min_issue_delay_vect_name (output_file, automaton);
7782 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7783 /* Compress the vector */
7784 if (automaton->max_min_delay < 2)
7785 automaton->min_issue_delay_table_compression_factor = 8;
7786 else if (automaton->max_min_delay < 4)
7787 automaton->min_issue_delay_table_compression_factor = 4;
7788 else if (automaton->max_min_delay < 16)
7789 automaton->min_issue_delay_table_compression_factor = 2;
7790 else
7791 automaton->min_issue_delay_table_compression_factor = 1;
7792 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7793 "compressed min issue delay vector");
7794 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7795 (VLA_HWINT_LENGTH (min_issue_delay_vect)
7796 + automaton->min_issue_delay_table_compression_factor
7797 - 1)
7798 / automaton->min_issue_delay_table_compression_factor);
7799 for (i = 0;
7800 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7801 i++)
7802 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7803 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7804 VLA_HWINT (compressed_min_issue_delay_vect,
7805 i / automaton->min_issue_delay_table_compression_factor)
7806 |= (VLA_HWINT (min_issue_delay_vect, i)
7807 << (8 - (i % automaton->min_issue_delay_table_compression_factor
7808 + 1)
7809 * (8 / automaton->min_issue_delay_table_compression_factor)));
7810 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7811 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7812 fprintf (output_file, "};\n\n");
7813 VLA_PTR_DELETE (output_states_vect);
7814 VLA_HWINT_DELETE (min_issue_delay_vect);
7815 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7818 #ifndef NDEBUG
7819 /* Number of states which contains transition only by advancing cpu
7820 cycle. */
7821 static int locked_states_num;
7822 #endif
7824 /* Form and output vector representing the locked states of
7825 AUTOMATON. */
7826 static void
7827 output_dead_lock_vect (automaton)
7828 automaton_t automaton;
7830 state_t *state_ptr;
7831 arc_t arc;
7832 vla_hwint_t dead_lock_vect;
7834 /* Create vect of pointers to states ordered by num of
7835 transitions from the state (state with the maximum num is the
7836 first). */
7837 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7838 pass_states (automaton, add_states_vect_el);
7839 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7840 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7841 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7842 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7843 state_ptr++)
7845 arc = first_out_arc (*state_ptr);
7846 if (arc == NULL)
7847 abort ();
7848 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
7849 = (next_out_arc (arc) == NULL
7850 && (arc->insn->insn_reserv_decl
7851 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
7852 #ifndef NDEBUG
7853 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
7854 locked_states_num++;
7855 #endif
7857 fprintf (output_file, "/* Vector for locked state flags. */\n");
7858 fprintf (output_file, "static const ");
7859 output_range_type (output_file, 0, 1);
7860 fprintf (output_file, " ");
7861 output_dead_lock_vect_name (output_file, automaton);
7862 fprintf (output_file, "[] = {\n");
7863 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
7864 VLA_HWINT_LENGTH (dead_lock_vect));
7865 fprintf (output_file, "};\n\n");
7866 VLA_HWINT_DELETE (dead_lock_vect);
7867 VLA_PTR_DELETE (output_states_vect);
7870 /* Form and output vector representing reserved units of the states of
7871 AUTOMATON. */
7872 static void
7873 output_reserved_units_table (automaton)
7874 automaton_t automaton;
7876 state_t *curr_state_ptr;
7877 vla_hwint_t reserved_units_table;
7878 size_t state_byte_size;
7879 int i;
7881 /* Create vect of pointers to states. */
7882 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7883 pass_states (automaton, add_states_vect_el);
7884 /* Create vector. */
7885 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
7886 state_byte_size = (description->query_units_num + 7) / 8;
7887 VLA_HWINT_EXPAND (reserved_units_table,
7888 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7889 for (i = 0;
7890 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7891 i++)
7892 VLA_HWINT (reserved_units_table, i) = 0;
7893 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
7894 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7895 curr_state_ptr++)
7897 for (i = 0; i < description->units_num; i++)
7898 if (units_array [i]->query_p)
7900 if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i))
7901 VLA_HWINT (reserved_units_table,
7902 (*curr_state_ptr)->order_state_num * state_byte_size
7903 + units_array [i]->query_num / 8)
7904 += (1 << (units_array [i]->query_num % 8));
7907 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7908 fprintf (output_file, "static const ");
7909 output_range_type (output_file, 0, 255);
7910 fprintf (output_file, " ");
7911 output_reserved_units_table_name (output_file, automaton);
7912 fprintf (output_file, "[] = {\n");
7913 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
7914 VLA_HWINT_LENGTH (reserved_units_table));
7915 fprintf (output_file, "};\n\n");
7916 VLA_HWINT_DELETE (reserved_units_table);
7917 VLA_PTR_DELETE (output_states_vect);
7920 /* The function outputs all tables representing DFA(s) used for fast
7921 pipeline hazards recognition. */
7922 static void
7923 output_tables ()
7925 automaton_t automaton;
7927 #ifndef NDEBUG
7928 locked_states_num = 0;
7929 #endif
7930 initiate_min_issue_delay_pass_states ();
7931 for (automaton = description->first_automaton;
7932 automaton != NULL;
7933 automaton = automaton->next_automaton)
7935 output_translate_vect (automaton);
7936 output_trans_table (automaton);
7937 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
7938 output_state_alts_table (automaton);
7939 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7940 AUTOMATON_STATE_ALTS_MACRO_NAME);
7941 output_min_issue_delay_table (automaton);
7942 output_dead_lock_vect (automaton);
7943 if (no_minimization_flag)
7945 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
7946 output_reserved_units_table (automaton);
7947 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7948 CPU_UNITS_QUERY_MACRO_NAME);
7951 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7952 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7955 /* The function outputs definition and value of PHR interface variable
7956 `max_insn_queue_index'. Its value is not less than maximal queue
7957 length needed for the insn scheduler. */
7958 static void
7959 output_max_insn_queue_index_def ()
7961 int i, max, latency;
7962 decl_t decl;
7964 max = description->max_insn_reserv_cycles;
7965 for (i = 0; i < description->decls_num; i++)
7967 decl = description->decls [i];
7968 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7970 latency = DECL_INSN_RESERV (decl)->default_latency;
7971 if (latency > max)
7972 max = latency;
7974 else if (decl->mode == dm_bypass)
7976 latency = DECL_BYPASS (decl)->latency;
7977 if (latency > max)
7978 max = latency;
7981 for (i = 0; (1 << i) <= max; i++)
7983 if (i < 0)
7984 abort ();
7985 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
7989 /* The function outputs switch cases for insn reseravtions using
7990 function *output_automata_list_code. */
7991 static void
7992 output_insn_code_cases (output_automata_list_code)
7993 void (*output_automata_list_code) (automata_list_el_t);
7995 decl_t decl, decl2;
7996 int i, j;
7998 for (i = 0; i < description->decls_num; i++)
8000 decl = description->decls [i];
8001 if (decl->mode == dm_insn_reserv)
8002 DECL_INSN_RESERV (decl)->processed_p = FALSE;
8004 for (i = 0; i < description->decls_num; i++)
8006 decl = description->decls [i];
8007 if (decl->mode == dm_insn_reserv
8008 && !DECL_INSN_RESERV (decl)->processed_p)
8010 for (j = i; j < description->decls_num; j++)
8012 decl2 = description->decls [j];
8013 if (decl2->mode == dm_insn_reserv
8014 && (DECL_INSN_RESERV (decl2)->important_automata_list
8015 == DECL_INSN_RESERV (decl)->important_automata_list))
8017 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8018 fprintf (output_file, " case %d: /* %s */\n",
8019 DECL_INSN_RESERV (decl2)->insn_num,
8020 DECL_INSN_RESERV (decl2)->name);
8023 (*output_automata_list_code)
8024 (DECL_INSN_RESERV (decl)->important_automata_list);
8030 /* The function outputs a code for evaluation of a minimal delay of
8031 issue of insns which have reservations in given AUTOMATA_LIST. */
8032 static void
8033 output_automata_list_min_issue_delay_code (automata_list)
8034 automata_list_el_t automata_list;
8036 automata_list_el_t el;
8037 automaton_t automaton;
8039 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8041 automaton = el->automaton;
8042 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8043 output_min_issue_delay_vect_name (output_file, automaton);
8044 fprintf (output_file,
8045 (automaton->min_issue_delay_table_compression_factor != 1
8046 ? " [(" : " ["));
8047 output_translate_vect_name (output_file, automaton);
8048 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8049 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8050 output_chip_member_name (output_file, automaton);
8051 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8052 if (automaton->min_issue_delay_table_compression_factor == 1)
8053 fprintf (output_file, "];\n");
8054 else
8056 fprintf (output_file, ") / %d];\n",
8057 automaton->min_issue_delay_table_compression_factor);
8058 fprintf (output_file, " %s = (%s >> (8 - (",
8059 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8060 output_translate_vect_name (output_file, automaton);
8061 fprintf
8062 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8063 INTERNAL_INSN_CODE_NAME,
8064 automaton->min_issue_delay_table_compression_factor,
8065 8 / automaton->min_issue_delay_table_compression_factor,
8066 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8067 - 1);
8069 if (el == automata_list)
8070 fprintf (output_file, " %s = %s;\n",
8071 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8072 else
8074 fprintf (output_file, " if (%s > %s)\n",
8075 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8076 fprintf (output_file, " %s = %s;\n",
8077 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8080 fprintf (output_file, " break;\n\n");
8083 /* Output function `internal_min_issue_delay'. */
8084 static void
8085 output_internal_min_issue_delay_func ()
8087 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8088 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
8089 fprintf (output_file,
8090 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8091 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8092 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8093 CHIP_PARAMETER_NAME);
8094 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8095 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8096 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8097 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8098 fprintf (output_file,
8099 "\n default:\n %s = -1;\n break;\n }\n",
8100 RESULT_VARIABLE_NAME);
8101 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8102 fprintf (output_file, "}\n\n");
8105 /* The function outputs a code changing state after issue of insns
8106 which have reservations in given AUTOMATA_LIST. */
8107 static void
8108 output_automata_list_transition_code (automata_list)
8109 automata_list_el_t automata_list;
8111 automata_list_el_t el, next_el;
8113 fprintf (output_file, " {\n");
8114 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8115 for (el = automata_list;; el = next_el)
8117 next_el = el->next_automata_list_el;
8118 if (next_el == NULL)
8119 break;
8120 fprintf (output_file, " ");
8121 output_state_member_type (output_file, el->automaton);
8122 fprintf (output_file, " ");
8123 output_temp_chip_member_name (output_file, el->automaton);
8124 fprintf (output_file, ";\n");
8126 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8127 if (comb_vect_p (el->automaton->trans_table))
8129 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8130 output_trans_base_vect_name (output_file, el->automaton);
8131 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8132 output_chip_member_name (output_file, el->automaton);
8133 fprintf (output_file, "] + ");
8134 output_translate_vect_name (output_file, el->automaton);
8135 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8136 fprintf (output_file, " if (");
8137 output_trans_check_vect_name (output_file, el->automaton);
8138 fprintf (output_file, " [%s] != %s->",
8139 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8140 output_chip_member_name (output_file, el->automaton);
8141 fprintf (output_file, ")\n");
8142 fprintf (output_file, " return %s (%s, %s);\n",
8143 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8144 CHIP_PARAMETER_NAME);
8145 fprintf (output_file, " else\n");
8146 fprintf (output_file, " ");
8147 if (el->next_automata_list_el != NULL)
8148 output_temp_chip_member_name (output_file, el->automaton);
8149 else
8151 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8152 output_chip_member_name (output_file, el->automaton);
8154 fprintf (output_file, " = ");
8155 output_trans_comb_vect_name (output_file, el->automaton);
8156 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8158 else
8160 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8161 output_trans_full_vect_name (output_file, el->automaton);
8162 fprintf (output_file, " [");
8163 output_translate_vect_name (output_file, el->automaton);
8164 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8165 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8166 output_chip_member_name (output_file, el->automaton);
8167 fprintf (output_file, " * %d];\n",
8168 el->automaton->insn_equiv_classes_num);
8169 fprintf (output_file, " if (%s >= %d)\n",
8170 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8171 fprintf (output_file, " return %s (%s, %s);\n",
8172 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8173 CHIP_PARAMETER_NAME);
8174 fprintf (output_file, " else\n ");
8175 if (el->next_automata_list_el != NULL)
8176 output_temp_chip_member_name (output_file, el->automaton);
8177 else
8179 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8180 output_chip_member_name (output_file, el->automaton);
8182 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8184 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8185 for (el = automata_list;; el = next_el)
8187 next_el = el->next_automata_list_el;
8188 if (next_el == NULL)
8189 break;
8190 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8191 output_chip_member_name (output_file, el->automaton);
8192 fprintf (output_file, " = ");
8193 output_temp_chip_member_name (output_file, el->automaton);
8194 fprintf (output_file, ";\n");
8196 fprintf (output_file, " return -1;\n");
8197 fprintf (output_file, " }\n");
8200 /* Output function `internal_state_transition'. */
8201 static void
8202 output_internal_trans_func ()
8204 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8205 INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
8206 fprintf (output_file,
8207 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8208 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8209 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
8210 CHIP_NAME, CHIP_PARAMETER_NAME);
8211 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8212 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8213 output_insn_code_cases (output_automata_list_transition_code);
8214 fprintf (output_file, "\n default:\n return -1;\n }\n");
8215 fprintf (output_file, "}\n\n");
8218 /* Output code
8220 if (insn != 0)
8222 insn_code = dfa_insn_code (insn);
8223 if (insn_code > DFA__ADVANCE_CYCLE)
8224 return code;
8226 else
8227 insn_code = DFA__ADVANCE_CYCLE;
8229 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8230 code denotes CODE. */
8231 static void
8232 output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
8233 const char *insn_name;
8234 const char *insn_code_name;
8235 int code;
8237 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8238 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8239 DFA_INSN_CODE_FUNC_NAME, insn_name);
8240 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8241 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8242 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8243 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8247 /* The function outputs function `dfa_insn_code'. */
8248 static void
8249 output_dfa_insn_code_func ()
8251 fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n");
8252 fprintf (output_file, "static int %s PARAMS ((rtx));\n",
8253 DFA_INSN_CODE_FUNC_NAME);
8254 fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
8255 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
8256 fprintf (output_file, "{\n int %s;\n int %s;\n\n",
8257 INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
8258 fprintf (output_file, " if (INSN_UID (%s) >= %s)\n {\n",
8259 INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8260 fprintf (output_file, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
8261 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8262 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
8263 fprintf (output_file, " %s = xrealloc (%s, %s * sizeof (int));\n",
8264 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8265 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8266 fprintf (output_file,
8267 " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
8268 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8269 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8270 TEMPORARY_VARIABLE_NAME);
8271 fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
8272 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8273 INSN_PARAMETER_NAME);
8274 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8275 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8276 fprintf (output_file, " %s [INSN_UID (%s)] = %s;\n",
8277 DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME,
8278 INTERNAL_INSN_CODE_NAME);
8279 fprintf (output_file, " }\n return %s;\n}\n\n",
8280 INTERNAL_INSN_CODE_NAME);
8283 /* The function outputs PHR interface function `state_transition'. */
8284 static void
8285 output_trans_func ()
8287 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8288 TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8289 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8290 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8291 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8292 INTERNAL_INSN_CODE_NAME, -1);
8293 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8294 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8297 /* The function outputs a code for evaluation of alternative states
8298 number for insns which have reservations in given AUTOMATA_LIST. */
8299 static void
8300 output_automata_list_state_alts_code (automata_list)
8301 automata_list_el_t automata_list;
8303 automata_list_el_t el;
8304 automaton_t automaton;
8306 fprintf (output_file, " {\n");
8307 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8308 if (comb_vect_p (el->automaton->state_alts_table))
8310 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8311 break;
8313 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8315 automaton = el->automaton;
8316 if (comb_vect_p (automaton->state_alts_table))
8318 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8319 output_state_alts_base_vect_name (output_file, automaton);
8320 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8321 output_chip_member_name (output_file, automaton);
8322 fprintf (output_file, "] + ");
8323 output_translate_vect_name (output_file, automaton);
8324 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8325 fprintf (output_file, " if (");
8326 output_state_alts_check_vect_name (output_file, automaton);
8327 fprintf (output_file, " [%s] != %s->",
8328 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8329 output_chip_member_name (output_file, automaton);
8330 fprintf (output_file, ")\n");
8331 fprintf (output_file, " return 0;\n");
8332 fprintf (output_file, " else\n");
8333 fprintf (output_file,
8334 (el == automata_list
8335 ? " %s = " : " %s += "),
8336 RESULT_VARIABLE_NAME);
8337 output_state_alts_comb_vect_name (output_file, automaton);
8338 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8340 else
8342 fprintf (output_file,
8343 (el == automata_list
8344 ? "\n %s = " : " %s += "),
8345 RESULT_VARIABLE_NAME);
8346 output_state_alts_full_vect_name (output_file, automaton);
8347 fprintf (output_file, " [");
8348 output_translate_vect_name (output_file, automaton);
8349 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8350 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8351 output_chip_member_name (output_file, automaton);
8352 fprintf (output_file, " * %d];\n",
8353 automaton->insn_equiv_classes_num);
8356 fprintf (output_file, " break;\n }\n\n");
8359 /* Output function `internal_state_alts'. */
8360 static void
8361 output_internal_state_alts_func ()
8363 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8364 INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8365 fprintf (output_file,
8366 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8367 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8368 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8369 CHIP_PARAMETER_NAME);
8370 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8371 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8372 output_insn_code_cases (output_automata_list_state_alts_code);
8373 fprintf (output_file,
8374 "\n default:\n %s = 0;\n break;\n }\n",
8375 RESULT_VARIABLE_NAME);
8376 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8377 fprintf (output_file, "}\n\n");
8380 /* The function outputs PHR interface function `state_alts'. */
8381 static void
8382 output_state_alts_func ()
8384 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8385 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8386 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8387 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8388 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8389 INTERNAL_INSN_CODE_NAME, 0);
8390 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8391 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8394 /* Output function `min_issue_delay'. */
8395 static void
8396 output_min_issue_delay_func ()
8398 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8399 MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8400 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8401 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8402 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8403 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8404 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8405 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8406 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8407 fprintf (output_file, " }\n else\n %s = %s;\n",
8408 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8409 fprintf (output_file, "\n return %s (%s, %s);\n",
8410 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8411 STATE_NAME);
8412 fprintf (output_file, "}\n\n");
8415 /* Output function `internal_dead_lock'. */
8416 static void
8417 output_internal_dead_lock_func ()
8419 automaton_t automaton;
8421 fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8422 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8423 fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8424 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8425 CHIP_PARAMETER_NAME);
8426 fprintf (output_file, "{\n");
8427 for (automaton = description->first_automaton;
8428 automaton != NULL;
8429 automaton = automaton->next_automaton)
8431 fprintf (output_file, " if (");
8432 output_dead_lock_vect_name (output_file, automaton);
8433 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8434 output_chip_member_name (output_file, automaton);
8435 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8437 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8440 /* The function outputs PHR interface function `state_dead_lock_p'. */
8441 static void
8442 output_dead_lock_func ()
8444 fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8445 DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8446 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8447 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8450 /* Output function `internal_reset'. */
8451 static void
8452 output_internal_reset_func ()
8454 fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8455 INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8456 fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8457 INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8458 CHIP_NAME, CHIP_PARAMETER_NAME);
8459 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8460 CHIP_PARAMETER_NAME, CHIP_NAME);
8463 /* The function outputs PHR interface function `state_size'. */
8464 static void
8465 output_size_func ()
8467 fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8468 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8471 /* The function outputs PHR interface function `state_reset'. */
8472 static void
8473 output_reset_func ()
8475 fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8476 RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8477 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8478 STATE_NAME);
8481 /* Output function `min_insn_conflict_delay'. */
8482 static void
8483 output_min_insn_conflict_delay_func ()
8485 fprintf (output_file,
8486 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8487 MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8488 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8489 STATE_TYPE_NAME, STATE_NAME,
8490 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8491 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8492 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8493 INTERNAL_INSN2_CODE_NAME);
8494 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8495 INTERNAL_INSN_CODE_NAME, 0);
8496 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8497 INTERNAL_INSN2_CODE_NAME, 0);
8498 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8499 CHIP_NAME, STATE_NAME, CHIP_NAME);
8500 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8501 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8502 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8503 fprintf (output_file, " return %s (%s, &%s);\n",
8504 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8505 CHIP_NAME);
8506 fprintf (output_file, "}\n\n");
8509 /* Output function `internal_insn_latency'. */
8510 static void
8511 output_internal_insn_latency_func ()
8513 decl_t decl;
8514 struct bypass_decl *bypass;
8515 int i;
8517 fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8518 INTERNAL_INSN_LATENCY_FUNC_NAME);
8519 fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8520 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8521 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8522 INSN2_PARAMETER_NAME);
8523 fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
8524 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8525 fprintf (output_file,
8526 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
8527 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8528 fprintf (output_file, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8529 for (i = 0; i < description->decls_num; i++)
8531 decl = description->decls [i];
8532 if (decl->mode == dm_insn_reserv)
8534 fprintf (output_file, " case %d:\n",
8535 DECL_INSN_RESERV (decl)->insn_num);
8536 if (DECL_INSN_RESERV (decl)->bypass_list == NULL)
8537 fprintf (output_file, " return (%s != %s ? %d : 0);\n",
8538 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8539 DECL_INSN_RESERV (decl)->default_latency);
8540 else
8542 fprintf (output_file, " switch (%s)\n {\n",
8543 INTERNAL_INSN2_CODE_NAME);
8544 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8545 bypass != NULL;
8546 bypass = bypass->next)
8548 fprintf (output_file, " case %d:\n",
8549 bypass->in_insn_reserv->insn_num);
8550 if (bypass->bypass_guard_name == NULL)
8551 fprintf (output_file, " return %d;\n",
8552 bypass->latency);
8553 else
8554 fprintf (output_file,
8555 " return (%s (%s, %s) ? %d : %d);\n",
8556 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8557 INSN2_PARAMETER_NAME, bypass->latency,
8558 DECL_INSN_RESERV (decl)->default_latency);
8560 fprintf (output_file, " default:\n");
8561 fprintf (output_file,
8562 " return (%s != %s ? %d : 0);\n }\n",
8563 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8564 DECL_INSN_RESERV (decl)->default_latency);
8569 fprintf (output_file, " default:\n return 0;\n }\n}\n\n");
8572 /* The function outputs PHR interface function `insn_latency'. */
8573 static void
8574 output_insn_latency_func ()
8576 fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
8577 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8578 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8579 fprintf (output_file, "{\n int %s, %s;\n",
8580 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8581 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8582 INTERNAL_INSN_CODE_NAME, 0);
8583 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8584 INTERNAL_INSN2_CODE_NAME, 0);
8585 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8586 INTERNAL_INSN_LATENCY_FUNC_NAME,
8587 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8588 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8591 /* The function outputs PHR interface function `print_reservation'. */
8592 static void
8593 output_print_reservation_func ()
8595 decl_t decl;
8596 int i;
8598 fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
8599 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8600 INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
8601 INSN_PARAMETER_NAME);
8602 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8603 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8604 fprintf (output_file, " %s = %s (%s);\n",
8605 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8606 INSN_PARAMETER_NAME);
8607 fprintf (output_file, " if (%s > %s)\n",
8608 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8609 fprintf (output_file, " {\n fprintf (%s, \"%s\");\n",
8610 FILE_PARAMETER_NAME, NOTHING_NAME);
8611 fprintf (output_file, " return;\n }\n");
8612 fprintf (output_file, " }\n else\n");
8613 fprintf (output_file,
8614 " {\n fprintf (%s, \"%s\");\n return;\n }\n",
8615 FILE_PARAMETER_NAME, NOTHING_NAME);
8616 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8617 for (i = 0; i < description->decls_num; i++)
8619 decl = description->decls [i];
8620 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8622 fprintf (output_file,
8623 " case %d:\n", DECL_INSN_RESERV (decl)->insn_num);
8624 fprintf (output_file,
8625 " fprintf (%s, \"%s\");\n break;\n",
8626 FILE_PARAMETER_NAME,
8627 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8628 finish_regexp_representation ();
8631 fprintf (output_file, " default:\n fprintf (%s, \"%s\");\n }\n",
8632 FILE_PARAMETER_NAME, NOTHING_NAME);
8633 fprintf (output_file, "}\n\n");
8636 /* The following function is used to sort unit declaration by their
8637 names. */
8638 static int
8639 units_cmp (unit1, unit2)
8640 const void *unit1, *unit2;
8642 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8643 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8645 return strcmp (u1->name, u2->name);
8648 /* The following macro value is name of struct containing unit name
8649 and unit code. */
8650 #define NAME_CODE_STRUCT_NAME "name_code"
8652 /* The following macro value is name of table of struct name_code. */
8653 #define NAME_CODE_TABLE_NAME "name_code_table"
8655 /* The following macro values are member names for struct name_code. */
8656 #define NAME_MEMBER_NAME "name"
8657 #define CODE_MEMBER_NAME "code"
8659 /* The following macro values are local variable names for function
8660 `get_cpu_unit_code'. */
8661 #define CMP_VARIABLE_NAME "cmp"
8662 #define LOW_VARIABLE_NAME "l"
8663 #define MIDDLE_VARIABLE_NAME "m"
8664 #define HIGH_VARIABLE_NAME "h"
8666 /* The following function outputs function to obtain internal cpu unit
8667 code by the cpu unit name. */
8668 static void
8669 output_get_cpu_unit_code_func ()
8671 int i;
8672 unit_decl_t *units;
8674 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8675 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8676 CPU_UNIT_NAME_PARAMETER_NAME);
8677 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8678 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8679 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8680 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8681 fprintf (output_file, " static struct %s %s [] =\n {\n",
8682 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8683 units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
8684 * description->units_num);
8685 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8686 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8687 for (i = 0; i < description->units_num; i++)
8688 if (units [i]->query_p)
8689 fprintf (output_file, " {\"%s\", %d},\n",
8690 units[i]->name, units[i]->query_num);
8691 fprintf (output_file, " };\n\n");
8692 fprintf (output_file, " /* The following is binary search: */\n");
8693 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8694 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8695 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8696 fprintf (output_file, " while (%s <= %s)\n {\n",
8697 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8698 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8699 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8700 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8701 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8702 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8703 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8704 fprintf (output_file, " %s = %s - 1;\n",
8705 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8706 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8707 fprintf (output_file, " %s = %s + 1;\n",
8708 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8709 fprintf (output_file, " else\n");
8710 fprintf (output_file, " return %s [%s].%s;\n }\n",
8711 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8712 fprintf (output_file, " return -1;\n}\n\n");
8713 free (units);
8716 /* The following function outputs function to check reservation of cpu
8717 unit (its internal code will be passed as the function argument) in
8718 given cpu state. */
8719 static void
8720 output_cpu_unit_reservation_p ()
8722 automaton_t automaton;
8724 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8725 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8726 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8727 CPU_CODE_PARAMETER_NAME);
8728 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8729 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8730 description->query_units_num);
8731 for (automaton = description->first_automaton;
8732 automaton != NULL;
8733 automaton = automaton->next_automaton)
8735 fprintf (output_file, " if ((");
8736 output_reserved_units_table_name (output_file, automaton);
8737 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8738 output_chip_member_name (output_file, automaton);
8739 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8740 (description->query_units_num + 7) / 8,
8741 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8742 fprintf (output_file, " return 1;\n");
8744 fprintf (output_file, " return 0;\n}\n\n");
8747 /* The function outputs PHR interface function `dfa_start'. */
8748 static void
8749 output_dfa_start_func ()
8751 fprintf (output_file,
8752 "void\n%s ()\n{\n int %s;\n\n %s = get_max_uid ();\n",
8753 DFA_START_FUNC_NAME, I_VARIABLE_NAME,
8754 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8755 fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
8756 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8757 fprintf (output_file,
8758 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8759 I_VARIABLE_NAME, I_VARIABLE_NAME,
8760 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8761 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8764 /* The function outputs PHR interface function `dfa_finish'. */
8765 static void
8766 output_dfa_finish_func ()
8768 fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
8769 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8774 /* The page contains code for output description file (readable
8775 representation of original description and generated DFA(s). */
8777 /* The function outputs string representation of IR reservation. */
8778 static void
8779 output_regexp (regexp)
8780 regexp_t regexp;
8782 fprintf (output_description_file, "%s", regexp_representation (regexp));
8783 finish_regexp_representation ();
8786 /* Output names of units in LIST separated by comma. */
8787 static void
8788 output_unit_set_el_list (list)
8789 unit_set_el_t list;
8791 unit_set_el_t el;
8793 for (el = list; el != NULL; el = el->next_unit_set_el)
8795 if (el != list)
8796 fprintf (output_description_file, ",");
8797 fprintf (output_description_file, "%s", el->unit_decl->name);
8801 /* The function outputs string representation of IR define_reservation
8802 and define_insn_reservation. */
8803 static void
8804 output_description ()
8806 decl_t decl;
8807 int i;
8809 for (i = 0; i < description->decls_num; i++)
8811 decl = description->decls [i];
8812 if (decl->mode == dm_unit)
8814 if (DECL_UNIT (decl)->excl_list != NULL)
8816 fprintf (output_description_file, "unit %s exlusion_set: ",
8817 DECL_UNIT (decl)->name);
8818 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8819 fprintf (output_description_file, "\n");
8821 if (DECL_UNIT (decl)->presence_list != NULL)
8823 fprintf (output_description_file, "unit %s presence_set: ",
8824 DECL_UNIT (decl)->name);
8825 output_unit_set_el_list (DECL_UNIT (decl)->presence_list);
8826 fprintf (output_description_file, "\n");
8828 if (DECL_UNIT (decl)->absence_list != NULL)
8830 fprintf (output_description_file, "unit %s absence_set: ",
8831 DECL_UNIT (decl)->name);
8832 output_unit_set_el_list (DECL_UNIT (decl)->absence_list);
8833 fprintf (output_description_file, "\n");
8837 fprintf (output_description_file, "\n");
8838 for (i = 0; i < description->decls_num; i++)
8840 decl = description->decls [i];
8841 if (decl->mode == dm_reserv)
8843 fprintf (output_description_file, "reservation ");
8844 fprintf (output_description_file, DECL_RESERV (decl)->name);
8845 fprintf (output_description_file, ": ");
8846 output_regexp (DECL_RESERV (decl)->regexp);
8847 fprintf (output_description_file, "\n");
8849 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8851 fprintf (output_description_file, "insn reservation %s ",
8852 DECL_INSN_RESERV (decl)->name);
8853 print_rtl (output_description_file,
8854 DECL_INSN_RESERV (decl)->condexp);
8855 fprintf (output_description_file, ": ");
8856 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8857 fprintf (output_description_file, "\n");
8859 else if (decl->mode == dm_bypass)
8860 fprintf (output_description_file, "bypass %d %s %s\n",
8861 DECL_BYPASS (decl)->latency,
8862 DECL_BYPASS (decl)->out_insn_name,
8863 DECL_BYPASS (decl)->in_insn_name);
8865 fprintf (output_description_file, "\n\f\n");
8868 /* The function outputs name of AUTOMATON. */
8869 static void
8870 output_automaton_name (f, automaton)
8871 FILE *f;
8872 automaton_t automaton;
8874 if (automaton->corresponding_automaton_decl == NULL)
8875 fprintf (f, "#%d", automaton->automaton_order_num);
8876 else
8877 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8880 /* Maximal length of line for pretty printing into description
8881 file. */
8882 #define MAX_LINE_LENGTH 70
8884 /* The function outputs units name belonging to AUTOMATON. */
8885 static void
8886 output_automaton_units (automaton)
8887 automaton_t automaton;
8889 decl_t decl;
8890 char *name;
8891 int curr_line_length;
8892 int there_is_an_automaton_unit;
8893 int i;
8895 fprintf (output_description_file, "\n Coresponding units:\n");
8896 fprintf (output_description_file, " ");
8897 curr_line_length = 4;
8898 there_is_an_automaton_unit = 0;
8899 for (i = 0; i < description->decls_num; i++)
8901 decl = description->decls [i];
8902 if (decl->mode == dm_unit
8903 && (DECL_UNIT (decl)->corresponding_automaton_num
8904 == automaton->automaton_order_num))
8906 there_is_an_automaton_unit = 1;
8907 name = DECL_UNIT (decl)->name;
8908 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8910 curr_line_length = strlen (name) + 4;
8911 fprintf (output_description_file, "\n ");
8913 else
8915 curr_line_length += strlen (name) + 1;
8916 fprintf (output_description_file, " ");
8918 fprintf (output_description_file, name);
8921 if (!there_is_an_automaton_unit)
8922 fprintf (output_description_file, "<None>");
8923 fprintf (output_description_file, "\n\n");
8926 /* The following variable is used for forming array of all possible cpu unit
8927 reservations described by the current DFA state. */
8928 static vla_ptr_t state_reservs;
8930 /* The function forms `state_reservs' for STATE. */
8931 static void
8932 add_state_reservs (state)
8933 state_t state;
8935 alt_state_t curr_alt_state;
8936 reserv_sets_t reservs;
8938 if (state->component_states != NULL)
8939 for (curr_alt_state = state->component_states;
8940 curr_alt_state != NULL;
8941 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8942 add_state_reservs (curr_alt_state->state);
8943 else
8945 reservs = state->reservs;
8946 VLA_PTR_ADD (state_reservs, reservs);
8950 /* The function outputs readable represenatation of all out arcs of
8951 STATE. */
8952 static void
8953 output_state_arcs (state)
8954 state_t state;
8956 arc_t arc;
8957 ainsn_t ainsn;
8958 char *insn_name;
8959 int curr_line_length;
8961 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8963 ainsn = arc->insn;
8964 if (!ainsn->first_insn_with_same_reservs)
8965 abort ();
8966 fprintf (output_description_file, " ");
8967 curr_line_length = 7;
8968 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8971 insn_name = ainsn->insn_reserv_decl->name;
8972 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8974 if (ainsn != arc->insn)
8976 fprintf (output_description_file, ",\n ");
8977 curr_line_length = strlen (insn_name) + 6;
8979 else
8980 curr_line_length += strlen (insn_name);
8982 else
8984 curr_line_length += strlen (insn_name);
8985 if (ainsn != arc->insn)
8987 curr_line_length += 2;
8988 fprintf (output_description_file, ", ");
8991 fprintf (output_description_file, insn_name);
8992 ainsn = ainsn->next_same_reservs_insn;
8994 while (ainsn != NULL);
8995 fprintf (output_description_file, " %d (%d)\n",
8996 arc->to_state->order_state_num, arc->state_alts);
8998 fprintf (output_description_file, "\n");
9001 /* The following function is used for sorting possible cpu unit
9002 reservation of a DFA state. */
9003 static int
9004 state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
9005 const void *reservs_ptr_1;
9006 const void *reservs_ptr_2;
9008 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9009 *(reserv_sets_t *) reservs_ptr_2);
9012 /* The following function is used for sorting possible cpu unit
9013 reservation of a DFA state. */
9014 static void
9015 remove_state_duplicate_reservs ()
9017 reserv_sets_t *reservs_ptr;
9018 reserv_sets_t *last_formed_reservs_ptr;
9020 last_formed_reservs_ptr = NULL;
9021 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9022 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9023 reservs_ptr++)
9024 if (last_formed_reservs_ptr == NULL)
9025 last_formed_reservs_ptr = reservs_ptr;
9026 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9028 ++last_formed_reservs_ptr;
9029 *last_formed_reservs_ptr = *reservs_ptr;
9031 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9034 /* The following function output readable representation of DFA(s)
9035 state used for fast recognition of pipeline hazards. State is
9036 described by possible (current and scehduled) cpu unit
9037 reservations. */
9038 static void
9039 output_state (state)
9040 state_t state;
9042 reserv_sets_t *reservs_ptr;
9044 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9045 fprintf (output_description_file, " State #%d", state->order_state_num);
9046 fprintf (output_description_file,
9047 state->new_cycle_p ? " (new cycle)\n" : "\n");
9048 add_state_reservs (state);
9049 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9050 sizeof (reserv_sets_t), state_reservs_cmp);
9051 remove_state_duplicate_reservs ();
9052 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9053 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9054 reservs_ptr++)
9056 fprintf (output_description_file, " ");
9057 output_reserv_sets (output_description_file, *reservs_ptr);
9058 fprintf (output_description_file, "\n");
9060 fprintf (output_description_file, "\n");
9061 output_state_arcs (state);
9062 VLA_PTR_DELETE (state_reservs);
9065 /* The following function output readable representation of
9066 DFAs used for fast recognition of pipeline hazards. */
9067 static void
9068 output_automaton_descriptions ()
9070 automaton_t automaton;
9072 for (automaton = description->first_automaton;
9073 automaton != NULL;
9074 automaton = automaton->next_automaton)
9076 fprintf (output_description_file, "\nAutomaton ");
9077 output_automaton_name (output_description_file, automaton);
9078 fprintf (output_description_file, "\n");
9079 output_automaton_units (automaton);
9080 pass_states (automaton, output_state);
9086 /* The page contains top level function for generation DFA(s) used for
9087 PHR. */
9089 /* The function outputs statistics about work of different phases of
9090 DFA generator. */
9091 static void
9092 output_statistics (f)
9093 FILE *f;
9095 automaton_t automaton;
9096 #ifndef NDEBUG
9097 int transition_comb_vect_els = 0;
9098 int transition_full_vect_els = 0;
9099 int state_alts_comb_vect_els = 0;
9100 int state_alts_full_vect_els = 0;
9101 int min_issue_delay_vect_els = 0;
9102 #endif
9104 for (automaton = description->first_automaton;
9105 automaton != NULL;
9106 automaton = automaton->next_automaton)
9108 fprintf (f, "\nAutomaton ");
9109 output_automaton_name (f, automaton);
9110 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9111 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9112 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9113 automaton->DFA_states_num, automaton->DFA_arcs_num);
9114 if (!no_minimization_flag)
9115 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9116 automaton->minimal_DFA_states_num,
9117 automaton->minimal_DFA_arcs_num);
9118 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9119 description->insns_num, automaton->insn_equiv_classes_num);
9120 #ifndef NDEBUG
9121 fprintf
9122 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9123 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9124 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9125 (comb_vect_p (automaton->trans_table)
9126 ? "use comb vect" : "use simple vect"));
9127 fprintf
9128 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9129 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9130 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9131 (comb_vect_p (automaton->state_alts_table)
9132 ? "use comb vect" : "use simple vect"));
9133 fprintf
9134 (f, "%5ld min delay table els, compression factor %d\n",
9135 (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num,
9136 automaton->min_issue_delay_table_compression_factor);
9137 transition_comb_vect_els
9138 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9139 transition_full_vect_els
9140 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9141 state_alts_comb_vect_els
9142 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9143 state_alts_full_vect_els
9144 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9145 min_issue_delay_vect_els
9146 += automaton->DFA_states_num * automaton->insn_equiv_classes_num;
9147 #endif
9149 #ifndef NDEBUG
9150 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9151 allocated_states_num, allocated_arcs_num);
9152 fprintf (f, "%5d all allocated alternative states\n",
9153 allocated_alt_states_num);
9154 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9155 transition_comb_vect_els, transition_full_vect_els);
9156 fprintf
9157 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9158 state_alts_comb_vect_els, state_alts_full_vect_els);
9159 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9160 fprintf (f, "%5d locked states num\n", locked_states_num);
9161 #endif
9164 /* The function output times of work of different phases of DFA
9165 generator. */
9166 static void
9167 output_time_statistics (f)
9168 FILE *f;
9170 fprintf (f, "\n transformation: ");
9171 print_active_time (f, transform_time);
9172 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9173 print_active_time (f, NDFA_time);
9174 if (ndfa_flag)
9176 fprintf (f, ", NDFA -> DFA: ");
9177 print_active_time (f, NDFA_to_DFA_time);
9179 fprintf (f, "\n DFA minimization: ");
9180 print_active_time (f, minimize_time);
9181 fprintf (f, ", making insn equivalence: ");
9182 print_active_time (f, equiv_time);
9183 fprintf (f, "\n all automaton generation: ");
9184 print_active_time (f, automaton_generation_time);
9185 fprintf (f, ", output: ");
9186 print_active_time (f, output_time);
9187 fprintf (f, "\n");
9190 /* The function generates DFA (deterministic finate state automaton)
9191 for fast recognition of pipeline hazards. No errors during
9192 checking must be fixed before this function call. */
9193 static void
9194 generate ()
9196 automata_num = split_argument;
9197 if (description->units_num < automata_num)
9198 automata_num = description->units_num;
9199 initiate_states ();
9200 initiate_arcs ();
9201 initiate_automata_lists ();
9202 initiate_pass_states ();
9203 initiate_excl_sets ();
9204 initiate_presence_absence_sets ();
9205 automaton_generation_time = create_ticker ();
9206 create_automata ();
9207 ticker_off (&automaton_generation_time);
9212 /* The following function creates insn attribute whose values are
9213 number alternatives in insn reservations. */
9214 static void
9215 make_insn_alts_attr ()
9217 int i, insn_num;
9218 decl_t decl;
9219 rtx condexp;
9221 condexp = rtx_alloc (COND);
9222 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9223 XEXP (condexp, 1) = make_numeric_value (0);
9224 for (i = insn_num = 0; i < description->decls_num; i++)
9226 decl = description->decls [i];
9227 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9229 XVECEXP (condexp, 0, 2 * insn_num)
9230 = DECL_INSN_RESERV (decl)->condexp;
9231 XVECEXP (condexp, 0, 2 * insn_num + 1)
9232 = make_numeric_value
9233 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9234 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9235 ->transformed_regexp)->regexps_num);
9236 insn_num++;
9239 if (description->insns_num != insn_num + 1)
9240 abort ();
9241 make_internal_attr (attr_printf (sizeof ("*")
9242 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9243 "*%s", INSN_ALTS_FUNC_NAME),
9244 condexp, 0);
9249 /* The following function creates attribute which is order number of
9250 insn in pipeline hazard description translator. */
9251 static void
9252 make_internal_dfa_insn_code_attr ()
9254 int i, insn_num;
9255 decl_t decl;
9256 rtx condexp;
9258 condexp = rtx_alloc (COND);
9259 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9260 XEXP (condexp, 1)
9261 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9262 ->insn_num + 1);
9263 for (i = insn_num = 0; i < description->decls_num; i++)
9265 decl = description->decls [i];
9266 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9268 XVECEXP (condexp, 0, 2 * insn_num)
9269 = DECL_INSN_RESERV (decl)->condexp;
9270 XVECEXP (condexp, 0, 2 * insn_num + 1)
9271 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9272 insn_num++;
9275 if (description->insns_num != insn_num + 1)
9276 abort ();
9277 make_internal_attr
9278 (attr_printf (sizeof ("*")
9279 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9280 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9281 condexp, 0);
9286 /* The following function creates attribute which order number of insn
9287 in pipeline hazard description translator. */
9288 static void
9289 make_default_insn_latency_attr ()
9291 int i, insn_num;
9292 decl_t decl;
9293 rtx condexp;
9295 condexp = rtx_alloc (COND);
9296 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9297 XEXP (condexp, 1) = make_numeric_value (0);
9298 for (i = insn_num = 0; i < description->decls_num; i++)
9300 decl = description->decls [i];
9301 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9303 XVECEXP (condexp, 0, 2 * insn_num)
9304 = DECL_INSN_RESERV (decl)->condexp;
9305 XVECEXP (condexp, 0, 2 * insn_num + 1)
9306 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9307 insn_num++;
9310 if (description->insns_num != insn_num + 1)
9311 abort ();
9312 make_internal_attr (attr_printf (sizeof ("*")
9313 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9314 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9315 condexp, 0);
9320 /* The following function creates attribute which returns 1 if given
9321 output insn has bypassing and 0 otherwise. */
9322 static void
9323 make_bypass_attr ()
9325 int i, bypass_insn;
9326 int bypass_insns_num = 0;
9327 decl_t decl;
9328 rtx result_rtx;
9330 for (i = 0; i < description->decls_num; i++)
9332 decl = description->decls [i];
9333 if (decl->mode == dm_insn_reserv
9334 && DECL_INSN_RESERV (decl)->condexp != NULL
9335 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9336 bypass_insns_num++;
9338 if (bypass_insns_num == 0)
9339 result_rtx = make_numeric_value (0);
9340 else
9342 result_rtx = rtx_alloc (COND);
9343 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9344 XEXP (result_rtx, 1) = make_numeric_value (0);
9346 for (i = bypass_insn = 0; i < description->decls_num; i++)
9348 decl = description->decls [i];
9349 if (decl->mode == dm_insn_reserv
9350 && DECL_INSN_RESERV (decl)->condexp != NULL
9351 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9353 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9354 = DECL_INSN_RESERV (decl)->condexp;
9355 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9356 = make_numeric_value (1);
9357 bypass_insn++;
9361 make_internal_attr (attr_printf (sizeof ("*")
9362 + strlen (BYPASS_P_FUNC_NAME) + 1,
9363 "*%s", BYPASS_P_FUNC_NAME),
9364 result_rtx, 0);
9369 /* This page mainly contains top level functions of pipeline hazards
9370 description translator. */
9372 /* The following macro value is suffix of name of description file of
9373 pipeline hazards description translator. */
9374 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9376 /* The function returns suffix of given file name. The returned
9377 string can not be changed. */
9378 static const char *
9379 file_name_suffix (file_name)
9380 const char *file_name;
9382 const char *last_period;
9384 for (last_period = NULL; *file_name != '\0'; file_name++)
9385 if (*file_name == '.')
9386 last_period = file_name;
9387 return (last_period == NULL ? file_name : last_period);
9390 /* The function returns base name of given file name, i.e. pointer to
9391 first char after last `/' (or `\' for WIN32) in given file name,
9392 given file name itself if the directory name is absent. The
9393 returned string can not be changed. */
9394 static const char *
9395 base_file_name (file_name)
9396 const char *file_name;
9398 int directory_name_length;
9400 directory_name_length = strlen (file_name);
9401 #ifdef WIN32
9402 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9403 && file_name[directory_name_length] != '\\')
9404 #else
9405 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9406 #endif
9407 directory_name_length--;
9408 return file_name + directory_name_length + 1;
9411 /* The following is top level function to initialize the work of
9412 pipeline hazards description translator. */
9413 void
9414 initiate_automaton_gen (argc, argv)
9415 int argc;
9416 char **argv;
9418 const char *base_name;
9419 int i;
9421 ndfa_flag = 0;
9422 split_argument = 0; /* default value */
9423 no_minimization_flag = 0;
9424 time_flag = 0;
9425 v_flag = 0;
9426 w_flag = 0;
9427 for (i = 2; i < argc; i++)
9428 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9429 no_minimization_flag = 1;
9430 else if (strcmp (argv [i], TIME_OPTION) == 0)
9431 time_flag = 1;
9432 else if (strcmp (argv [i], V_OPTION) == 0)
9433 v_flag = 1;
9434 else if (strcmp (argv [i], W_OPTION) == 0)
9435 w_flag = 1;
9436 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9437 ndfa_flag = 1;
9438 else if (strcmp (argv [i], "-split") == 0)
9440 if (i + 1 >= argc)
9441 fatal ("-split has no argument.");
9442 fatal ("option `-split' has not been implemented yet\n");
9443 /* split_argument = atoi (argument_vect [i + 1]); */
9445 VLA_PTR_CREATE (decls, 150, "decls");
9446 /* Initialize IR storage. */
9447 obstack_init (&irp);
9448 initiate_automaton_decl_table ();
9449 initiate_insn_decl_table ();
9450 initiate_decl_table ();
9451 output_file = stdout;
9452 output_description_file = NULL;
9453 base_name = base_file_name (argv[1]);
9454 obstack_grow (&irp, base_name,
9455 strlen (base_name) - strlen (file_name_suffix (base_name)));
9456 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9457 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9458 obstack_1grow (&irp, '\0');
9459 output_description_file_name = obstack_base (&irp);
9460 obstack_finish (&irp);
9463 /* The following function checks existence at least one arc marked by
9464 each insn. */
9465 static void
9466 check_automata_insn_issues ()
9468 automaton_t automaton;
9469 ainsn_t ainsn, reserv_ainsn;
9471 for (automaton = description->first_automaton;
9472 automaton != NULL;
9473 automaton = automaton->next_automaton)
9475 for (ainsn = automaton->ainsn_list;
9476 ainsn != NULL;
9477 ainsn = ainsn->next_ainsn)
9478 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9480 for (reserv_ainsn = ainsn;
9481 reserv_ainsn != NULL;
9482 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9483 if (automaton->corresponding_automaton_decl != NULL)
9485 if (!w_flag)
9486 error ("Automaton `%s': Insn `%s' will never be issued",
9487 automaton->corresponding_automaton_decl->name,
9488 reserv_ainsn->insn_reserv_decl->name);
9489 else
9490 warning
9491 ("Automaton `%s': Insn `%s' will never be issued",
9492 automaton->corresponding_automaton_decl->name,
9493 reserv_ainsn->insn_reserv_decl->name);
9495 else
9497 if (!w_flag)
9498 error ("Insn `%s' will never be issued",
9499 reserv_ainsn->insn_reserv_decl->name);
9500 else
9501 warning ("Insn `%s' will never be issued",
9502 reserv_ainsn->insn_reserv_decl->name);
9508 /* The following vla is used for storing pointers to all achieved
9509 states. */
9510 static vla_ptr_t automaton_states;
9512 /* This function is called by function pass_states to add an achieved
9513 STATE. */
9514 static void
9515 add_automaton_state (state)
9516 state_t state;
9518 VLA_PTR_ADD (automaton_states, state);
9521 /* The following function forms list of important automata (whose
9522 states may be changed after the insn issue) for each insn. */
9523 static void
9524 form_important_insn_automata_lists ()
9526 automaton_t automaton;
9527 state_t *state_ptr;
9528 decl_t decl;
9529 ainsn_t ainsn;
9530 arc_t arc;
9531 int i;
9533 VLA_PTR_CREATE (automaton_states, 1500,
9534 "automaton states for forming important insn automata sets");
9535 /* Mark important ainsns. */
9536 for (automaton = description->first_automaton;
9537 automaton != NULL;
9538 automaton = automaton->next_automaton)
9540 VLA_PTR_NULLIFY (automaton_states);
9541 pass_states (automaton, add_automaton_state);
9542 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9543 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9544 state_ptr++)
9546 for (arc = first_out_arc (*state_ptr);
9547 arc != NULL;
9548 arc = next_out_arc (arc))
9549 if (arc->to_state != *state_ptr)
9551 if (!arc->insn->first_insn_with_same_reservs)
9552 abort ();
9553 for (ainsn = arc->insn;
9554 ainsn != NULL;
9555 ainsn = ainsn->next_same_reservs_insn)
9556 ainsn->important_p = TRUE;
9560 VLA_PTR_DELETE (automaton_states);
9561 /* Create automata sets for the insns. */
9562 for (i = 0; i < description->decls_num; i++)
9564 decl = description->decls [i];
9565 if (decl->mode == dm_insn_reserv)
9567 automata_list_start ();
9568 for (automaton = description->first_automaton;
9569 automaton != NULL;
9570 automaton = automaton->next_automaton)
9571 for (ainsn = automaton->ainsn_list;
9572 ainsn != NULL;
9573 ainsn = ainsn->next_ainsn)
9574 if (ainsn->important_p
9575 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9577 automata_list_add (automaton);
9578 break;
9580 DECL_INSN_RESERV (decl)->important_automata_list
9581 = automata_list_finish ();
9587 /* The following is top level function to generate automat(a,on) for
9588 fast recognition of pipeline hazards. */
9589 void
9590 expand_automata ()
9592 int i;
9594 description = create_node (sizeof (struct description)
9595 /* One entry for cycle advancing insn. */
9596 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9597 description->decls_num = VLA_PTR_LENGTH (decls);
9598 description->query_units_num = 0;
9599 for (i = 0; i < description->decls_num; i++)
9601 description->decls [i] = VLA_PTR (decls, i);
9602 if (description->decls [i]->mode == dm_unit
9603 && DECL_UNIT (description->decls [i])->query_p)
9604 DECL_UNIT (description->decls [i])->query_num
9605 = description->query_units_num++;
9607 all_time = create_ticker ();
9608 check_time = create_ticker ();
9609 fprintf (stderr, "Check description...");
9610 fflush (stderr);
9611 check_all_description ();
9612 fprintf (stderr, "done\n");
9613 ticker_off (&check_time);
9614 generation_time = create_ticker ();
9615 if (!have_error)
9617 transform_insn_regexps ();
9618 check_unit_distributions_to_automata ();
9620 if (!have_error)
9622 generate ();
9623 check_automata_insn_issues ();
9625 if (!have_error)
9627 form_important_insn_automata_lists ();
9628 fprintf (stderr, "Generation of attributes...");
9629 fflush (stderr);
9630 make_internal_dfa_insn_code_attr ();
9631 make_insn_alts_attr ();
9632 make_default_insn_latency_attr ();
9633 make_bypass_attr ();
9634 fprintf (stderr, "done\n");
9636 ticker_off (&generation_time);
9637 ticker_off (&all_time);
9638 fprintf (stderr, "All other genattrtab stuff...");
9639 fflush (stderr);
9642 /* The following is top level function to output PHR and to finish
9643 work with pipeline description translator. */
9644 void
9645 write_automata ()
9647 fprintf (stderr, "done\n");
9648 if (have_error)
9649 fatal ("Errors in DFA description");
9650 ticker_on (&all_time);
9651 output_time = create_ticker ();
9652 fprintf (stderr, "Forming and outputing automata tables...");
9653 fflush (stderr);
9654 output_dfa_max_issue_rate ();
9655 output_tables ();
9656 fprintf (stderr, "done\n");
9657 fprintf (stderr, "Output functions to work with automata...");
9658 fflush (stderr);
9659 output_chip_definitions ();
9660 output_max_insn_queue_index_def ();
9661 output_internal_min_issue_delay_func ();
9662 output_internal_trans_func ();
9663 /* Cache of insn dfa codes: */
9664 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9665 fprintf (output_file, "\nstatic int %s;\n\n",
9666 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9667 output_dfa_insn_code_func ();
9668 output_trans_func ();
9669 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9670 output_internal_state_alts_func ();
9671 output_state_alts_func ();
9672 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9673 AUTOMATON_STATE_ALTS_MACRO_NAME);
9674 output_min_issue_delay_func ();
9675 output_internal_dead_lock_func ();
9676 output_dead_lock_func ();
9677 output_size_func ();
9678 output_internal_reset_func ();
9679 output_reset_func ();
9680 output_min_insn_conflict_delay_func ();
9681 output_internal_insn_latency_func ();
9682 output_insn_latency_func ();
9683 output_print_reservation_func ();
9684 if (no_minimization_flag)
9686 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9687 output_get_cpu_unit_code_func ();
9688 output_cpu_unit_reservation_p ();
9689 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9690 CPU_UNITS_QUERY_MACRO_NAME);
9692 output_dfa_start_func ();
9693 output_dfa_finish_func ();
9694 fprintf (stderr, "done\n");
9695 if (v_flag)
9697 output_description_file = fopen (output_description_file_name, "w");
9698 if (output_description_file == NULL)
9700 perror (output_description_file_name);
9701 exit (FATAL_EXIT_CODE);
9703 fprintf (stderr, "Output automata description...");
9704 fflush (stderr);
9705 output_description ();
9706 output_automaton_descriptions ();
9707 fprintf (stderr, "done\n");
9708 output_statistics (output_description_file);
9710 output_statistics (stderr);
9711 ticker_off (&output_time);
9712 output_time_statistics (stderr);
9713 finish_states ();
9714 finish_arcs ();
9715 finish_automata_lists ();
9716 if (time_flag)
9718 fprintf (stderr, "Summary:\n");
9719 fprintf (stderr, " check time ");
9720 print_active_time (stderr, check_time);
9721 fprintf (stderr, ", generation time ");
9722 print_active_time (stderr, generation_time);
9723 fprintf (stderr, ", all time ");
9724 print_active_time (stderr, all_time);
9725 fprintf (stderr, "\n");
9727 /* Finish all work. */
9728 if (output_description_file != NULL)
9730 fflush (output_description_file);
9731 if (ferror (stdout) != 0)
9732 fatal ("Error in writing DFA description file %s",
9733 output_description_file_name);
9734 fclose (output_description_file);
9736 finish_automaton_decl_table ();
9737 finish_insn_decl_table ();
9738 finish_decl_table ();
9739 obstack_free (&irp, NULL);
9740 if (have_error && output_description_file != NULL)
9741 remove (output_description_file_name);