Mon Jun 10 20:42:34 CEST 2002 Jan Hubicka <jh@suse.cz>
[official-gcc.git] / gcc / genautomata.c
blob6eec55f4f9dec1542bc243bbcf4081fb4055b27a
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 #define obstack_chunk_alloc xmalloc
120 #define obstack_chunk_free free
122 /* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
124 typedef int pos_t;
126 /* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128 typedef unsigned HOST_WIDE_INT set_el_t;
130 /* Reservations of function units are represented by value of the following
131 type. */
132 typedef set_el_t *reserv_sets_t;
134 /* The following structure represents variable length array (vla) of
135 pointers and HOST WIDE INTs. We could be use only varray. But we
136 add new lay because we add elements very frequently and this could
137 stress OS allocator when varray is used only. */
138 typedef struct {
139 size_t length; /* current size of vla. */
140 varray_type varray; /* container for vla. */
141 } vla_ptr_t;
143 typedef vla_ptr_t vla_hwint_t;
145 /* The following structure describes a ticker. */
146 struct ticker
148 /* The following member value is time of the ticker creation with
149 taking into account time when the ticker is off. Active time of
150 the ticker is current time minus the value. */
151 int modified_creation_time;
152 /* The following member value is time (incremented by one) when the
153 ticker was off. Zero value means that now the ticker is on. */
154 int incremented_off_time;
157 /* The ticker is represented by the following type. */
158 typedef struct ticker ticker_t;
160 /* The following type describes elements of output vectors. */
161 typedef HOST_WIDE_INT vect_el_t;
163 /* Forward declaration of structures of internal representation of
164 pipeline description based on NDFA. */
166 struct unit_decl;
167 struct bypass_decl;
168 struct result_decl;
169 struct automaton_decl;
170 struct unit_rel_decl;
171 struct reserv_decl;
172 struct insn_reserv_decl;
173 struct decl;
174 struct unit_regexp;
175 struct result_regexp;
176 struct reserv_regexp;
177 struct nothing_regexp;
178 struct sequence_regexp;
179 struct repeat_regexp;
180 struct allof_regexp;
181 struct oneof_regexp;
182 struct regexp;
183 struct description;
184 struct unit_set_el;
185 struct state;
186 struct alt_state;
187 struct arc;
188 struct ainsn;
189 struct automaton;
190 struct state_ainsn_table;
192 /* The following typedefs are for brevity. */
193 typedef struct unit_decl *unit_decl_t;
194 typedef struct decl *decl_t;
195 typedef struct regexp *regexp_t;
196 typedef struct unit_set_el *unit_set_el_t;
197 typedef struct alt_state *alt_state_t;
198 typedef struct state *state_t;
199 typedef struct arc *arc_t;
200 typedef struct ainsn *ainsn_t;
201 typedef struct automaton *automaton_t;
202 typedef struct automata_list_el *automata_list_el_t;
203 typedef struct state_ainsn_table *state_ainsn_table_t;
206 /* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
207 gen_bypass, gen_excl_set, gen_presence_set, gen_absence_set,
208 gen_automaton, gen_automata_option, gen_reserv, gen_insn_reserv,
209 initiate_automaton_gen, expand_automata, write_automata are
210 described on the file top because the functions are called from
211 function `main'. */
213 static void *create_node PARAMS ((size_t));
214 static void *copy_node PARAMS ((void *, size_t));
215 static char *check_name PARAMS ((char *, pos_t));
216 static char *next_sep_el PARAMS ((char **, int, int));
217 static int n_sep_els PARAMS ((char *, int, int));
218 static char **get_str_vect PARAMS ((char *, int *, int, int));
219 static regexp_t gen_regexp_el PARAMS ((char *));
220 static regexp_t gen_regexp_repeat PARAMS ((char *));
221 static regexp_t gen_regexp_allof PARAMS ((char *));
222 static regexp_t gen_regexp_oneof PARAMS ((char *));
223 static regexp_t gen_regexp_sequence PARAMS ((char *));
224 static regexp_t gen_regexp PARAMS ((char *));
226 static unsigned string_hash PARAMS ((const char *));
227 static unsigned automaton_decl_hash PARAMS ((const void *));
228 static int automaton_decl_eq_p PARAMS ((const void *,
229 const void *));
230 static decl_t insert_automaton_decl PARAMS ((decl_t));
231 static decl_t find_automaton_decl PARAMS ((char *));
232 static void initiate_automaton_decl_table PARAMS ((void));
233 static void finish_automaton_decl_table PARAMS ((void));
235 static unsigned insn_decl_hash PARAMS ((const void *));
236 static int insn_decl_eq_p PARAMS ((const void *,
237 const void *));
238 static decl_t insert_insn_decl PARAMS ((decl_t));
239 static decl_t find_insn_decl PARAMS ((char *));
240 static void initiate_insn_decl_table PARAMS ((void));
241 static void finish_insn_decl_table PARAMS ((void));
243 static unsigned decl_hash PARAMS ((const void *));
244 static int decl_eq_p PARAMS ((const void *,
245 const void *));
246 static decl_t insert_decl PARAMS ((decl_t));
247 static decl_t find_decl PARAMS ((char *));
248 static void initiate_decl_table PARAMS ((void));
249 static void finish_decl_table PARAMS ((void));
251 static unit_set_el_t process_excls PARAMS ((char **, int, pos_t));
252 static void add_excls PARAMS ((unit_set_el_t, unit_set_el_t,
253 pos_t));
254 static unit_set_el_t process_presence_absence
255 PARAMS ((char **, int, pos_t, int));
256 static void add_presence_absence PARAMS ((unit_set_el_t, unit_set_el_t,
257 pos_t, int));
258 static void process_decls PARAMS ((void));
259 static struct bypass_decl *find_bypass PARAMS ((struct bypass_decl *,
260 struct insn_reserv_decl *));
261 static void check_automaton_usage PARAMS ((void));
262 static regexp_t process_regexp PARAMS ((regexp_t));
263 static void process_regexp_decls PARAMS ((void));
264 static void check_usage PARAMS ((void));
265 static int loop_in_regexp PARAMS ((regexp_t, decl_t));
266 static void check_loops_in_regexps PARAMS ((void));
267 static int process_regexp_cycles PARAMS ((regexp_t, int));
268 static void evaluate_max_reserv_cycles PARAMS ((void));
269 static void check_all_description PARAMS ((void));
271 static ticker_t create_ticker PARAMS ((void));
272 static void ticker_off PARAMS ((ticker_t *));
273 static void ticker_on PARAMS ((ticker_t *));
274 static int active_time PARAMS ((ticker_t));
275 static void print_active_time PARAMS ((FILE *, ticker_t));
277 static void add_advance_cycle_insn_decl PARAMS ((void));
279 static alt_state_t get_free_alt_state PARAMS ((void));
280 static void free_alt_state PARAMS ((alt_state_t));
281 static void free_alt_states PARAMS ((alt_state_t));
282 static int alt_state_cmp PARAMS ((const void *alt_state_ptr_1,
283 const void *alt_state_ptr_2));
284 static alt_state_t uniq_sort_alt_states PARAMS ((alt_state_t));
285 static int alt_states_eq PARAMS ((alt_state_t, alt_state_t));
286 static void initiate_alt_states PARAMS ((void));
287 static void finish_alt_states PARAMS ((void));
289 static reserv_sets_t alloc_empty_reserv_sets PARAMS ((void));
290 static unsigned reserv_sets_hash_value PARAMS ((reserv_sets_t));
291 static int reserv_sets_cmp PARAMS ((reserv_sets_t, reserv_sets_t));
292 static int reserv_sets_eq PARAMS ((reserv_sets_t, reserv_sets_t));
293 static void set_unit_reserv PARAMS ((reserv_sets_t, int, int));
294 static int test_unit_reserv PARAMS ((reserv_sets_t, int, int));
295 static int it_is_empty_reserv_sets PARAMS ((reserv_sets_t))
296 ATTRIBUTE_UNUSED;
297 static int reserv_sets_are_intersected PARAMS ((reserv_sets_t, reserv_sets_t));
298 static void reserv_sets_shift PARAMS ((reserv_sets_t, reserv_sets_t));
299 static void reserv_sets_or PARAMS ((reserv_sets_t, reserv_sets_t,
300 reserv_sets_t));
301 static void reserv_sets_and PARAMS ((reserv_sets_t, reserv_sets_t,
302 reserv_sets_t))
303 ATTRIBUTE_UNUSED;
304 static void output_cycle_reservs PARAMS ((FILE *, reserv_sets_t,
305 int, int));
306 static void output_reserv_sets PARAMS ((FILE *, reserv_sets_t));
307 static state_t get_free_state PARAMS ((int, automaton_t));
308 static void free_state PARAMS ((state_t));
309 static unsigned state_hash PARAMS ((const void *));
310 static int state_eq_p PARAMS ((const void *, const void *));
311 static state_t insert_state PARAMS ((state_t));
312 static void set_state_reserv PARAMS ((state_t, int, int));
313 static int intersected_state_reservs_p PARAMS ((state_t, state_t));
314 static state_t states_union PARAMS ((state_t, state_t));
315 static state_t state_shift PARAMS ((state_t));
316 static void initiate_states PARAMS ((void));
317 static void finish_states PARAMS ((void));
319 static void free_arc PARAMS ((arc_t));
320 static void remove_arc PARAMS ((state_t, arc_t));
321 static arc_t find_arc PARAMS ((state_t, state_t, ainsn_t));
322 static arc_t add_arc PARAMS ((state_t, state_t, ainsn_t, int));
323 static arc_t first_out_arc PARAMS ((state_t));
324 static arc_t next_out_arc PARAMS ((arc_t));
325 static void initiate_arcs PARAMS ((void));
326 static void finish_arcs PARAMS ((void));
328 static automata_list_el_t get_free_automata_list_el PARAMS ((void));
329 static void free_automata_list_el PARAMS ((automata_list_el_t));
330 static void free_automata_list PARAMS ((automata_list_el_t));
331 static unsigned automata_list_hash PARAMS ((const void *));
332 static int automata_list_eq_p PARAMS ((const void *, const void *));
333 static void initiate_automata_lists PARAMS ((void));
334 static void automata_list_start PARAMS ((void));
335 static void automata_list_add PARAMS ((automaton_t));
336 static automata_list_el_t automata_list_finish PARAMS ((void));
337 static void finish_automata_lists PARAMS ((void));
339 static void initiate_excl_sets PARAMS ((void));
340 static reserv_sets_t get_excl_set PARAMS ((reserv_sets_t));
342 static void initiate_presence_absence_sets PARAMS ((void));
343 static reserv_sets_t get_presence_absence_set PARAMS ((reserv_sets_t, int));
345 static regexp_t copy_insn_regexp PARAMS ((regexp_t));
346 static regexp_t transform_1 PARAMS ((regexp_t));
347 static regexp_t transform_2 PARAMS ((regexp_t));
348 static regexp_t transform_3 PARAMS ((regexp_t));
349 static regexp_t regexp_transform_func
350 PARAMS ((regexp_t, regexp_t (*) (regexp_t)));
351 static regexp_t transform_regexp PARAMS ((regexp_t));
352 static void transform_insn_regexps PARAMS ((void));
354 static void process_unit_to_form_the_same_automaton_unit_lists
355 PARAMS ((regexp_t, regexp_t, int));
356 static void form_the_same_automaton_unit_lists_from_regexp PARAMS ((regexp_t));
357 static void form_the_same_automaton_unit_lists PARAMS ((void));
358 static void check_unit_distributions_to_automata PARAMS ((void));
360 static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t,
361 int));
362 static void finish_forming_alt_state PARAMS ((alt_state_t,
363 automaton_t));
364 static void process_alts_for_forming_states PARAMS ((regexp_t,
365 automaton_t, int));
366 static void create_alt_states PARAMS ((automaton_t));
368 static void form_ainsn_with_same_reservs PARAMS ((automaton_t));
370 static void make_automaton PARAMS ((automaton_t));
371 static void form_arcs_marked_by_insn PARAMS ((state_t));
372 static void create_composed_state PARAMS ((state_t, arc_t, vla_ptr_t *));
373 static void NDFA_to_DFA PARAMS ((automaton_t));
374 static void pass_state_graph PARAMS ((state_t, void (*) (state_t)));
375 static void pass_states PARAMS ((automaton_t,
376 void (*) (state_t)));
377 static void initiate_pass_states PARAMS ((void));
378 static void add_achieved_state PARAMS ((state_t));
379 static int set_out_arc_insns_equiv_num PARAMS ((state_t, int));
380 static void clear_arc_insns_equiv_num PARAMS ((state_t));
381 static void copy_equiv_class PARAMS ((vla_ptr_t *to,
382 const vla_ptr_t *from));
383 static int state_is_differed PARAMS ((state_t, int, int));
384 static state_t init_equiv_class PARAMS ((state_t *states, int));
385 static int partition_equiv_class PARAMS ((state_t *, int,
386 vla_ptr_t *, int *));
387 static void evaluate_equiv_classes PARAMS ((automaton_t, vla_ptr_t *));
388 static void merge_states PARAMS ((automaton_t, vla_ptr_t *));
389 static void set_new_cycle_flags PARAMS ((state_t));
390 static void minimize_DFA PARAMS ((automaton_t));
391 static void incr_states_and_arcs_nums PARAMS ((state_t));
392 static void count_states_and_arcs PARAMS ((automaton_t, int *, int *));
393 static void build_automaton PARAMS ((automaton_t));
395 static void set_order_state_num PARAMS ((state_t));
396 static void enumerate_states PARAMS ((automaton_t));
398 static ainsn_t insert_ainsn_into_equiv_class PARAMS ((ainsn_t, ainsn_t));
399 static void delete_ainsn_from_equiv_class PARAMS ((ainsn_t));
400 static void process_insn_equiv_class PARAMS ((ainsn_t, arc_t *));
401 static void process_state_for_insn_equiv_partition PARAMS ((state_t));
402 static void set_insn_equiv_classes PARAMS ((automaton_t));
404 static double estimate_one_automaton_bound PARAMS ((void));
405 static int compare_max_occ_cycle_nums PARAMS ((const void *,
406 const void *));
407 static void units_to_automata_heuristic_distr PARAMS ((void));
408 static ainsn_t create_ainsns PARAMS ((void));
409 static void units_to_automata_distr PARAMS ((void));
410 static void create_automata PARAMS ((void));
412 static void form_regexp PARAMS ((regexp_t));
413 static const char *regexp_representation PARAMS ((regexp_t));
414 static void finish_regexp_representation PARAMS ((void));
416 static void output_range_type PARAMS ((FILE *, long int, long int));
417 static int longest_path_length PARAMS ((state_t));
418 static void process_state_longest_path_length PARAMS ((state_t));
419 static void output_dfa_max_issue_rate PARAMS ((void));
420 static void output_vect PARAMS ((vect_el_t *, int));
421 static void output_chip_member_name PARAMS ((FILE *, automaton_t));
422 static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t));
423 static void output_translate_vect_name PARAMS ((FILE *, automaton_t));
424 static void output_trans_full_vect_name PARAMS ((FILE *, automaton_t));
425 static void output_trans_comb_vect_name PARAMS ((FILE *, automaton_t));
426 static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t));
427 static void output_trans_base_vect_name PARAMS ((FILE *, automaton_t));
428 static void output_state_alts_full_vect_name PARAMS ((FILE *, automaton_t));
429 static void output_state_alts_comb_vect_name PARAMS ((FILE *, automaton_t));
430 static void output_state_alts_check_vect_name PARAMS ((FILE *, automaton_t));
431 static void output_state_alts_base_vect_name PARAMS ((FILE *, automaton_t));
432 static void output_min_issue_delay_vect_name PARAMS ((FILE *, automaton_t));
433 static void output_dead_lock_vect_name PARAMS ((FILE *, automaton_t));
434 static void output_reserved_units_table_name PARAMS ((FILE *, automaton_t));
435 static void output_state_member_type PARAMS ((FILE *, automaton_t));
436 static void output_chip_definitions PARAMS ((void));
437 static void output_translate_vect PARAMS ((automaton_t));
438 static int comb_vect_p PARAMS ((state_ainsn_table_t));
439 static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t));
440 static void output_state_ainsn_table
441 PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
442 void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
443 void (*) (FILE *, automaton_t)));
444 static void add_vect PARAMS ((state_ainsn_table_t,
445 int, vect_el_t *, int));
446 static int out_state_arcs_num PARAMS ((state_t));
447 static int compare_transition_els_num PARAMS ((const void *, const void *));
448 static void add_vect_el PARAMS ((vla_hwint_t *,
449 ainsn_t, int));
450 static void add_states_vect_el PARAMS ((state_t));
451 static void output_trans_table PARAMS ((automaton_t));
452 static void output_state_alts_table PARAMS ((automaton_t));
453 static int min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
454 static int min_issue_delay PARAMS ((state_t, ainsn_t));
455 static void initiate_min_issue_delay_pass_states PARAMS ((void));
456 static void output_min_issue_delay_table PARAMS ((automaton_t));
457 static void output_dead_lock_vect PARAMS ((automaton_t));
458 static void output_reserved_units_table PARAMS ((automaton_t));
459 static void output_tables PARAMS ((void));
460 static void output_max_insn_queue_index_def PARAMS ((void));
461 static void output_insn_code_cases PARAMS ((void (*) (automata_list_el_t)));
462 static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
463 static void output_internal_min_issue_delay_func PARAMS ((void));
464 static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
465 static void output_internal_trans_func PARAMS ((void));
466 static void output_internal_insn_code_evaluation PARAMS ((const char *,
467 const char *, int));
468 static void output_dfa_insn_code_func PARAMS ((void));
469 static void output_trans_func PARAMS ((void));
470 static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
471 static void output_internal_state_alts_func PARAMS ((void));
472 static void output_state_alts_func PARAMS ((void));
473 static void output_min_issue_delay_func PARAMS ((void));
474 static void output_internal_dead_lock_func PARAMS ((void));
475 static void output_dead_lock_func PARAMS ((void));
476 static void output_internal_reset_func PARAMS ((void));
477 static void output_size_func PARAMS ((void));
478 static void output_reset_func PARAMS ((void));
479 static void output_min_insn_conflict_delay_func PARAMS ((void));
480 static void output_internal_insn_latency_func PARAMS ((void));
481 static void output_insn_latency_func PARAMS ((void));
482 static void output_print_reservation_func PARAMS ((void));
483 static int units_cmp PARAMS ((const void *,
484 const void *));
485 static void output_get_cpu_unit_code_func PARAMS ((void));
486 static void output_cpu_unit_reservation_p PARAMS ((void));
487 static void output_dfa_start_func PARAMS ((void));
488 static void output_dfa_finish_func PARAMS ((void));
490 static void output_regexp PARAMS ((regexp_t ));
491 static void output_unit_set_el_list PARAMS ((unit_set_el_t));
492 static void output_description PARAMS ((void));
493 static void output_automaton_name PARAMS ((FILE *, automaton_t));
494 static void output_automaton_units PARAMS ((automaton_t));
495 static void add_state_reservs PARAMS ((state_t));
496 static void output_state_arcs PARAMS ((state_t));
497 static int state_reservs_cmp PARAMS ((const void *,
498 const void *));
499 static void remove_state_duplicate_reservs PARAMS ((void));
500 static void output_state PARAMS ((state_t));
501 static void output_automaton_descriptions PARAMS ((void));
502 static void output_statistics PARAMS ((FILE *));
503 static void output_time_statistics PARAMS ((FILE *));
504 static void generate PARAMS ((void));
506 static void make_insn_alts_attr PARAMS ((void));
507 static void make_internal_dfa_insn_code_attr PARAMS ((void));
508 static void make_default_insn_latency_attr PARAMS ((void));
509 static void make_bypass_attr PARAMS ((void));
510 static const char *file_name_suffix PARAMS ((const char *));
511 static const char *base_file_name PARAMS ((const char *));
512 static void check_automata_insn_issues PARAMS ((void));
513 static void add_automaton_state PARAMS ((state_t));
514 static void form_important_insn_automata_lists PARAMS ((void));
516 /* Undefined position. */
517 static pos_t no_pos = 0;
519 /* All IR is stored in the following obstack. */
520 static struct obstack irp;
524 /* This page contains code for work with variable length array (vla)
525 of pointers. We could be use only varray. But we add new lay
526 because we add elements very frequently and this could stress OS
527 allocator when varray is used only. */
529 /* Start work with vla. */
530 #define VLA_PTR_CREATE(vla, allocated_length, name) \
531 do \
533 vla_ptr_t *vla_ptr = &(vla); \
535 VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\
536 vla_ptr->length = 0; \
538 while (0)
540 /* Finish work with the vla. */
541 #define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
543 /* Return start address of the vla. */
544 #define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
546 /* Address of the last element of the vla. Do not use side effects in
547 the macro argument. */
548 #define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \
549 (vla).length - 1))
550 /* Nullify the vla. */
551 #define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
553 /* Shorten the vla on given number bytes. */
554 #define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
556 /* Expand the vla on N elements. The values of new elements are
557 undefined. */
558 #define VLA_PTR_EXPAND(vla, n) \
559 do { \
560 vla_ptr_t *expand_vla_ptr = &(vla); \
561 size_t new_length = (n) + expand_vla_ptr->length; \
563 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
564 VARRAY_GROW (expand_vla_ptr->varray, \
565 (new_length - expand_vla_ptr->length < 128 \
566 ? expand_vla_ptr->length + 128 : new_length)); \
567 expand_vla_ptr->length = new_length; \
568 } while (0)
570 /* Add element to the end of the vla. */
571 #define VLA_PTR_ADD(vla, ptr) \
572 do { \
573 vla_ptr_t *vla_ptr = &(vla); \
575 VLA_PTR_EXPAND (*vla_ptr, 1); \
576 VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\
577 } while (0)
579 /* Length of the vla in elements. */
580 #define VLA_PTR_LENGTH(vla) ((vla).length)
582 /* N-th element of the vla. */
583 #define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
586 /* The following macros are analogous to the previous ones but for
587 VLAs of HOST WIDE INTs. */
589 #define VLA_HWINT_CREATE(vla, allocated_length, name) \
590 do { \
591 vla_hwint_t *vla_ptr = &(vla); \
593 VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name); \
594 vla_ptr->length = 0; \
595 } while (0)
597 #define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
599 #define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
601 /* Do not use side effects in the macro argument. */
602 #define VLA_HWINT_LAST(vla) (&VARRAY_WIDE_INT ((vla).varray, \
603 (vla).length - 1))
605 #define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
607 #define VLA_HWINT_SHORTEN(vla, n) ((vla).length -= (n))
609 #define VLA_HWINT_EXPAND(vla, n) \
610 do { \
611 vla_hwint_t *expand_vla_ptr = &(vla); \
612 size_t new_length = (n) + expand_vla_ptr->length; \
614 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
615 VARRAY_GROW (expand_vla_ptr->varray, \
616 (new_length - expand_vla_ptr->length < 128 \
617 ? expand_vla_ptr->length + 128 : new_length)); \
618 expand_vla_ptr->length = new_length; \
619 } while (0)
621 #define VLA_HWINT_ADD(vla, ptr) \
622 do { \
623 vla_hwint_t *vla_ptr = &(vla); \
625 VLA_HWINT_EXPAND (*vla_ptr, 1); \
626 VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr); \
627 } while (0)
629 #define VLA_HWINT_LENGTH(vla) ((vla).length)
631 #define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
635 /* Options with the following names can be set up in automata_option
636 construction. Because the strings occur more one time we use the
637 macros. */
639 #define NO_MINIMIZATION_OPTION "-no-minimization"
641 #define TIME_OPTION "-time"
643 #define V_OPTION "-v"
645 #define W_OPTION "-w"
647 #define NDFA_OPTION "-ndfa"
649 /* The following flags are set up by function `initiate_automaton_gen'. */
651 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
652 static int ndfa_flag;
654 /* Do not make minimization of DFA (`-no-minimization'). */
655 static int no_minimization_flag;
657 /* Value of this variable is number of automata being generated. The
658 actual number of automata may be less this value if there is not
659 sufficient number of units. This value is defined by argument of
660 option `-split' or by constructions automaton if the value is zero
661 (it is default value of the argument). */
662 static int split_argument;
664 /* Flag of output time statistics (`-time'). */
665 static int time_flag;
667 /* Flag of creation of description file which contains description of
668 result automaton and statistics information (`-v'). */
669 static int v_flag;
671 /* Flag of generating warning instead of error for non-critical errors
672 (`-w'). */
673 static int w_flag;
676 /* Output file for pipeline hazard recognizer (PHR) being generated.
677 The value is NULL if the file is not defined. */
678 static FILE *output_file;
680 /* Description file of PHR. The value is NULL if the file is not
681 created. */
682 static FILE *output_description_file;
684 /* PHR description file name. */
685 static char *output_description_file_name;
687 /* Value of the following variable is node representing description
688 being processed. This is start point of IR. */
689 static struct description *description;
693 /* This page contains description of IR structure (nodes). */
695 enum decl_mode
697 dm_unit,
698 dm_bypass,
699 dm_automaton,
700 dm_excl,
701 dm_presence,
702 dm_absence,
703 dm_reserv,
704 dm_insn_reserv
707 /* This describes define_cpu_unit and define_query_cpu_unit (see file
708 rtl.def). */
709 struct unit_decl
711 char *name;
712 /* NULL if the automaton name is absent. */
713 char *automaton_name;
714 /* If the following value is not zero, the cpu unit reservation is
715 described in define_query_cpu_unit. */
716 char query_p;
718 /* The following fields are defined by checker. */
720 /* The following field value is nonzero if the unit is used in an
721 regexp. */
722 char unit_is_used;
724 /* The following field value is used to form cyclic lists of units
725 which should be in the same automaton because the unit is
726 reserved not on all alternatives of a regexp on a cycle. */
727 unit_decl_t the_same_automaton_unit;
728 /* The following field is TRUE if we already reported that the unit
729 is not in the same automaton. */
730 int the_same_automaton_message_reported_p;
732 /* The following field value is order number (0, 1, ...) of given
733 unit. */
734 int unit_num;
735 /* The following field value is corresponding declaration of
736 automaton which was given in description. If the field value is
737 NULL then automaton in the unit declaration was absent. */
738 struct automaton_decl *automaton_decl;
739 /* The following field value is maximal cycle number (1, ...) on
740 which given unit occurs in insns. Zero value means that given
741 unit is not used in insns. */
742 int max_occ_cycle_num;
743 /* The following list contains units which conflict with given
744 unit. */
745 unit_set_el_t excl_list;
746 /* The following list contains units which are required to
747 reservation of given unit. */
748 unit_set_el_t presence_list;
749 /* The following list contains units which should be not present in
750 reservation for given unit. */
751 unit_set_el_t absence_list;
752 /* The following is used only when `query_p' has nonzero value.
753 This is query number for the unit. */
754 int query_num;
756 /* The following fields are defined by automaton generator. */
758 /* The following field value is number of the automaton to which
759 given unit belongs. */
760 int corresponding_automaton_num;
763 /* This describes define_bypass (see file rtl.def). */
764 struct bypass_decl
766 int latency;
767 char *out_insn_name;
768 char *in_insn_name;
769 char *bypass_guard_name;
771 /* The following fields are defined by checker. */
773 /* output and input insns of given bypass. */
774 struct insn_reserv_decl *out_insn_reserv;
775 struct insn_reserv_decl *in_insn_reserv;
776 /* The next bypass for given output insn. */
777 struct bypass_decl *next;
780 /* This describes define_automaton (see file rtl.def). */
781 struct automaton_decl
783 char *name;
785 /* The following fields are defined by automaton generator. */
787 /* The following field value is nonzero if the automaton is used in
788 an regexp definition. */
789 char automaton_is_used;
791 /* The following fields are defined by checker. */
793 /* The following field value is the corresponding automaton. This
794 field is not NULL only if the automaton is present in unit
795 declarations and the automatic partition on automata is not
796 used. */
797 automaton_t corresponding_automaton;
800 /* This describes unit relations: exclusion_set, presence_set, or
801 absence_set (see file rtl.def). */
802 struct unit_rel_decl
804 int names_num;
805 int first_list_length;
806 char *names [1];
809 /* This describes define_reservation (see file rtl.def). */
810 struct reserv_decl
812 char *name;
813 regexp_t regexp;
815 /* The following fields are defined by checker. */
817 /* The following field value is nonzero if the unit is used in an
818 regexp. */
819 char reserv_is_used;
820 /* The following field is used to check up cycle in expression
821 definition. */
822 int loop_pass_num;
825 /* This describes define_insn_reservartion (see file rtl.def). */
826 struct insn_reserv_decl
828 rtx condexp;
829 int default_latency;
830 regexp_t regexp;
831 char *name;
833 /* The following fields are defined by checker. */
835 /* The following field value is order number (0, 1, ...) of given
836 insn. */
837 int insn_num;
838 /* The following field value is list of bypasses in which given insn
839 is output insn. */
840 struct bypass_decl *bypass_list;
842 /* The following fields are defined by automaton generator. */
844 /* The following field is the insn regexp transformed that
845 the regexp has not optional regexp, repetition regexp, and an
846 reservation name (i.e. reservation identifiers are changed by the
847 corresponding regexp) and all alternations are the topest level
848 of the regexp. The value can be NULL only if it is special
849 insn `cycle advancing'. */
850 regexp_t transformed_regexp;
851 /* The following field value is list of arcs marked given
852 insn. The field is used in transfromation NDFA -> DFA. */
853 arc_t arcs_marked_by_insn;
854 /* The two following fields are used during minimization of a finite state
855 automaton. */
856 /* The field value is number of equivalence class of state into
857 which arc marked by given insn enters from a state (fixed during
858 an automaton minimization). */
859 int equiv_class_num;
860 /* The field value is state_alts of arc leaving a state (fixed
861 during an automaton minimization) and marked by given insn
862 enters. */
863 int state_alts;
864 /* The following member value is the list to automata which can be
865 changed by the insn issue. */
866 automata_list_el_t important_automata_list;
867 /* The following member is used to process insn once for output. */
868 int processed_p;
871 /* This contains a declaration mentioned above. */
872 struct decl
874 /* What node in the union? */
875 enum decl_mode mode;
876 pos_t pos;
877 union
879 struct unit_decl unit;
880 struct bypass_decl bypass;
881 struct automaton_decl automaton;
882 struct unit_rel_decl excl;
883 struct unit_rel_decl presence;
884 struct unit_rel_decl absence;
885 struct reserv_decl reserv;
886 struct insn_reserv_decl insn_reserv;
887 } decl;
890 /* The following structures represent parsed reservation strings. */
891 enum regexp_mode
893 rm_unit,
894 rm_reserv,
895 rm_nothing,
896 rm_sequence,
897 rm_repeat,
898 rm_allof,
899 rm_oneof
902 /* Cpu unit in reservation. */
903 struct unit_regexp
905 char *name;
906 unit_decl_t unit_decl;
909 /* Define_reservation in a reservation. */
910 struct reserv_regexp
912 char *name;
913 struct reserv_decl *reserv_decl;
916 /* Absence of reservation (represented by string `nothing'). */
917 struct nothing_regexp
919 /* This used to be empty but ISO C doesn't allow that. */
920 char unused;
923 /* Representation of reservations separated by ',' (see file
924 rtl.def). */
925 struct sequence_regexp
927 int regexps_num;
928 regexp_t regexps [1];
931 /* Representation of construction `repeat' (see file rtl.def). */
932 struct repeat_regexp
934 int repeat_num;
935 regexp_t regexp;
938 /* Representation of reservations separated by '+' (see file
939 rtl.def). */
940 struct allof_regexp
942 int regexps_num;
943 regexp_t regexps [1];
946 /* Representation of reservations separated by '|' (see file
947 rtl.def). */
948 struct oneof_regexp
950 int regexps_num;
951 regexp_t regexps [1];
954 /* Representation of a reservation string. */
955 struct regexp
957 /* What node in the union? */
958 enum regexp_mode mode;
959 pos_t pos;
960 union
962 struct unit_regexp unit;
963 struct reserv_regexp reserv;
964 struct nothing_regexp nothing;
965 struct sequence_regexp sequence;
966 struct repeat_regexp repeat;
967 struct allof_regexp allof;
968 struct oneof_regexp oneof;
969 } regexp;
972 /* Reperesents description of pipeline hazard description based on
973 NDFA. */
974 struct description
976 int decls_num;
978 /* The following fields are defined by checker. */
980 /* The following fields values are correspondingly number of all
981 units, query units, and insns in the description. */
982 int units_num;
983 int query_units_num;
984 int insns_num;
985 /* The following field value is max length (in cycles) of
986 reservations of insns. The field value is defined only for
987 correct programs. */
988 int max_insn_reserv_cycles;
990 /* The following fields are defined by automaton generator. */
992 /* The following field value is the first automaton. */
993 automaton_t first_automaton;
995 /* The following field is created by pipeline hazard parser and
996 contains all declarations. We allocate additional entry for
997 special insn "cycle advancing" which is added by the automaton
998 generator. */
999 decl_t decls [1];
1004 /* The following nodes are created in automaton checker. */
1006 /* The following nodes represent exclusion, presence, absence set for
1007 cpu units. Each element are accessed through only one excl_list,
1008 presence_list, absence_list. */
1009 struct unit_set_el
1011 unit_decl_t unit_decl;
1012 unit_set_el_t next_unit_set_el;
1017 /* The following nodes are created in automaton generator. */
1019 /* The following node type describes state automaton. The state may
1020 be deterministic or non-deterministic. Non-deterministic state has
1021 several component states which represent alternative cpu units
1022 reservations. The state also is used for describing a
1023 deterministic reservation of automaton insn. */
1024 struct state
1026 /* The following member value is nonzero if there is a transition by
1027 cycle advancing. */
1028 int new_cycle_p;
1029 /* The following field is list of processor unit reservations on
1030 each cycle. */
1031 reserv_sets_t reservs;
1032 /* The following field is unique number of given state between other
1033 states. */
1034 int unique_num;
1035 /* The following field value is automaton to which given state
1036 belongs. */
1037 automaton_t automaton;
1038 /* The following field value is the first arc output from given
1039 state. */
1040 arc_t first_out_arc;
1041 /* The following field is used to form NDFA. */
1042 char it_was_placed_in_stack_for_NDFA_forming;
1043 /* The following field is used to form DFA. */
1044 char it_was_placed_in_stack_for_DFA_forming;
1045 /* The following field is used to transform NDFA to DFA. The field
1046 value is not NULL if the state is a compound state. In this case
1047 the value of field `unit_sets_list' is NULL. All states in the
1048 list are in the hash table. The list is formed through field
1049 `next_sorted_alt_state'. */
1050 alt_state_t component_states;
1051 /* The following field is used for passing graph of states. */
1052 int pass_num;
1053 /* The list of states belonging to one equivalence class is formed
1054 with the aid of the following field. */
1055 state_t next_equiv_class_state;
1056 /* The two following fields are used during minimization of a finite
1057 state automaton. */
1058 int equiv_class_num_1, equiv_class_num_2;
1059 /* The following field is used during minimization of a finite state
1060 automaton. The field value is state corresponding to equivalence
1061 class to which given state belongs. */
1062 state_t equiv_class_state;
1063 /* The following field value is the order number of given state.
1064 The states in final DFA is enumerated with the aid of the
1065 following field. */
1066 int order_state_num;
1067 /* This member is used for passing states for searching minimal
1068 delay time. */
1069 int state_pass_num;
1070 /* The following member is used to evaluate min issue delay of insn
1071 for a state. */
1072 int min_insn_issue_delay;
1073 /* The following member is used to evaluate max issue rate of the
1074 processor. The value of the member is maximal length of the path
1075 from given state no containing arcs marked by special insn `cycle
1076 advancing'. */
1077 int longest_path_length;
1080 /* The following macro is an initial value of member
1081 `longest_path_length' of a state. */
1082 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1084 /* Automaton arc. */
1085 struct arc
1087 /* The following field refers for the state into which given arc
1088 enters. */
1089 state_t to_state;
1090 /* The following field describes that the insn issue (with cycle
1091 advancing for special insn `cycle advancing' and without cycle
1092 advancing for others) makes transition from given state to
1093 another given state. */
1094 ainsn_t insn;
1095 /* The following field value is the next arc output from the same
1096 state. */
1097 arc_t next_out_arc;
1098 /* List of arcs marked given insn is formed with the following
1099 field. The field is used in transfromation NDFA -> DFA. */
1100 arc_t next_arc_marked_by_insn;
1101 /* The following field is defined if NDFA_FLAG is zero. The member
1102 value is number of alternative reservations which can be used for
1103 transition for given state by given insn. */
1104 int state_alts;
1107 /* The following node type describes a deterministic alternative in
1108 non-deterministic state which characterizes cpu unit reservations
1109 of automaton insn or which is part of NDFA. */
1110 struct alt_state
1112 /* The following field is a determinist state which characterizes
1113 unit reservations of the instruction. */
1114 state_t state;
1115 /* The following field refers to the next state which characterizes
1116 unit reservations of the instruction. */
1117 alt_state_t next_alt_state;
1118 /* The following field refers to the next state in sorted list. */
1119 alt_state_t next_sorted_alt_state;
1122 /* The following node type describes insn of automaton. They are
1123 labels of FA arcs. */
1124 struct ainsn
1126 /* The following field value is the corresponding insn declaration
1127 of description. */
1128 struct insn_reserv_decl *insn_reserv_decl;
1129 /* The following field value is the next insn declaration for an
1130 automaton. */
1131 ainsn_t next_ainsn;
1132 /* The following field is states which characterize automaton unit
1133 reservations of the instruction. The value can be NULL only if it
1134 is special insn `cycle advancing'. */
1135 alt_state_t alt_states;
1136 /* The following field is sorted list of states which characterize
1137 automaton unit reservations of the instruction. The value can be
1138 NULL only if it is special insn `cycle advancing'. */
1139 alt_state_t sorted_alt_states;
1140 /* The following field refers the next automaton insn with
1141 the same reservations. */
1142 ainsn_t next_same_reservs_insn;
1143 /* The following field is flag of the first automaton insn with the
1144 same reservations in the declaration list. Only arcs marked such
1145 insn is present in the automaton. This significantly decreases
1146 memory requirements especially when several automata are
1147 formed. */
1148 char first_insn_with_same_reservs;
1149 /* The following member has nonzero value if there is arc from state of
1150 the automaton marked by the ainsn. */
1151 char arc_exists_p;
1152 /* Cyclic list of insns of an equivalence class is formed with the
1153 aid of the following field. */
1154 ainsn_t next_equiv_class_insn;
1155 /* The following field value is nonzero if the insn declaration is
1156 the first insn declaration with given equivalence number. */
1157 char first_ainsn_with_given_equialence_num;
1158 /* The following field is number of class of equivalence of insns.
1159 It is necessary because many insns may be equivalent with the
1160 point of view of pipeline hazards. */
1161 int insn_equiv_class_num;
1162 /* The following member value is TRUE if there is an arc in the
1163 automaton marked by the insn into another state. In other
1164 words, the insn can change the state of the automaton. */
1165 int important_p;
1168 /* The folowing describes an automaton for PHR. */
1169 struct automaton
1171 /* The following field value is the list of insn declarations for
1172 given automaton. */
1173 ainsn_t ainsn_list;
1174 /* The following field value is the corresponding automaton
1175 declaration. This field is not NULL only if the automatic
1176 partition on automata is not used. */
1177 struct automaton_decl *corresponding_automaton_decl;
1178 /* The following field value is the next automaton. */
1179 automaton_t next_automaton;
1180 /* The following field is start state of FA. There are not unit
1181 reservations in the state. */
1182 state_t start_state;
1183 /* The following field value is number of equivalence classes of
1184 insns (see field `insn_equiv_class_num' in
1185 `insn_reserv_decl'). */
1186 int insn_equiv_classes_num;
1187 /* The following field value is number of states of final DFA. */
1188 int achieved_states_num;
1189 /* The following field value is the order number (0, 1, ...) of
1190 given automaton. */
1191 int automaton_order_num;
1192 /* The following fields contain statistics information about
1193 building automaton. */
1194 int NDFA_states_num, DFA_states_num;
1195 /* The following field value is defined only if minimization of DFA
1196 is used. */
1197 int minimal_DFA_states_num;
1198 int NDFA_arcs_num, DFA_arcs_num;
1199 /* The following field value is defined only if minimization of DFA
1200 is used. */
1201 int minimal_DFA_arcs_num;
1202 /* The following two members refer for two table state x ainsn ->
1203 int. */
1204 state_ainsn_table_t trans_table;
1205 state_ainsn_table_t state_alts_table;
1206 /* The following member value is maximal value of min issue delay
1207 for insns of the automaton. */
1208 int max_min_delay;
1209 /* Usually min issue delay is small and we can place several (2, 4,
1210 8) elements in one vector element. So the compression factor can
1211 be 1 (no compression), 2, 4, 8. */
1212 int min_issue_delay_table_compression_factor;
1215 /* The following is the element of the list of automata. */
1216 struct automata_list_el
1218 /* The automaton itself. */
1219 automaton_t automaton;
1220 /* The next automata set element. */
1221 automata_list_el_t next_automata_list_el;
1224 /* The following structure describes a table state X ainsn -> int(>= 0). */
1225 struct state_ainsn_table
1227 /* Automaton to which given table belongs. */
1228 automaton_t automaton;
1229 /* The following tree vectors for comb vector implementation of the
1230 table. */
1231 vla_hwint_t comb_vect;
1232 vla_hwint_t check_vect;
1233 vla_hwint_t base_vect;
1234 /* This is simple implementation of the table. */
1235 vla_hwint_t full_vect;
1236 /* Minimal and maximal values of the previous vectors. */
1237 int min_comb_vect_el_value, max_comb_vect_el_value;
1238 int min_base_vect_el_value, max_base_vect_el_value;
1241 /* Macros to access members of unions. Use only them for access to
1242 union members of declarations and regexps. */
1244 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1246 #define DECL_UNIT(d) __extension__ \
1247 (({ struct decl *_decl = (d); \
1248 if (_decl->mode != dm_unit) \
1249 decl_mode_check_failed (_decl->mode, "dm_unit", \
1250 __FILE__, __LINE__, __FUNCTION__); \
1251 &(_decl)->decl.unit; }))
1253 #define DECL_BYPASS(d) __extension__ \
1254 (({ struct decl *_decl = (d); \
1255 if (_decl->mode != dm_bypass) \
1256 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1257 __FILE__, __LINE__, __FUNCTION__); \
1258 &(_decl)->decl.bypass; }))
1260 #define DECL_AUTOMATON(d) __extension__ \
1261 (({ struct decl *_decl = (d); \
1262 if (_decl->mode != dm_automaton) \
1263 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1264 __FILE__, __LINE__, __FUNCTION__); \
1265 &(_decl)->decl.automaton; }))
1267 #define DECL_EXCL(d) __extension__ \
1268 (({ struct decl *_decl = (d); \
1269 if (_decl->mode != dm_excl) \
1270 decl_mode_check_failed (_decl->mode, "dm_excl", \
1271 __FILE__, __LINE__, __FUNCTION__); \
1272 &(_decl)->decl.excl; }))
1274 #define DECL_PRESENCE(d) __extension__ \
1275 (({ struct decl *_decl = (d); \
1276 if (_decl->mode != dm_presence) \
1277 decl_mode_check_failed (_decl->mode, "dm_presence", \
1278 __FILE__, __LINE__, __FUNCTION__); \
1279 &(_decl)->decl.presence; }))
1281 #define DECL_ABSENCE(d) __extension__ \
1282 (({ struct decl *_decl = (d); \
1283 if (_decl->mode != dm_absence) \
1284 decl_mode_check_failed (_decl->mode, "dm_absence", \
1285 __FILE__, __LINE__, __FUNCTION__); \
1286 &(_decl)->decl.absence; }))
1288 #define DECL_RESERV(d) __extension__ \
1289 (({ struct decl *_decl = (d); \
1290 if (_decl->mode != dm_reserv) \
1291 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1292 __FILE__, __LINE__, __FUNCTION__); \
1293 &(_decl)->decl.reserv; }))
1295 #define DECL_INSN_RESERV(d) __extension__ \
1296 (({ struct decl *_decl = (d); \
1297 if (_decl->mode != dm_insn_reserv) \
1298 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1299 __FILE__, __LINE__, __FUNCTION__); \
1300 &(_decl)->decl.insn_reserv; }))
1302 static const char *decl_name PARAMS ((enum decl_mode));
1303 static void decl_mode_check_failed PARAMS ((enum decl_mode, const char *,
1304 const char *, int, const char *));
1306 /* Return string representation of declaration mode MODE. */
1307 static const char *
1308 decl_name (mode)
1309 enum decl_mode mode;
1311 static char str [100];
1313 if (mode == dm_unit)
1314 return "dm_unit";
1315 else if (mode == dm_bypass)
1316 return "dm_bypass";
1317 else if (mode == dm_automaton)
1318 return "dm_automaton";
1319 else if (mode == dm_excl)
1320 return "dm_excl";
1321 else if (mode == dm_presence)
1322 return "dm_presence";
1323 else if (mode == dm_absence)
1324 return "dm_absence";
1325 else if (mode == dm_reserv)
1326 return "dm_reserv";
1327 else if (mode == dm_insn_reserv)
1328 return "dm_insn_reserv";
1329 else
1330 sprintf (str, "unknown (%d)", (int) mode);
1331 return str;
1334 /* The function prints message about unexpected declaration and finish
1335 the program. */
1336 static void
1337 decl_mode_check_failed (mode, expected_mode_str, file, line, func)
1338 enum decl_mode mode;
1339 const char *expected_mode_str;
1340 const char *file;
1341 int line;
1342 const char *func;
1344 fprintf
1345 (stderr,
1346 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1347 file, line, func, expected_mode_str, decl_name (mode));
1348 exit (1);
1352 #define REGEXP_UNIT(r) __extension__ \
1353 (({ struct regexp *_regexp = (r); \
1354 if (_regexp->mode != rm_unit) \
1355 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1356 __FILE__, __LINE__, __FUNCTION__); \
1357 &(_regexp)->regexp.unit; }))
1359 #define REGEXP_RESERV(r) __extension__ \
1360 (({ struct regexp *_regexp = (r); \
1361 if (_regexp->mode != rm_reserv) \
1362 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1363 __FILE__, __LINE__, __FUNCTION__); \
1364 &(_regexp)->regexp.reserv; }))
1366 #define REGEXP_SEQUENCE(r) __extension__ \
1367 (({ struct regexp *_regexp = (r); \
1368 if (_regexp->mode != rm_sequence) \
1369 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1370 __FILE__, __LINE__, __FUNCTION__); \
1371 &(_regexp)->regexp.sequence; }))
1373 #define REGEXP_REPEAT(r) __extension__ \
1374 (({ struct regexp *_regexp = (r); \
1375 if (_regexp->mode != rm_repeat) \
1376 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1377 __FILE__, __LINE__, __FUNCTION__); \
1378 &(_regexp)->regexp.repeat; }))
1380 #define REGEXP_ALLOF(r) __extension__ \
1381 (({ struct regexp *_regexp = (r); \
1382 if (_regexp->mode != rm_allof) \
1383 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1384 __FILE__, __LINE__, __FUNCTION__); \
1385 &(_regexp)->regexp.allof; }))
1387 #define REGEXP_ONEOF(r) __extension__ \
1388 (({ struct regexp *_regexp = (r); \
1389 if (_regexp->mode != rm_oneof) \
1390 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1391 __FILE__, __LINE__, __FUNCTION__); \
1392 &(_regexp)->regexp.oneof; }))
1394 static const char *regexp_name PARAMS ((enum regexp_mode));
1395 static void regexp_mode_check_failed PARAMS ((enum regexp_mode, const char *,
1396 const char *, int,
1397 const char *));
1400 /* Return string representation of regexp mode MODE. */
1401 static const char *
1402 regexp_name (mode)
1403 enum regexp_mode mode;
1405 static char str [100];
1407 if (mode == rm_unit)
1408 return "rm_unit";
1409 else if (mode == rm_reserv)
1410 return "rm_reserv";
1411 else if (mode == rm_nothing)
1412 return "rm_nothing";
1413 else if (mode == rm_sequence)
1414 return "rm_sequence";
1415 else if (mode == rm_repeat)
1416 return "rm_repeat";
1417 else if (mode == rm_allof)
1418 return "rm_allof";
1419 else if (mode == rm_oneof)
1420 return "rm_oneof";
1421 else
1422 sprintf (str, "unknown (%d)", (int) mode);
1423 return str;
1426 /* The function prints message about unexpected regexp and finish the
1427 program. */
1428 static void
1429 regexp_mode_check_failed (mode, expected_mode_str, file, line, func)
1430 enum regexp_mode mode;
1431 const char *expected_mode_str;
1432 const char *file;
1433 int line;
1434 const char *func;
1436 fprintf
1437 (stderr,
1438 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1439 file, line, func, expected_mode_str, regexp_name (mode));
1440 exit (1);
1443 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1445 #define DECL_UNIT(d) (&(d)->decl.unit)
1446 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1447 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1448 #define DECL_EXCL(d) (&(d)->decl.excl)
1449 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1450 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1451 #define DECL_RESERV(d) (&(d)->decl.reserv)
1452 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1454 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1455 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1456 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1457 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1458 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1459 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1461 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1463 /* Create IR structure (node). */
1464 static void *
1465 create_node (size)
1466 size_t size;
1468 void *result;
1470 obstack_blank (&irp, size);
1471 result = obstack_base (&irp);
1472 obstack_finish (&irp);
1473 /* Default values of members are NULL and zero. */
1474 memset (result, 0, size);
1475 return result;
1478 /* Copy IR structure (node). */
1479 static void *
1480 copy_node (from, size)
1481 void *from;
1482 size_t size;
1484 void *result;
1485 result = create_node (size);
1486 memcpy (result, from, size);
1487 return result;
1490 /* The function checks that NAME does not contain quotes (`"'). */
1491 static char *
1492 check_name (name, pos)
1493 char * name;
1494 pos_t pos ATTRIBUTE_UNUSED;
1496 char *str;
1498 for (str = name; *str != '\0'; str++)
1499 if (*str == '\"')
1500 error ("Name `%s' contains quotes", name);
1501 return name;
1504 /* Pointers top all declartions during IR generation are stored in the
1505 following. */
1506 static vla_ptr_t decls;
1508 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1509 string containing the next separated element, taking parentheses
1510 into account if PAR_FLAG has nonzero value. Advance the pointer to
1511 after the string scanned, or the end-of-string. Return NULL if at
1512 end of string. */
1513 static char *
1514 next_sep_el (pstr, sep, par_flag)
1515 char **pstr;
1516 int sep;
1517 int par_flag;
1519 char *out_str;
1520 char *p;
1521 int pars_num;
1522 int n_spaces;
1524 /* Remove leading whitespaces. */
1525 while (ISSPACE ((int) **pstr))
1526 (*pstr)++;
1528 if (**pstr == '\0')
1529 return NULL;
1531 n_spaces = 0;
1532 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1534 if (par_flag && *p == '(')
1535 pars_num++;
1536 else if (par_flag && *p == ')')
1537 pars_num--;
1538 else if (pars_num == 0 && *p == sep)
1539 break;
1540 if (pars_num == 0 && ISSPACE ((int) *p))
1541 n_spaces++;
1542 else
1544 for (; n_spaces != 0; n_spaces--)
1545 obstack_1grow (&irp, p [-n_spaces]);
1546 obstack_1grow (&irp, *p);
1549 obstack_1grow (&irp, '\0');
1550 out_str = obstack_base (&irp);
1551 obstack_finish (&irp);
1553 *pstr = p;
1554 if (**pstr == sep)
1555 (*pstr)++;
1557 return out_str;
1560 /* Given a string and a separator, return the number of separated
1561 elements in it, taking parentheses into account if PAR_FLAG has
1562 nonzero value. Return 0 for the null string, -1 if parantheses is
1563 not balanced. */
1564 static int
1565 n_sep_els (s, sep, par_flag)
1566 char *s;
1567 int sep;
1568 int par_flag;
1570 int n;
1571 int pars_num;
1573 if (*s == '\0')
1574 return 0;
1576 for (pars_num = 0, n = 1; *s; s++)
1577 if (par_flag && *s == '(')
1578 pars_num++;
1579 else if (par_flag && *s == ')')
1580 pars_num--;
1581 else if (pars_num == 0 && *s == sep)
1582 n++;
1584 return (pars_num != 0 ? -1 : n);
1587 /* Given a string and a separator, return vector of strings which are
1588 elements in the string and number of elements through els_num.
1589 Take parentheses into account if PAR_FLAG has nonzero value.
1590 Return 0 for the null string, -1 if parantheses are not balanced. */
1591 static char **
1592 get_str_vect (str, els_num, sep, par_flag)
1593 char *str;
1594 int *els_num;
1595 int sep;
1596 int par_flag;
1598 int i;
1599 char **vect;
1600 char **pstr;
1602 *els_num = n_sep_els (str, sep, par_flag);
1603 if (*els_num <= 0)
1604 return NULL;
1605 obstack_blank (&irp, sizeof (char *) * (*els_num));
1606 vect = (char **) obstack_base (&irp);
1607 obstack_finish (&irp);
1608 pstr = &str;
1609 for (i = 0; i < *els_num; i++)
1610 vect [i] = next_sep_el (pstr, sep, par_flag);
1611 if (next_sep_el (pstr, sep, par_flag) != NULL)
1612 abort ();
1613 return vect;
1616 /* Process a DEFINE_CPU_UNIT.
1618 This gives information about a unit contained in CPU. We fill a
1619 struct unit_decl with information used later by `expand_automata'. */
1620 void
1621 gen_cpu_unit (def)
1622 rtx def;
1624 decl_t decl;
1625 char **str_cpu_units;
1626 int vect_length;
1627 int i;
1629 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1630 if (str_cpu_units == NULL)
1631 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1632 for (i = 0; i < vect_length; i++)
1634 decl = create_node (sizeof (struct decl));
1635 decl->mode = dm_unit;
1636 decl->pos = 0;
1637 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1638 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1639 DECL_UNIT (decl)->query_p = 0;
1640 VLA_PTR_ADD (decls, decl);
1641 num_dfa_decls++;
1645 /* Process a DEFINE_QUERY_CPU_UNIT.
1647 This gives information about a unit contained in CPU. We fill a
1648 struct unit_decl with information used later by `expand_automata'. */
1649 void
1650 gen_query_cpu_unit (def)
1651 rtx def;
1653 decl_t decl;
1654 char **str_cpu_units;
1655 int vect_length;
1656 int i;
1658 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1659 if (str_cpu_units == NULL)
1660 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1661 for (i = 0; i < vect_length; i++)
1663 decl = create_node (sizeof (struct decl));
1664 decl->mode = dm_unit;
1665 decl->pos = 0;
1666 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1667 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1668 DECL_UNIT (decl)->query_p = 1;
1669 VLA_PTR_ADD (decls, decl);
1670 num_dfa_decls++;
1674 /* Process a DEFINE_BYPASS.
1676 This gives information about a unit contained in the CPU. We fill
1677 in a struct bypass_decl with information used later by
1678 `expand_automata'. */
1679 void
1680 gen_bypass (def)
1681 rtx def;
1683 decl_t decl;
1684 char **out_insns;
1685 int out_length;
1686 char **in_insns;
1687 int in_length;
1688 int i, j;
1690 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', 0);
1691 if (out_insns == NULL)
1692 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1693 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', 0);
1694 if (in_insns == NULL)
1695 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1696 for (i = 0; i < out_length; i++)
1697 for (j = 0; j < in_length; j++)
1699 decl = create_node (sizeof (struct decl));
1700 decl->mode = dm_bypass;
1701 decl->pos = 0;
1702 DECL_BYPASS (decl)->latency = XINT (def, 0);
1703 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1704 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1705 DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
1706 VLA_PTR_ADD (decls, decl);
1707 num_dfa_decls++;
1711 /* Process an EXCLUSION_SET.
1713 This gives information about a cpu unit conflicts. We fill a
1714 struct unit_rel_decl (excl) with information used later by
1715 `expand_automata'. */
1716 void
1717 gen_excl_set (def)
1718 rtx def;
1720 decl_t decl;
1721 char **first_str_cpu_units;
1722 char **second_str_cpu_units;
1723 int first_vect_length;
1724 int length;
1725 int i;
1727 first_str_cpu_units
1728 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1729 if (first_str_cpu_units == NULL)
1730 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1731 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1733 if (second_str_cpu_units == NULL)
1734 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1735 length += first_vect_length;
1736 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1737 decl->mode = dm_excl;
1738 decl->pos = 0;
1739 DECL_EXCL (decl)->names_num = length;
1740 DECL_EXCL (decl)->first_list_length = first_vect_length;
1741 for (i = 0; i < length; i++)
1742 if (i < first_vect_length)
1743 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1744 else
1745 DECL_EXCL (decl)->names [i]
1746 = second_str_cpu_units [i - first_vect_length];
1747 VLA_PTR_ADD (decls, decl);
1748 num_dfa_decls++;
1751 /* Process a PRESENCE_SET.
1753 This gives information about a cpu unit reservation requirements.
1754 We fill a struct unit_rel_decl (presence) with information used
1755 later by `expand_automata'. */
1756 void
1757 gen_presence_set (def)
1758 rtx def;
1760 decl_t decl;
1761 char **first_str_cpu_units;
1762 char **second_str_cpu_units;
1763 int first_vect_length;
1764 int length;
1765 int i;
1767 first_str_cpu_units
1768 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1769 if (first_str_cpu_units == NULL)
1770 fatal ("invalid first string `%s' in presence_set", XSTR (def, 0));
1771 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1773 if (second_str_cpu_units == NULL)
1774 fatal ("invalid second string `%s' in presence_set", XSTR (def, 1));
1775 length += first_vect_length;
1776 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1777 decl->mode = dm_presence;
1778 decl->pos = 0;
1779 DECL_PRESENCE (decl)->names_num = length;
1780 DECL_PRESENCE (decl)->first_list_length = first_vect_length;
1781 for (i = 0; i < length; i++)
1782 if (i < first_vect_length)
1783 DECL_PRESENCE (decl)->names [i] = first_str_cpu_units [i];
1784 else
1785 DECL_PRESENCE (decl)->names [i]
1786 = second_str_cpu_units [i - first_vect_length];
1787 VLA_PTR_ADD (decls, decl);
1788 num_dfa_decls++;
1791 /* Process an ABSENCE_SET.
1793 This gives information about a cpu unit reservation requirements.
1794 We fill a struct unit_rel_decl (absence) with information used
1795 later by `expand_automata'. */
1796 void
1797 gen_absence_set (def)
1798 rtx def;
1800 decl_t decl;
1801 char **first_str_cpu_units;
1802 char **second_str_cpu_units;
1803 int first_vect_length;
1804 int length;
1805 int i;
1807 first_str_cpu_units
1808 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1809 if (first_str_cpu_units == NULL)
1810 fatal ("invalid first string `%s' in absence_set", XSTR (def, 0));
1811 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1813 if (second_str_cpu_units == NULL)
1814 fatal ("invalid second string `%s' in absence_set", XSTR (def, 1));
1815 length += first_vect_length;
1816 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1817 decl->mode = dm_absence;
1818 decl->pos = 0;
1819 DECL_ABSENCE (decl)->names_num = length;
1820 DECL_ABSENCE (decl)->first_list_length = first_vect_length;
1821 for (i = 0; i < length; i++)
1822 if (i < first_vect_length)
1823 DECL_ABSENCE (decl)->names [i] = first_str_cpu_units [i];
1824 else
1825 DECL_ABSENCE (decl)->names [i]
1826 = second_str_cpu_units [i - first_vect_length];
1827 VLA_PTR_ADD (decls, decl);
1828 num_dfa_decls++;
1831 /* Process a DEFINE_AUTOMATON.
1833 This gives information about a finite state automaton used for
1834 recognizing pipeline hazards. We fill a struct automaton_decl
1835 with information used later by `expand_automata'. */
1836 void
1837 gen_automaton (def)
1838 rtx def;
1840 decl_t decl;
1841 char **str_automata;
1842 int vect_length;
1843 int i;
1845 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1846 if (str_automata == NULL)
1847 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1848 for (i = 0; i < vect_length; i++)
1850 decl = create_node (sizeof (struct decl));
1851 decl->mode = dm_automaton;
1852 decl->pos = 0;
1853 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1854 VLA_PTR_ADD (decls, decl);
1855 num_dfa_decls++;
1859 /* Process an AUTOMATA_OPTION.
1861 This gives information how to generate finite state automaton used
1862 for recognizing pipeline hazards. */
1863 void
1864 gen_automata_option (def)
1865 rtx def;
1867 if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1868 no_minimization_flag = 1;
1869 else if (strcmp ((char *) XSTR (def, 0), TIME_OPTION + 1) == 0)
1870 time_flag = 1;
1871 else if (strcmp ((char *) XSTR (def, 0), V_OPTION + 1) == 0)
1872 v_flag = 1;
1873 else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
1874 w_flag = 1;
1875 else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
1876 ndfa_flag = 1;
1877 else
1878 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1881 /* Name in reservation to denote absence reservation. */
1882 #define NOTHING_NAME "nothing"
1884 /* The following string contains original reservation string being
1885 parsed. */
1886 static char *reserv_str;
1888 /* Parse an element in STR. */
1889 static regexp_t
1890 gen_regexp_el (str)
1891 char *str;
1893 regexp_t regexp;
1894 int len;
1896 if (*str == '(')
1898 len = strlen (str);
1899 if (str [len - 1] != ')')
1900 fatal ("garbage after ) in reservation `%s'", reserv_str);
1901 str [len - 1] = '\0';
1902 regexp = gen_regexp_sequence (str + 1);
1904 else if (strcmp (str, NOTHING_NAME) == 0)
1906 regexp = create_node (sizeof (struct decl));
1907 regexp->mode = rm_nothing;
1909 else
1911 regexp = create_node (sizeof (struct decl));
1912 regexp->mode = rm_unit;
1913 REGEXP_UNIT (regexp)->name = str;
1915 return regexp;
1918 /* Parse construction `repeat' in STR. */
1919 static regexp_t
1920 gen_regexp_repeat (str)
1921 char *str;
1923 regexp_t regexp;
1924 regexp_t repeat;
1925 char **repeat_vect;
1926 int els_num;
1927 int i;
1929 repeat_vect = get_str_vect (str, &els_num, '*', 1);
1930 if (repeat_vect == NULL)
1931 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1932 if (els_num > 1)
1934 regexp = gen_regexp_el (repeat_vect [0]);
1935 for (i = 1; i < els_num; i++)
1937 repeat = create_node (sizeof (struct regexp));
1938 repeat->mode = rm_repeat;
1939 REGEXP_REPEAT (repeat)->regexp = regexp;
1940 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1941 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1942 fatal ("repetition `%s' <= 1 in reservation `%s'",
1943 str, reserv_str);
1944 regexp = repeat;
1946 return regexp;
1948 else
1949 return gen_regexp_el (str);
1952 /* Parse reservation STR which possibly contains separator '+'. */
1953 static regexp_t
1954 gen_regexp_allof (str)
1955 char *str;
1957 regexp_t allof;
1958 char **allof_vect;
1959 int els_num;
1960 int i;
1962 allof_vect = get_str_vect (str, &els_num, '+', 1);
1963 if (allof_vect == NULL)
1964 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1965 if (els_num > 1)
1967 allof = create_node (sizeof (struct regexp)
1968 + sizeof (regexp_t) * (els_num - 1));
1969 allof->mode = rm_allof;
1970 REGEXP_ALLOF (allof)->regexps_num = els_num;
1971 for (i = 0; i < els_num; i++)
1972 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1973 return allof;
1975 else
1976 return gen_regexp_repeat (str);
1979 /* Parse reservation STR which possibly contains separator '|'. */
1980 static regexp_t
1981 gen_regexp_oneof (str)
1982 char *str;
1984 regexp_t oneof;
1985 char **oneof_vect;
1986 int els_num;
1987 int i;
1989 oneof_vect = get_str_vect (str, &els_num, '|', 1);
1990 if (oneof_vect == NULL)
1991 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1992 if (els_num > 1)
1994 oneof = create_node (sizeof (struct regexp)
1995 + sizeof (regexp_t) * (els_num - 1));
1996 oneof->mode = rm_oneof;
1997 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1998 for (i = 0; i < els_num; i++)
1999 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
2000 return oneof;
2002 else
2003 return gen_regexp_allof (str);
2006 /* Parse reservation STR which possibly contains separator ','. */
2007 static regexp_t
2008 gen_regexp_sequence (str)
2009 char *str;
2011 regexp_t sequence;
2012 char **sequence_vect;
2013 int els_num;
2014 int i;
2016 sequence_vect = get_str_vect (str, &els_num, ',', 1);
2017 if (els_num > 1)
2019 sequence = create_node (sizeof (struct regexp)
2020 + sizeof (regexp_t) * (els_num - 1));
2021 sequence->mode = rm_sequence;
2022 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2023 for (i = 0; i < els_num; i++)
2024 REGEXP_SEQUENCE (sequence)->regexps [i]
2025 = gen_regexp_oneof (sequence_vect [i]);
2026 return sequence;
2028 else
2029 return gen_regexp_oneof (str);
2032 /* Parse construction reservation STR. */
2033 static regexp_t
2034 gen_regexp (str)
2035 char *str;
2037 reserv_str = str;
2038 return gen_regexp_sequence (str);;
2041 /* Process a DEFINE_RESERVATION.
2043 This gives information about a reservation of cpu units. We fill
2044 in a struct reserv_decl with information used later by
2045 `expand_automata'. */
2046 void
2047 gen_reserv (def)
2048 rtx def;
2050 decl_t decl;
2052 decl = create_node (sizeof (struct decl));
2053 decl->mode = dm_reserv;
2054 decl->pos = 0;
2055 DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2056 DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2057 VLA_PTR_ADD (decls, decl);
2058 num_dfa_decls++;
2061 /* Process a DEFINE_INSN_RESERVATION.
2063 This gives information about the reservation of cpu units by an
2064 insn. We fill a struct insn_reserv_decl with information used
2065 later by `expand_automata'. */
2066 void
2067 gen_insn_reserv (def)
2068 rtx def;
2070 decl_t decl;
2072 decl = create_node (sizeof (struct decl));
2073 decl->mode = dm_insn_reserv;
2074 decl->pos = 0;
2075 DECL_INSN_RESERV (decl)->name
2076 = check_name ((char *) XSTR (def, 0), decl->pos);
2077 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2078 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2079 DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2080 VLA_PTR_ADD (decls, decl);
2081 num_dfa_decls++;
2086 /* The function evaluates hash value (0..UINT_MAX) of string. */
2087 static unsigned
2088 string_hash (string)
2089 const char *string;
2091 unsigned result, i;
2093 for (result = i = 0;*string++ != '\0'; i++)
2094 result += ((unsigned char) *string << (i % CHAR_BIT));
2095 return result;
2100 /* This page contains abstract data `table of automaton declarations'.
2101 Elements of the table is nodes representing automaton declarations.
2102 Key of the table elements is name of given automaton. Rememeber
2103 that automaton names have own space. */
2105 /* The function evaluates hash value of an automaton declaration. The
2106 function is used by abstract data `hashtab'. The function returns
2107 hash value (0..UINT_MAX) of given automaton declaration. */
2108 static unsigned
2109 automaton_decl_hash (automaton_decl)
2110 const void *automaton_decl;
2112 const decl_t decl = (decl_t) automaton_decl;
2114 if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
2115 abort ();
2116 return string_hash (DECL_AUTOMATON (decl)->name);
2119 /* The function tests automaton declarations on equality of their
2120 keys. The function is used by abstract data `hashtab'. The
2121 function returns 1 if the declarations have the same key, 0
2122 otherwise. */
2123 static int
2124 automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
2125 const void* automaton_decl_1;
2126 const void* automaton_decl_2;
2128 const decl_t decl1 = (decl_t) automaton_decl_1;
2129 const decl_t decl2 = (decl_t) automaton_decl_2;
2131 if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
2132 || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
2133 abort ();
2134 return strcmp (DECL_AUTOMATON (decl1)->name,
2135 DECL_AUTOMATON (decl2)->name) == 0;
2138 /* The automaton declaration table itself is represented by the
2139 following variable. */
2140 static htab_t automaton_decl_table;
2142 /* The function inserts automaton declaration into the table. The
2143 function does nothing if an automaton declaration with the same key
2144 exists already in the table. The function returns automaton
2145 declaration node in the table with the same key as given automaton
2146 declaration node. */
2147 static decl_t
2148 insert_automaton_decl (automaton_decl)
2149 decl_t automaton_decl;
2151 void **entry_ptr;
2153 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
2154 if (*entry_ptr == NULL)
2155 *entry_ptr = (void *) automaton_decl;
2156 return (decl_t) *entry_ptr;
2159 /* The following variable value is node representing automaton
2160 declaration. The node used for searching automaton declaration
2161 with given name. */
2162 static struct decl work_automaton_decl;
2164 /* The function searches for automaton declaration in the table with
2165 the same key as node representing name of the automaton
2166 declaration. The function returns node found in the table, NULL if
2167 such node does not exist in the table. */
2168 static decl_t
2169 find_automaton_decl (name)
2170 char *name;
2172 void *entry;
2174 work_automaton_decl.mode = dm_automaton;
2175 DECL_AUTOMATON (&work_automaton_decl)->name = name;
2176 entry = htab_find (automaton_decl_table, &work_automaton_decl);
2177 return (decl_t) entry;
2180 /* The function creates empty automaton declaration table and node
2181 representing automaton declaration and used for searching automaton
2182 declaration with given name. The function must be called only once
2183 before any work with the automaton declaration table. */
2184 static void
2185 initiate_automaton_decl_table ()
2187 work_automaton_decl.mode = dm_automaton;
2188 automaton_decl_table = htab_create (10, automaton_decl_hash,
2189 automaton_decl_eq_p, (htab_del) 0);
2192 /* The function deletes the automaton declaration table. Only call of
2193 function `initiate_automaton_decl_table' is possible immediately
2194 after this function call. */
2195 static void
2196 finish_automaton_decl_table ()
2198 htab_delete (automaton_decl_table);
2203 /* This page contains abstract data `table of insn declarations'.
2204 Elements of the table is nodes representing insn declarations. Key
2205 of the table elements is name of given insn (in corresponding
2206 define_insn_reservation). Rememeber that insn names have own
2207 space. */
2209 /* The function evaluates hash value of an insn declaration. The
2210 function is used by abstract data `hashtab'. The function returns
2211 hash value (0..UINT_MAX) of given insn declaration. */
2212 static unsigned
2213 insn_decl_hash (insn_decl)
2214 const void *insn_decl;
2216 const decl_t decl = (decl_t) insn_decl;
2218 if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
2219 abort ();
2220 return string_hash (DECL_INSN_RESERV (decl)->name);
2223 /* The function tests insn declarations on equality of their keys.
2224 The function is used by abstract data `hashtab'. The function
2225 returns 1 if declarations have the same key, 0 otherwise. */
2226 static int
2227 insn_decl_eq_p (insn_decl_1, insn_decl_2)
2228 const void *insn_decl_1;
2229 const void *insn_decl_2;
2231 const decl_t decl1 = (decl_t) insn_decl_1;
2232 const decl_t decl2 = (decl_t) insn_decl_2;
2234 if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
2235 || decl2->mode != dm_insn_reserv
2236 || DECL_INSN_RESERV (decl2)->name == NULL)
2237 abort ();
2238 return strcmp (DECL_INSN_RESERV (decl1)->name,
2239 DECL_INSN_RESERV (decl2)->name) == 0;
2242 /* The insn declaration table itself is represented by the following
2243 variable. The table does not contain insn reservation
2244 declarations. */
2245 static htab_t insn_decl_table;
2247 /* The function inserts insn declaration into the table. The function
2248 does nothing if an insn declaration with the same key exists
2249 already in the table. The function returns insn declaration node
2250 in the table with the same key as given insn declaration node. */
2251 static decl_t
2252 insert_insn_decl (insn_decl)
2253 decl_t insn_decl;
2255 void **entry_ptr;
2257 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2258 if (*entry_ptr == NULL)
2259 *entry_ptr = (void *) insn_decl;
2260 return (decl_t) *entry_ptr;
2263 /* The following variable value is node representing insn reservation
2264 declaration. The node used for searching insn reservation
2265 declaration with given name. */
2266 static struct decl work_insn_decl;
2268 /* The function searches for insn reservation declaration in the table
2269 with the same key as node representing name of the insn reservation
2270 declaration. The function returns node found in the table, NULL if
2271 such node does not exist in the table. */
2272 static decl_t
2273 find_insn_decl (name)
2274 char *name;
2276 void *entry;
2278 work_insn_decl.mode = dm_insn_reserv;
2279 DECL_INSN_RESERV (&work_insn_decl)->name = name;
2280 entry = htab_find (insn_decl_table, &work_insn_decl);
2281 return (decl_t) entry;
2284 /* The function creates empty insn declaration table and node
2285 representing insn declaration and used for searching insn
2286 declaration with given name. The function must be called only once
2287 before any work with the insn declaration table. */
2288 static void
2289 initiate_insn_decl_table ()
2291 work_insn_decl.mode = dm_insn_reserv;
2292 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2293 (htab_del) 0);
2296 /* The function deletes the insn declaration table. Only call of
2297 function `initiate_insn_decl_table' is possible immediately after
2298 this function call. */
2299 static void
2300 finish_insn_decl_table ()
2302 htab_delete (insn_decl_table);
2307 /* This page contains abstract data `table of declarations'. Elements
2308 of the table is nodes representing declarations (of units and
2309 reservations). Key of the table elements is names of given
2310 declarations. */
2312 /* The function evaluates hash value of a declaration. The function
2313 is used by abstract data `hashtab'. The function returns hash
2314 value (0..UINT_MAX) of given declaration. */
2315 static unsigned
2316 decl_hash (decl)
2317 const void *decl;
2319 const decl_t d = (const decl_t) decl;
2321 if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
2322 && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
2323 abort ();
2324 return string_hash (d->mode == dm_unit
2325 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
2328 /* The function tests declarations on equality of their keys. The
2329 function is used by abstract data `hashtab'. The function
2330 returns 1 if the declarations have the same key, 0 otherwise. */
2331 static int
2332 decl_eq_p (decl_1, decl_2)
2333 const void *decl_1;
2334 const void *decl_2;
2336 const decl_t d1 = (const decl_t) decl_1;
2337 const decl_t d2 = (const decl_t) decl_2;
2339 if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
2340 && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
2341 || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
2342 && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
2343 abort ();
2344 return strcmp ((d1->mode == dm_unit
2345 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
2346 (d2->mode == dm_unit
2347 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2350 /* The declaration table itself is represented by the following
2351 variable. */
2352 static htab_t decl_table;
2354 /* The function inserts declaration into the table. The function does
2355 nothing if a declaration with the same key exists already in the
2356 table. The function returns declaration node in the table with the
2357 same key as given declaration node. */
2359 static decl_t
2360 insert_decl (decl)
2361 decl_t decl;
2363 void **entry_ptr;
2365 entry_ptr = htab_find_slot (decl_table, decl, 1);
2366 if (*entry_ptr == NULL)
2367 *entry_ptr = (void *) decl;
2368 return (decl_t) *entry_ptr;
2371 /* The following variable value is node representing declaration. The
2372 node used for searching declaration with given name. */
2373 static struct decl work_decl;
2375 /* The function searches for declaration in the table with the same
2376 key as node representing name of the declaration. The function
2377 returns node found in the table, NULL if such node does not exist
2378 in the table. */
2379 static decl_t
2380 find_decl (name)
2381 char *name;
2383 void *entry;
2385 work_decl.mode = dm_unit;
2386 DECL_UNIT (&work_decl)->name = name;
2387 entry = htab_find (decl_table, &work_decl);
2388 return (decl_t) entry;
2391 /* The function creates empty declaration table and node representing
2392 declaration and used for searching declaration with given name.
2393 The function must be called only once before any work with the
2394 declaration table. */
2395 static void
2396 initiate_decl_table ()
2398 work_decl.mode = dm_unit;
2399 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2402 /* The function deletes the declaration table. Only call of function
2403 `initiate_declaration_table' is possible immediately after this
2404 function call. */
2405 static void
2406 finish_decl_table ()
2408 htab_delete (decl_table);
2413 /* This page contains checker of pipeline hazard description. */
2415 /* Checking NAMES in an exclusion clause vector and returning formed
2416 unit_set_el_list. */
2417 static unit_set_el_t
2418 process_excls (names, num, excl_pos)
2419 char **names;
2420 int num;
2421 pos_t excl_pos ATTRIBUTE_UNUSED;
2423 unit_set_el_t el_list;
2424 unit_set_el_t last_el;
2425 unit_set_el_t new_el;
2426 decl_t decl_in_table;
2427 int i;
2429 el_list = NULL;
2430 last_el = NULL;
2431 for (i = 0; i < num; i++)
2433 decl_in_table = find_decl (names [i]);
2434 if (decl_in_table == NULL)
2435 error ("unit `%s' in exclusion is not declared", names [i]);
2436 else if (decl_in_table->mode != dm_unit)
2437 error ("`%s' in exclusion is not unit", names [i]);
2438 else
2440 new_el = create_node (sizeof (struct unit_set_el));
2441 new_el->unit_decl = DECL_UNIT (decl_in_table);
2442 new_el->next_unit_set_el = NULL;
2443 if (last_el == NULL)
2444 el_list = last_el = new_el;
2445 else
2447 last_el->next_unit_set_el = new_el;
2448 last_el = last_el->next_unit_set_el;
2452 return el_list;
2455 /* The function adds each element from SOURCE_LIST to the exclusion
2456 list of the each element from DEST_LIST. Checking situation "unit
2457 excludes itself". */
2458 static void
2459 add_excls (dest_list, source_list, excl_pos)
2460 unit_set_el_t dest_list;
2461 unit_set_el_t source_list;
2462 pos_t excl_pos ATTRIBUTE_UNUSED;
2464 unit_set_el_t dst;
2465 unit_set_el_t src;
2466 unit_set_el_t curr_el;
2467 unit_set_el_t prev_el;
2468 unit_set_el_t copy;
2470 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2471 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2473 if (dst->unit_decl == src->unit_decl)
2475 error ("unit `%s' excludes itself", src->unit_decl->name);
2476 continue;
2478 if (dst->unit_decl->automaton_name != NULL
2479 && src->unit_decl->automaton_name != NULL
2480 && strcmp (dst->unit_decl->automaton_name,
2481 src->unit_decl->automaton_name) != 0)
2483 error ("units `%s' and `%s' in exclusion set belong to different automata",
2484 src->unit_decl->name, dst->unit_decl->name);
2485 continue;
2487 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2488 curr_el != NULL;
2489 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2490 if (curr_el->unit_decl == src->unit_decl)
2491 break;
2492 if (curr_el == NULL)
2494 /* Element not found - insert. */
2495 copy = copy_node (src, sizeof (*src));
2496 copy->next_unit_set_el = NULL;
2497 if (prev_el == NULL)
2498 dst->unit_decl->excl_list = copy;
2499 else
2500 prev_el->next_unit_set_el = copy;
2505 /* Checking NAMES in an presence clause vector and returning formed
2506 unit_set_el_list. The function is called only after processing all
2507 exclusion sets. */
2508 static unit_set_el_t
2509 process_presence_absence (names, num, req_pos, presence_p)
2510 char **names;
2511 int num;
2512 pos_t req_pos ATTRIBUTE_UNUSED;
2513 int presence_p;
2515 unit_set_el_t el_list;
2516 unit_set_el_t last_el;
2517 unit_set_el_t new_el;
2518 decl_t decl_in_table;
2519 int i;
2521 el_list = NULL;
2522 last_el = NULL;
2523 for (i = 0; i < num; i++)
2525 decl_in_table = find_decl (names [i]);
2526 if (decl_in_table == NULL)
2527 error ((presence_p
2528 ? "unit `%s' in presence set is not declared"
2529 : "unit `%s' in absence set is not declared"), names [i]);
2530 else if (decl_in_table->mode != dm_unit)
2531 error ((presence_p
2532 ? "`%s' in presence set is not unit"
2533 : "`%s' in absence set is not unit"), names [i]);
2534 else
2536 new_el = create_node (sizeof (struct unit_set_el));
2537 new_el->unit_decl = DECL_UNIT (decl_in_table);
2538 new_el->next_unit_set_el = NULL;
2539 if (last_el == NULL)
2540 el_list = last_el = new_el;
2541 else
2543 last_el->next_unit_set_el = new_el;
2544 last_el = last_el->next_unit_set_el;
2548 return el_list;
2551 /* The function adds each element from SOURCE_LIST to presence (if
2552 PRESENCE_P) or absence list of the each element from DEST_LIST.
2553 Checking situations "unit requires own presence", "unit requires
2554 own absence", and "unit excludes and requires presence of ...".
2555 Remember that we process absence sets only after all presence
2556 sets. */
2557 static void
2558 add_presence_absence (dest_list, source_list, req_pos, presence_p)
2559 unit_set_el_t dest_list;
2560 unit_set_el_t source_list;
2561 pos_t req_pos ATTRIBUTE_UNUSED;
2562 int presence_p;
2564 unit_set_el_t dst;
2565 unit_set_el_t src;
2566 unit_set_el_t curr_el;
2567 unit_set_el_t prev_el;
2568 unit_set_el_t copy;
2570 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2571 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2573 if (dst->unit_decl == src->unit_decl)
2575 error ((presence_p
2576 ? "unit `%s' requires own presence"
2577 : "unit `%s' requires own absence"), src->unit_decl->name);
2578 continue;
2580 if (dst->unit_decl->automaton_name != NULL
2581 && src->unit_decl->automaton_name != NULL
2582 && strcmp (dst->unit_decl->automaton_name,
2583 src->unit_decl->automaton_name) != 0)
2585 error ((presence_p
2586 ? "units `%s' and `%s' in presence set belong to different automata"
2587 : "units `%s' and `%s' in absence set belong to different automata"),
2588 src->unit_decl->name, dst->unit_decl->name);
2589 continue;
2591 for (curr_el = (presence_p
2592 ? dst->unit_decl->presence_list
2593 : dst->unit_decl->absence_list), prev_el = NULL;
2594 curr_el != NULL;
2595 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2596 if (curr_el->unit_decl == src->unit_decl)
2597 break;
2598 if (curr_el == NULL)
2600 /* Element not found - insert if there is no error. */
2601 int no_error_flag = 1;
2603 if (presence_p)
2604 for (curr_el = dst->unit_decl->excl_list;
2605 curr_el != NULL;
2606 curr_el = curr_el->next_unit_set_el)
2608 if (src->unit_decl == curr_el->unit_decl)
2610 if (!w_flag)
2612 error
2613 ("unit `%s' excludes and requires presence of `%s'",
2614 dst->unit_decl->name, src->unit_decl->name);
2615 no_error_flag = 0;
2617 else
2618 warning
2619 ("unit `%s' excludes and requires presence of `%s'",
2620 dst->unit_decl->name, src->unit_decl->name);
2623 else
2624 for (curr_el = dst->unit_decl->presence_list;
2625 curr_el != NULL;
2626 curr_el = curr_el->next_unit_set_el)
2628 if (src->unit_decl == curr_el->unit_decl)
2630 if (!w_flag)
2632 error
2633 ("unit `%s' requires absence and presence of `%s'",
2634 dst->unit_decl->name, src->unit_decl->name);
2635 no_error_flag = 0;
2637 else
2638 warning
2639 ("unit `%s' requires absence and presence of `%s'",
2640 dst->unit_decl->name, src->unit_decl->name);
2643 if (no_error_flag)
2645 copy = copy_node (src, sizeof (*src));
2646 copy->next_unit_set_el = NULL;
2647 if (prev_el == NULL)
2649 if (presence_p)
2650 dst->unit_decl->presence_list = copy;
2651 else
2652 dst->unit_decl->absence_list = copy;
2654 else
2655 prev_el->next_unit_set_el = copy;
2661 /* The function searches for bypass with given IN_INSN_RESERV in given
2662 BYPASS_LIST. */
2663 static struct bypass_decl *
2664 find_bypass (bypass_list, in_insn_reserv)
2665 struct bypass_decl *bypass_list;
2666 struct insn_reserv_decl *in_insn_reserv;
2668 struct bypass_decl *bypass;
2670 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2671 if (bypass->in_insn_reserv == in_insn_reserv)
2672 break;
2673 return bypass;
2676 /* The function processes pipeline description declarations, checks
2677 their correctness, and forms exclusion/presence/absence sets. */
2678 static void
2679 process_decls ()
2681 decl_t decl;
2682 decl_t automaton_decl;
2683 decl_t decl_in_table;
2684 decl_t out_insn_reserv;
2685 decl_t in_insn_reserv;
2686 struct bypass_decl *bypass;
2687 int automaton_presence;
2688 int i;
2690 /* Checking repeated automata declarations. */
2691 automaton_presence = 0;
2692 for (i = 0; i < description->decls_num; i++)
2694 decl = description->decls [i];
2695 if (decl->mode == dm_automaton)
2697 automaton_presence = 1;
2698 decl_in_table = insert_automaton_decl (decl);
2699 if (decl_in_table != decl)
2701 if (!w_flag)
2702 error ("repeated declaration of automaton `%s'",
2703 DECL_AUTOMATON (decl)->name);
2704 else
2705 warning ("repeated declaration of automaton `%s'",
2706 DECL_AUTOMATON (decl)->name);
2710 /* Checking undeclared automata, repeated declarations (except for
2711 automata) and correctness of their attributes (insn latency times
2712 etc.). */
2713 for (i = 0; i < description->decls_num; i++)
2715 decl = description->decls [i];
2716 if (decl->mode == dm_insn_reserv)
2718 DECL_INSN_RESERV (decl)->condexp
2719 = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
2720 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2721 error ("define_insn_reservation `%s' has negative latency time",
2722 DECL_INSN_RESERV (decl)->name);
2723 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2724 description->insns_num++;
2725 decl_in_table = insert_insn_decl (decl);
2726 if (decl_in_table != decl)
2727 error ("`%s' is already used as insn reservation name",
2728 DECL_INSN_RESERV (decl)->name);
2730 else if (decl->mode == dm_bypass)
2732 if (DECL_BYPASS (decl)->latency < 0)
2733 error ("define_bypass `%s - %s' has negative latency time",
2734 DECL_BYPASS (decl)->out_insn_name,
2735 DECL_BYPASS (decl)->in_insn_name);
2737 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2739 if (decl->mode == dm_unit)
2741 DECL_UNIT (decl)->automaton_decl = NULL;
2742 if (DECL_UNIT (decl)->automaton_name != NULL)
2744 automaton_decl
2745 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2746 if (automaton_decl == NULL)
2747 error ("automaton `%s' is not declared",
2748 DECL_UNIT (decl)->automaton_name);
2749 else
2751 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2752 DECL_UNIT (decl)->automaton_decl
2753 = DECL_AUTOMATON (automaton_decl);
2756 else if (automaton_presence)
2757 error ("define_unit `%s' without automaton when one defined",
2758 DECL_UNIT (decl)->name);
2759 DECL_UNIT (decl)->unit_num = description->units_num;
2760 description->units_num++;
2761 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2763 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2764 continue;
2766 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2768 else
2770 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2772 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2773 continue;
2775 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2777 if (decl_in_table == NULL)
2778 decl_in_table = insert_decl (decl);
2779 else
2781 if (decl->mode == dm_unit)
2782 error ("repeated declaration of unit `%s'",
2783 DECL_UNIT (decl)->name);
2784 else
2785 error ("repeated declaration of reservation `%s'",
2786 DECL_RESERV (decl)->name);
2790 /* Check bypasses and form list of bypasses for each (output)
2791 insn. */
2792 for (i = 0; i < description->decls_num; i++)
2794 decl = description->decls [i];
2795 if (decl->mode == dm_bypass)
2797 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2798 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2799 if (out_insn_reserv == NULL)
2800 error ("there is no insn reservation `%s'",
2801 DECL_BYPASS (decl)->out_insn_name);
2802 else if (in_insn_reserv == NULL)
2803 error ("there is no insn reservation `%s'",
2804 DECL_BYPASS (decl)->in_insn_name);
2805 else
2807 DECL_BYPASS (decl)->out_insn_reserv
2808 = DECL_INSN_RESERV (out_insn_reserv);
2809 DECL_BYPASS (decl)->in_insn_reserv
2810 = DECL_INSN_RESERV (in_insn_reserv);
2811 bypass
2812 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2813 DECL_BYPASS (decl)->in_insn_reserv);
2814 if (bypass != NULL)
2816 if (DECL_BYPASS (decl)->latency == bypass->latency)
2818 if (!w_flag)
2819 error
2820 ("the same bypass `%s - %s' is already defined",
2821 DECL_BYPASS (decl)->out_insn_name,
2822 DECL_BYPASS (decl)->in_insn_name);
2823 else
2824 warning
2825 ("the same bypass `%s - %s' is already defined",
2826 DECL_BYPASS (decl)->out_insn_name,
2827 DECL_BYPASS (decl)->in_insn_name);
2829 else
2830 error ("bypass `%s - %s' is already defined",
2831 DECL_BYPASS (decl)->out_insn_name,
2832 DECL_BYPASS (decl)->in_insn_name);
2834 else
2836 DECL_BYPASS (decl)->next
2837 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2838 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2839 = DECL_BYPASS (decl);
2845 /* Check exclusion set declarations and form exclussion sets. */
2846 for (i = 0; i < description->decls_num; i++)
2848 decl = description->decls [i];
2849 if (decl->mode == dm_excl)
2851 unit_set_el_t unit_set_el_list;
2852 unit_set_el_t unit_set_el_list_2;
2854 unit_set_el_list
2855 = process_excls (DECL_EXCL (decl)->names,
2856 DECL_EXCL (decl)->first_list_length, decl->pos);
2857 unit_set_el_list_2
2858 = process_excls (&DECL_EXCL (decl)->names
2859 [DECL_EXCL (decl)->first_list_length],
2860 DECL_EXCL (decl)->names_num
2861 - DECL_EXCL (decl)->first_list_length,
2862 decl->pos);
2863 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2864 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2868 /* Check presence set declarations and form presence sets. */
2869 for (i = 0; i < description->decls_num; i++)
2871 decl = description->decls [i];
2872 if (decl->mode == dm_presence)
2874 unit_set_el_t unit_set_el_list;
2875 unit_set_el_t unit_set_el_list_2;
2877 unit_set_el_list
2878 = process_presence_absence
2879 (DECL_PRESENCE (decl)->names,
2880 DECL_PRESENCE (decl)->first_list_length, decl->pos, 1);
2881 unit_set_el_list_2
2882 = process_presence_absence
2883 (&DECL_PRESENCE (decl)->names
2884 [DECL_PRESENCE (decl)->first_list_length],
2885 DECL_PRESENCE (decl)->names_num
2886 - DECL_PRESENCE (decl)->first_list_length,
2887 decl->pos, 1);
2888 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2889 decl->pos, 1);
2893 /* Check absence set declarations and form absence sets. */
2894 for (i = 0; i < description->decls_num; i++)
2896 decl = description->decls [i];
2897 if (decl->mode == dm_absence)
2899 unit_set_el_t unit_set_el_list;
2900 unit_set_el_t unit_set_el_list_2;
2902 unit_set_el_list
2903 = process_presence_absence
2904 (DECL_ABSENCE (decl)->names,
2905 DECL_ABSENCE (decl)->first_list_length, decl->pos, 0);
2906 unit_set_el_list_2
2907 = process_presence_absence
2908 (&DECL_ABSENCE (decl)->names
2909 [DECL_ABSENCE (decl)->first_list_length],
2910 DECL_ABSENCE (decl)->names_num
2911 - DECL_ABSENCE (decl)->first_list_length,
2912 decl->pos, 0);
2913 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2914 decl->pos, 0);
2919 /* The following function checks that declared automaton is used. If
2920 the automaton is not used, the function fixes error/warning. The
2921 following function must be called only after `process_decls'. */
2922 static void
2923 check_automaton_usage ()
2925 decl_t decl;
2926 int i;
2928 for (i = 0; i < description->decls_num; i++)
2930 decl = description->decls [i];
2931 if (decl->mode == dm_automaton
2932 && !DECL_AUTOMATON (decl)->automaton_is_used)
2934 if (!w_flag)
2935 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2936 else
2937 warning ("automaton `%s' is not used",
2938 DECL_AUTOMATON (decl)->name);
2943 /* The following recursive function processes all regexp in order to
2944 fix usage of units or reservations and to fix errors of undeclared
2945 name. The function may change unit_regexp onto reserv_regexp.
2946 Remember that reserv_regexp does not exist before the function
2947 call. */
2948 static regexp_t
2949 process_regexp (regexp)
2950 regexp_t regexp;
2952 decl_t decl_in_table;
2953 regexp_t new_regexp;
2954 int i;
2956 if (regexp->mode == rm_unit)
2958 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2959 if (decl_in_table == NULL)
2960 error ("undeclared unit or reservation `%s'",
2961 REGEXP_UNIT (regexp)->name);
2962 else if (decl_in_table->mode == dm_unit)
2964 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2965 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2967 else if (decl_in_table->mode == dm_reserv)
2969 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2970 new_regexp = create_node (sizeof (struct regexp));
2971 new_regexp->mode = rm_reserv;
2972 new_regexp->pos = regexp->pos;
2973 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2974 REGEXP_RESERV (new_regexp)->reserv_decl
2975 = DECL_RESERV (decl_in_table);
2976 regexp = new_regexp;
2978 else
2979 abort ();
2981 else if (regexp->mode == rm_sequence)
2982 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2983 REGEXP_SEQUENCE (regexp)->regexps [i]
2984 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2985 else if (regexp->mode == rm_allof)
2986 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2987 REGEXP_ALLOF (regexp)->regexps [i]
2988 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2989 else if (regexp->mode == rm_oneof)
2990 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2991 REGEXP_ONEOF (regexp)->regexps [i]
2992 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2993 else if (regexp->mode == rm_repeat)
2994 REGEXP_REPEAT (regexp)->regexp
2995 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2996 else if (regexp->mode != rm_nothing)
2997 abort ();
2998 return regexp;
3001 /* The following function processes regexp of define_reservation and
3002 define_insn_reservation with the aid of function
3003 `process_regexp'. */
3004 static void
3005 process_regexp_decls ()
3007 decl_t decl;
3008 int i;
3010 for (i = 0; i < description->decls_num; i++)
3012 decl = description->decls [i];
3013 if (decl->mode == dm_reserv)
3014 DECL_RESERV (decl)->regexp
3015 = process_regexp (DECL_RESERV (decl)->regexp);
3016 else if (decl->mode == dm_insn_reserv)
3017 DECL_INSN_RESERV (decl)->regexp
3018 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3022 /* The following function checks that declared unit is used. If the
3023 unit is not used, the function fixes errors/warnings. The
3024 following function must be called only after `process_decls',
3025 `process_regexp_decls'. */
3026 static void
3027 check_usage ()
3029 decl_t decl;
3030 int i;
3032 for (i = 0; i < description->decls_num; i++)
3034 decl = description->decls [i];
3035 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3037 if (!w_flag)
3038 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3039 else
3040 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3042 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3044 if (!w_flag)
3045 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3046 else
3047 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3052 /* The following variable value is number of reservation being
3053 processed on loop recognition. */
3054 static int curr_loop_pass_num;
3056 /* The following recursive function returns nonzero value if REGEXP
3057 contains given decl or reservations in given regexp refers for
3058 given decl. */
3059 static int
3060 loop_in_regexp (regexp, start_decl)
3061 regexp_t regexp;
3062 decl_t start_decl;
3064 int i;
3066 if (regexp == NULL)
3067 return 0;
3068 if (regexp->mode == rm_unit)
3069 return 0;
3070 else if (regexp->mode == rm_reserv)
3072 if (start_decl->mode == dm_reserv
3073 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3074 return 1;
3075 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3076 == curr_loop_pass_num)
3077 /* declaration has been processed. */
3078 return 0;
3079 else
3081 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3082 = curr_loop_pass_num;
3083 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3084 start_decl);
3087 else if (regexp->mode == rm_sequence)
3089 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3090 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3091 return 1;
3092 return 0;
3094 else if (regexp->mode == rm_allof)
3096 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3097 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3098 return 1;
3099 return 0;
3101 else if (regexp->mode == rm_oneof)
3103 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3104 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3105 return 1;
3106 return 0;
3108 else if (regexp->mode == rm_repeat)
3109 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3110 else
3112 if (regexp->mode != rm_nothing)
3113 abort ();
3114 return 0;
3118 /* The following function fixes errors "cycle in definition ...". The
3119 function uses function `loop_in_regexp' for that. */
3120 static void
3121 check_loops_in_regexps ()
3123 decl_t decl;
3124 int i;
3126 for (i = 0; i < description->decls_num; i++)
3128 decl = description->decls [i];
3129 if (decl->mode == dm_reserv)
3130 DECL_RESERV (decl)->loop_pass_num = 0;
3132 for (i = 0; i < description->decls_num; i++)
3134 decl = description->decls [i];
3135 curr_loop_pass_num = i;
3137 if (decl->mode == dm_reserv)
3139 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
3140 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3142 if (DECL_RESERV (decl)->regexp == NULL)
3143 abort ();
3144 error ("cycle in definition of reservation `%s'",
3145 DECL_RESERV (decl)->name);
3151 /* The function recursively processes IR of reservation and defines
3152 max and min cycle for reservation of unit and for result in the
3153 reservation. */
3154 static int
3155 process_regexp_cycles (regexp, start_cycle)
3156 regexp_t regexp;
3157 int start_cycle;
3159 int i;
3161 if (regexp->mode == rm_unit)
3163 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < start_cycle)
3164 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = start_cycle;
3165 return start_cycle;
3167 else if (regexp->mode == rm_reserv)
3168 return process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3169 start_cycle);
3170 else if (regexp->mode == rm_repeat)
3172 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3173 start_cycle = process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3174 start_cycle) + 1;
3175 return start_cycle;
3177 else if (regexp->mode == rm_sequence)
3179 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3180 start_cycle
3181 = process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3182 start_cycle) + 1;
3183 return start_cycle;
3185 else if (regexp->mode == rm_allof)
3187 int finish_cycle = 0;
3188 int cycle;
3190 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3192 cycle = process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3193 start_cycle);
3194 if (finish_cycle < cycle)
3195 finish_cycle = cycle;
3197 return finish_cycle;
3199 else if (regexp->mode == rm_oneof)
3201 int finish_cycle = 0;
3202 int cycle;
3204 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3206 cycle = process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3207 start_cycle);
3208 if (finish_cycle < cycle)
3209 finish_cycle = cycle;
3211 return finish_cycle;
3213 else
3215 if (regexp->mode != rm_nothing)
3216 abort ();
3217 return start_cycle;
3221 /* The following function is called only for correct program. The
3222 function defines max reservation of insns in cycles. */
3223 static void
3224 evaluate_max_reserv_cycles ()
3226 int max_insn_cycles_num;
3227 decl_t decl;
3228 int i;
3230 description->max_insn_reserv_cycles = 0;
3231 for (i = 0; i < description->decls_num; i++)
3233 decl = description->decls [i];
3234 if (decl->mode == dm_insn_reserv)
3236 max_insn_cycles_num
3237 = process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0);
3238 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3239 description->max_insn_reserv_cycles = max_insn_cycles_num;
3242 description->max_insn_reserv_cycles++;
3245 /* The following function calls functions for checking all
3246 description. */
3247 static void
3248 check_all_description ()
3250 process_decls ();
3251 check_automaton_usage ();
3252 process_regexp_decls ();
3253 check_usage ();
3254 check_loops_in_regexps ();
3255 if (!have_error)
3256 evaluate_max_reserv_cycles ();
3261 /* The page contains abstract data `ticker'. This data is used to
3262 report time of different phases of building automata. It is
3263 possibly to write a description for which automata will be built
3264 during several minutes even on fast machine. */
3266 /* The following function creates ticker and makes it active. */
3267 static ticker_t
3268 create_ticker ()
3270 ticker_t ticker;
3272 ticker.modified_creation_time = get_run_time ();
3273 ticker.incremented_off_time = 0;
3274 return ticker;
3277 /* The following function switches off given ticker. */
3278 static void
3279 ticker_off (ticker)
3280 ticker_t *ticker;
3282 if (ticker->incremented_off_time == 0)
3283 ticker->incremented_off_time = get_run_time () + 1;
3286 /* The following function switches on given ticker. */
3287 static void
3288 ticker_on (ticker)
3289 ticker_t *ticker;
3291 if (ticker->incremented_off_time != 0)
3293 ticker->modified_creation_time
3294 += get_run_time () - ticker->incremented_off_time + 1;
3295 ticker->incremented_off_time = 0;
3299 /* The following function returns current time in milliseconds since
3300 the moment when given ticker was created. */
3301 static int
3302 active_time (ticker)
3303 ticker_t ticker;
3305 if (ticker.incremented_off_time != 0)
3306 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3307 else
3308 return get_run_time () - ticker.modified_creation_time;
3311 /* The following function returns string representation of active time
3312 of given ticker. The result is string representation of seconds
3313 with accuracy of 1/100 second. Only result of the last call of the
3314 function exists. Therefore the following code is not correct
3316 printf ("parser time: %s\ngeneration time: %s\n",
3317 active_time_string (parser_ticker),
3318 active_time_string (generation_ticker));
3320 Correct code has to be the following
3322 printf ("parser time: %s\n", active_time_string (parser_ticker));
3323 printf ("generation time: %s\n",
3324 active_time_string (generation_ticker));
3327 static void
3328 print_active_time (f, ticker)
3329 FILE *f;
3330 ticker_t ticker;
3332 int msecs;
3334 msecs = active_time (ticker);
3335 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3340 /* The following variable value is number of automaton which are
3341 really being created. This value is defined on the base of
3342 argument of option `-split'. If the variable has zero value the
3343 number of automata is defined by the constructions `%automaton'.
3344 This case occures when option `-split' is absent or has zero
3345 argument. If constructions `define_automaton' is absent only one
3346 automaton is created. */
3347 static int automata_num;
3349 /* The following variable values are times of
3350 o transformation of regular expressions
3351 o building NDFA (DFA if !ndfa_flag)
3352 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3353 o DFA minimization
3354 o building insn equivalence classes
3355 o all previous ones
3356 o code output */
3357 static ticker_t transform_time;
3358 static ticker_t NDFA_time;
3359 static ticker_t NDFA_to_DFA_time;
3360 static ticker_t minimize_time;
3361 static ticker_t equiv_time;
3362 static ticker_t automaton_generation_time;
3363 static ticker_t output_time;
3365 /* The following variable values are times of
3366 all checking
3367 all generation
3368 all pipeline hazard translator work */
3369 static ticker_t check_time;
3370 static ticker_t generation_time;
3371 static ticker_t all_time;
3375 /* Pseudo insn decl which denotes advancing cycle. */
3376 static decl_t advance_cycle_insn_decl;
3377 static void
3378 add_advance_cycle_insn_decl ()
3380 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3381 advance_cycle_insn_decl->mode = dm_insn_reserv;
3382 advance_cycle_insn_decl->pos = no_pos;
3383 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3384 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
3385 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3386 = description->insns_num;
3387 description->decls [description->decls_num] = advance_cycle_insn_decl;
3388 description->decls_num++;
3389 description->insns_num++;
3390 num_dfa_decls++;
3394 /* Abstract data `alternative states' which reperesents
3395 nondeterministic nature of the description (see comments for
3396 structures alt_state and state). */
3398 /* List of free states. */
3399 static alt_state_t first_free_alt_state;
3401 #ifndef NDEBUG
3402 /* The following variables is maximal number of allocated nodes
3403 alt_state. */
3404 static int allocated_alt_states_num = 0;
3405 #endif
3407 /* The following function returns free node alt_state. It may be new
3408 allocated node or node freed eralier. */
3409 static alt_state_t
3410 get_free_alt_state ()
3412 alt_state_t result;
3414 if (first_free_alt_state != NULL)
3416 result = first_free_alt_state;
3417 first_free_alt_state = first_free_alt_state->next_alt_state;
3419 else
3421 #ifndef NDEBUG
3422 allocated_alt_states_num++;
3423 #endif
3424 result = create_node (sizeof (struct alt_state));
3426 result->state = NULL;
3427 result->next_alt_state = NULL;
3428 result->next_sorted_alt_state = NULL;
3429 return result;
3432 /* The function frees node ALT_STATE. */
3433 static void
3434 free_alt_state (alt_state)
3435 alt_state_t alt_state;
3437 if (alt_state == NULL)
3438 return;
3439 alt_state->next_alt_state = first_free_alt_state;
3440 first_free_alt_state = alt_state;
3443 /* The function frees list started with node ALT_STATE_LIST. */
3444 static void
3445 free_alt_states (alt_states_list)
3446 alt_state_t alt_states_list;
3448 alt_state_t curr_alt_state;
3449 alt_state_t next_alt_state;
3451 for (curr_alt_state = alt_states_list;
3452 curr_alt_state != NULL;
3453 curr_alt_state = next_alt_state)
3455 next_alt_state = curr_alt_state->next_alt_state;
3456 free_alt_state (curr_alt_state);
3460 /* The function compares unique numbers of alt states. */
3461 static int
3462 alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
3463 const void *alt_state_ptr_1;
3464 const void *alt_state_ptr_2;
3466 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3467 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3468 return 0;
3469 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3470 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3471 return -1;
3472 else
3473 return 1;
3476 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3477 states from the list. The comparison key is alt state unique
3478 number. */
3479 static alt_state_t
3480 uniq_sort_alt_states (alt_states_list)
3481 alt_state_t alt_states_list;
3483 alt_state_t curr_alt_state;
3484 vla_ptr_t alt_states;
3485 size_t i;
3486 size_t prev_unique_state_ind;
3487 alt_state_t result;
3488 alt_state_t *result_ptr;
3490 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3491 for (curr_alt_state = alt_states_list;
3492 curr_alt_state != NULL;
3493 curr_alt_state = curr_alt_state->next_alt_state)
3494 VLA_PTR_ADD (alt_states, curr_alt_state);
3495 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3496 sizeof (alt_state_t), alt_state_cmp);
3497 if (VLA_PTR_LENGTH (alt_states) == 0)
3498 result = NULL;
3499 else
3501 result_ptr = VLA_PTR_BEGIN (alt_states);
3502 prev_unique_state_ind = 0;
3503 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3504 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3506 prev_unique_state_ind++;
3507 result_ptr [prev_unique_state_ind] = result_ptr [i];
3509 #if 0
3510 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3511 free_alt_state (result_ptr [i]);
3512 #endif
3513 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3514 result_ptr = VLA_PTR_BEGIN (alt_states);
3515 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3516 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3517 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3518 result = *result_ptr;
3520 VLA_PTR_DELETE (alt_states);
3521 return result;
3524 /* The function checks equality of alt state lists. Remember that the
3525 lists must be already sorted by the previous function. */
3526 static int
3527 alt_states_eq (alt_states_1, alt_states_2)
3528 alt_state_t alt_states_1;
3529 alt_state_t alt_states_2;
3531 while (alt_states_1 != NULL && alt_states_2 != NULL
3532 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3534 alt_states_1 = alt_states_1->next_sorted_alt_state;
3535 alt_states_2 = alt_states_2->next_sorted_alt_state;
3537 return alt_states_1 == alt_states_2;
3540 /* Initialization of the abstract data. */
3541 static void
3542 initiate_alt_states ()
3544 first_free_alt_state = NULL;
3547 /* Finishing work with the abstract data. */
3548 static void
3549 finish_alt_states ()
3555 /* The page contains macros for work with bits strings. We could use
3556 standard gcc bitmap or sbitmap but it would result in difficulties
3557 of building canadian cross. */
3559 /* Set bit number bitno in the bit string. The macro is not side
3560 effect proof. */
3561 #define SET_BIT(bitstring, bitno) \
3562 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3564 /* Test if bit number bitno in the bitstring is set. The macro is not
3565 side effect proof. */
3566 #define TEST_BIT(bitstring, bitno) \
3567 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3571 /* This page contains abstract data `state'. */
3573 /* Maximal length of reservations in cycles (>= 1). */
3574 static int max_cycles_num;
3576 /* Number of set elements (see type set_el_t) needed for
3577 representation of one cycle reservation. It is depended on units
3578 number. */
3579 static int els_in_cycle_reserv;
3581 /* Number of set elements (see type set_el_t) needed for
3582 representation of maximal length reservation. Deterministic
3583 reservation is stored as set (bit string) of length equal to the
3584 variable value * number of bits in set_el_t. */
3585 static int els_in_reservs;
3587 /* VLA for representation of array of pointers to unit
3588 declarations. */
3589 static vla_ptr_t units_container;
3591 /* The start address of the array. */
3592 static unit_decl_t *units_array;
3594 /* Empty reservation of maximal length. */
3595 static reserv_sets_t empty_reserv;
3597 /* The state table itself is represented by the following variable. */
3598 static htab_t state_table;
3600 /* VLA for representation of array of pointers to free nodes
3601 `state'. */
3602 static vla_ptr_t free_states;
3604 static int curr_unique_state_num;
3606 #ifndef NDEBUG
3607 /* The following variables is maximal number of allocated nodes
3608 `state'. */
3609 static int allocated_states_num = 0;
3610 #endif
3612 /* Allocate new reservation set. */
3613 static reserv_sets_t
3614 alloc_empty_reserv_sets ()
3616 reserv_sets_t result;
3618 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3619 result = (reserv_sets_t) obstack_base (&irp);
3620 obstack_finish (&irp);
3621 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3622 return result;
3625 /* Hash value of reservation set. */
3626 static unsigned
3627 reserv_sets_hash_value (reservs)
3628 reserv_sets_t reservs;
3630 set_el_t hash_value;
3631 unsigned result;
3632 int reservs_num, i;
3633 set_el_t *reserv_ptr;
3635 hash_value = 0;
3636 reservs_num = els_in_reservs;
3637 reserv_ptr = reservs;
3638 i = 0;
3639 while (reservs_num != 0)
3641 reservs_num--;
3642 hash_value += ((*reserv_ptr >> i)
3643 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3644 i++;
3645 if (i == sizeof (set_el_t) * CHAR_BIT)
3646 i = 0;
3647 reserv_ptr++;
3649 if (sizeof (set_el_t) <= sizeof (unsigned))
3650 return hash_value;
3651 result = 0;
3652 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3654 result += (unsigned) hash_value;
3655 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3657 return result;
3660 /* Comparison of given reservation sets. */
3661 static int
3662 reserv_sets_cmp (reservs_1, reservs_2)
3663 reserv_sets_t reservs_1;
3664 reserv_sets_t reservs_2;
3666 int reservs_num;
3667 set_el_t *reserv_ptr_1;
3668 set_el_t *reserv_ptr_2;
3670 if (reservs_1 == NULL || reservs_2 == NULL)
3671 abort ();
3672 reservs_num = els_in_reservs;
3673 reserv_ptr_1 = reservs_1;
3674 reserv_ptr_2 = reservs_2;
3675 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3677 reservs_num--;
3678 reserv_ptr_1++;
3679 reserv_ptr_2++;
3681 if (reservs_num == 0)
3682 return 0;
3683 else if (*reserv_ptr_1 < *reserv_ptr_2)
3684 return -1;
3685 else
3686 return 1;
3689 /* The function checks equality of the reservation sets. */
3690 static int
3691 reserv_sets_eq (reservs_1, reservs_2)
3692 reserv_sets_t reservs_1;
3693 reserv_sets_t reservs_2;
3695 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3698 /* Set up in the reservation set that unit with UNIT_NUM is used on
3699 CYCLE_NUM. */
3700 static void
3701 set_unit_reserv (reservs, cycle_num, unit_num)
3702 reserv_sets_t reservs;
3703 int cycle_num;
3704 int unit_num;
3706 if (cycle_num >= max_cycles_num)
3707 abort ();
3708 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3709 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3712 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3713 used on CYCLE_NUM. */
3714 static int
3715 test_unit_reserv (reservs, cycle_num, unit_num)
3716 reserv_sets_t reservs;
3717 int cycle_num;
3718 int unit_num;
3720 if (cycle_num >= max_cycles_num)
3721 abort ();
3722 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3723 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3726 /* The function checks that the reservation set represents no one unit
3727 reservation. */
3728 static int
3729 it_is_empty_reserv_sets (operand)
3730 reserv_sets_t operand;
3732 set_el_t *reserv_ptr;
3733 int reservs_num;
3735 if (operand == NULL)
3736 abort ();
3737 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3738 reservs_num != 0;
3739 reserv_ptr++, reservs_num--)
3740 if (*reserv_ptr != 0)
3741 return 0;
3742 return 1;
3745 /* The function checks that the reservation sets are intersected,
3746 i.e. there is a unit reservation on a cycle in both reservation
3747 sets. */
3748 static int
3749 reserv_sets_are_intersected (operand_1, operand_2)
3750 reserv_sets_t operand_1;
3751 reserv_sets_t operand_2;
3753 set_el_t *el_ptr_1;
3754 set_el_t *el_ptr_2;
3755 set_el_t *cycle_ptr_1;
3756 set_el_t *cycle_ptr_2;
3757 int nonzero_p;
3759 if (operand_1 == NULL || operand_2 == NULL)
3760 abort ();
3761 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3762 el_ptr_1 < operand_1 + els_in_reservs;
3763 el_ptr_1++, el_ptr_2++)
3764 if (*el_ptr_1 & *el_ptr_2)
3765 return 1;
3766 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3767 cycle_ptr_1 < operand_1 + els_in_reservs;
3768 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3770 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3771 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3772 el_ptr_1++, el_ptr_2++)
3773 if (*el_ptr_1 & *el_ptr_2)
3774 return 1;
3775 nonzero_p = 0;
3776 for (el_ptr_1 = cycle_ptr_1,
3777 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 1);
3778 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3779 el_ptr_1++, el_ptr_2++)
3780 if (*el_ptr_1 & *el_ptr_2)
3781 break;
3782 else if (*el_ptr_2 != 0)
3783 nonzero_p = 1;
3784 if (nonzero_p && el_ptr_1 >= cycle_ptr_1 + els_in_cycle_reserv)
3785 return 1;
3786 for (el_ptr_1 = cycle_ptr_1,
3787 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 0);
3788 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3789 el_ptr_1++, el_ptr_2++)
3790 /* It looks like code for exclusion but exclusion set is
3791 made as symmetric relation preliminary. */
3792 if (*el_ptr_1 & *el_ptr_2)
3793 return 1;
3795 return 0;
3798 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3799 cpu cycle. The remaining bits of OPERAND (representing the last
3800 cycle unit reservations) are not chenged. */
3801 static void
3802 reserv_sets_shift (result, operand)
3803 reserv_sets_t result;
3804 reserv_sets_t operand;
3806 int i;
3808 if (result == NULL || operand == NULL || result == operand)
3809 abort ();
3810 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3811 result [i - els_in_cycle_reserv] = operand [i];
3814 /* OR of the reservation sets. */
3815 static void
3816 reserv_sets_or (result, operand_1, operand_2)
3817 reserv_sets_t result;
3818 reserv_sets_t operand_1;
3819 reserv_sets_t operand_2;
3821 set_el_t *el_ptr_1;
3822 set_el_t *el_ptr_2;
3823 set_el_t *result_set_el_ptr;
3825 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3826 abort ();
3827 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3828 el_ptr_1 < operand_1 + els_in_reservs;
3829 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3830 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3833 /* AND of the reservation sets. */
3834 static void
3835 reserv_sets_and (result, operand_1, operand_2)
3836 reserv_sets_t result;
3837 reserv_sets_t operand_1;
3838 reserv_sets_t operand_2;
3840 set_el_t *el_ptr_1;
3841 set_el_t *el_ptr_2;
3842 set_el_t *result_set_el_ptr;
3844 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3845 abort ();
3846 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3847 el_ptr_1 < operand_1 + els_in_reservs;
3848 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3849 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3852 /* The function outputs string representation of units reservation on
3853 cycle START_CYCLE in the reservation set. The function uses repeat
3854 construction if REPETITION_NUM > 1. */
3855 static void
3856 output_cycle_reservs (f, reservs, start_cycle, repetition_num)
3857 FILE *f;
3858 reserv_sets_t reservs;
3859 int start_cycle;
3860 int repetition_num;
3862 int unit_num;
3863 int reserved_units_num;
3865 reserved_units_num = 0;
3866 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3867 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3868 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3869 reserved_units_num++;
3870 if (repetition_num <= 0)
3871 abort ();
3872 if (repetition_num != 1 && reserved_units_num > 1)
3873 fprintf (f, "(");
3874 reserved_units_num = 0;
3875 for (unit_num = 0;
3876 unit_num < description->units_num;
3877 unit_num++)
3878 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3879 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3881 if (reserved_units_num != 0)
3882 fprintf (f, "+");
3883 reserved_units_num++;
3884 fprintf (f, "%s", units_array [unit_num]->name);
3886 if (reserved_units_num == 0)
3887 fprintf (f, NOTHING_NAME);
3888 if (repetition_num <= 0)
3889 abort ();
3890 if (reserved_units_num > 1)
3891 fprintf (f, ")");
3892 if (repetition_num != 1)
3893 fprintf (f, "*%d", repetition_num);
3896 /* The function outputs string representation of units reservation in
3897 the reservation set. */
3898 static void
3899 output_reserv_sets (f, reservs)
3900 FILE *f;
3901 reserv_sets_t reservs;
3903 int start_cycle = 0;
3904 int cycle;
3905 int repetition_num;
3907 repetition_num = 0;
3908 for (cycle = 0; cycle < max_cycles_num; cycle++)
3909 if (repetition_num == 0)
3911 repetition_num++;
3912 start_cycle = cycle;
3914 else if (memcmp
3915 ((char *) reservs + start_cycle * els_in_cycle_reserv
3916 * sizeof (set_el_t),
3917 (char *) reservs + cycle * els_in_cycle_reserv
3918 * sizeof (set_el_t),
3919 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3920 repetition_num++;
3921 else
3923 if (start_cycle != 0)
3924 fprintf (f, ", ");
3925 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3926 repetition_num = 1;
3927 start_cycle = cycle;
3929 if (start_cycle < max_cycles_num)
3931 if (start_cycle != 0)
3932 fprintf (f, ", ");
3933 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3937 /* The following function returns free node state for AUTOMATON. It
3938 may be new allocated node or node freed eralier. The function also
3939 allocates reservation set if WITH_RESERVS has nonzero value. */
3940 static state_t
3941 get_free_state (with_reservs, automaton)
3942 int with_reservs;
3943 automaton_t automaton;
3945 state_t result;
3947 if (max_cycles_num <= 0 || automaton == NULL)
3948 abort ();
3949 if (VLA_PTR_LENGTH (free_states) != 0)
3951 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
3952 VLA_PTR_SHORTEN (free_states, 1);
3953 result->automaton = automaton;
3954 result->first_out_arc = NULL;
3955 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3956 result->it_was_placed_in_stack_for_DFA_forming = 0;
3957 result->component_states = NULL;
3958 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3960 else
3962 #ifndef NDEBUG
3963 allocated_states_num++;
3964 #endif
3965 result = create_node (sizeof (struct state));
3966 result->automaton = automaton;
3967 result->first_out_arc = NULL;
3968 result->unique_num = curr_unique_state_num;
3969 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3970 curr_unique_state_num++;
3972 if (with_reservs)
3974 if (result->reservs == NULL)
3975 result->reservs = alloc_empty_reserv_sets ();
3976 else
3977 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3979 return result;
3982 /* The function frees node STATE. */
3983 static void
3984 free_state (state)
3985 state_t state;
3987 free_alt_states (state->component_states);
3988 VLA_PTR_ADD (free_states, state);
3991 /* Hash value of STATE. If STATE represents deterministic state it is
3992 simply hash value of the corresponding reservation set. Otherwise
3993 it is formed from hash values of the component deterministic
3994 states. One more key is order number of state automaton. */
3995 static unsigned
3996 state_hash (state)
3997 const void *state;
3999 unsigned int hash_value;
4000 alt_state_t alt_state;
4002 if (((state_t) state)->component_states == NULL)
4003 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
4004 else
4006 hash_value = 0;
4007 for (alt_state = ((state_t) state)->component_states;
4008 alt_state != NULL;
4009 alt_state = alt_state->next_sorted_alt_state)
4010 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4011 | (hash_value << CHAR_BIT))
4012 + alt_state->state->unique_num);
4014 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4015 | (hash_value << CHAR_BIT))
4016 + ((state_t) state)->automaton->automaton_order_num);
4017 return hash_value;
4020 /* Return nonzero value if the states are the same. */
4021 static int
4022 state_eq_p (state_1, state_2)
4023 const void *state_1;
4024 const void *state_2;
4026 alt_state_t alt_state_1;
4027 alt_state_t alt_state_2;
4029 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
4030 return 0;
4031 else if (((state_t) state_1)->component_states == NULL
4032 && ((state_t) state_2)->component_states == NULL)
4033 return reserv_sets_eq (((state_t) state_1)->reservs,
4034 ((state_t) state_2)->reservs);
4035 else if (((state_t) state_1)->component_states != NULL
4036 && ((state_t) state_2)->component_states != NULL)
4038 for (alt_state_1 = ((state_t) state_1)->component_states,
4039 alt_state_2 = ((state_t) state_2)->component_states;
4040 alt_state_1 != NULL && alt_state_2 != NULL;
4041 alt_state_1 = alt_state_1->next_sorted_alt_state,
4042 alt_state_2 = alt_state_2->next_sorted_alt_state)
4043 /* All state in the list must be already in the hash table.
4044 Also the lists must be sorted. */
4045 if (alt_state_1->state != alt_state_2->state)
4046 return 0;
4047 return alt_state_1 == alt_state_2;
4049 else
4050 return 0;
4053 /* Insert STATE into the state table. */
4054 static state_t
4055 insert_state (state)
4056 state_t state;
4058 void **entry_ptr;
4060 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
4061 if (*entry_ptr == NULL)
4062 *entry_ptr = (void *) state;
4063 return (state_t) *entry_ptr;
4066 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4067 deterministic STATE. */
4068 static void
4069 set_state_reserv (state, cycle_num, unit_num)
4070 state_t state;
4071 int cycle_num;
4072 int unit_num;
4074 set_unit_reserv (state->reservs, cycle_num, unit_num);
4077 /* Return nonzero value if the deterministic states contains a
4078 reservation of the same cpu unit on the same cpu cycle. */
4079 static int
4080 intersected_state_reservs_p (state1, state2)
4081 state_t state1;
4082 state_t state2;
4084 if (state1->automaton != state2->automaton)
4085 abort ();
4086 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
4089 /* Return deterministic state (inserted into the table) which
4090 representing the automaton state whic is union of reservations of
4091 deterministic states. */
4092 static state_t
4093 states_union (state1, state2)
4094 state_t state1;
4095 state_t state2;
4097 state_t result;
4098 state_t state_in_table;
4100 if (state1->automaton != state2->automaton)
4101 abort ();
4102 result = get_free_state (1, state1->automaton);
4103 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
4104 state_in_table = insert_state (result);
4105 if (result != state_in_table)
4107 free_state (result);
4108 result = state_in_table;
4110 return result;
4113 /* Return deterministic state (inserted into the table) which
4114 represent the automaton state is obtained from deterministic STATE
4115 by advancing cpu cycle. */
4116 static state_t
4117 state_shift (state)
4118 state_t state;
4120 state_t result;
4121 state_t state_in_table;
4123 result = get_free_state (1, state->automaton);
4124 reserv_sets_shift (result->reservs, state->reservs);
4125 state_in_table = insert_state (result);
4126 if (result != state_in_table)
4128 free_state (result);
4129 result = state_in_table;
4131 return result;
4134 /* Initialization of the abstract data. */
4135 static void
4136 initiate_states ()
4138 decl_t decl;
4139 int i;
4141 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
4142 units_array
4143 = (description->decls_num && description->units_num
4144 ? VLA_PTR_BEGIN (units_container) : NULL);
4145 for (i = 0; i < description->decls_num; i++)
4147 decl = description->decls [i];
4148 if (decl->mode == dm_unit)
4149 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
4151 max_cycles_num = description->max_insn_reserv_cycles;
4152 els_in_cycle_reserv
4153 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
4154 / (sizeof (set_el_t) * CHAR_BIT));
4155 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
4156 curr_unique_state_num = 0;
4157 initiate_alt_states ();
4158 VLA_PTR_CREATE (free_states, 1500, "free states");
4159 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
4160 empty_reserv = alloc_empty_reserv_sets ();
4163 /* Finisging work with the abstract data. */
4164 static void
4165 finish_states ()
4167 VLA_PTR_DELETE (units_container);
4168 htab_delete (state_table);
4169 VLA_PTR_DELETE (free_states);
4170 finish_alt_states ();
4175 /* Abstract data `arcs'. */
4177 /* List of free arcs. */
4178 static arc_t first_free_arc;
4180 #ifndef NDEBUG
4181 /* The following variables is maximal number of allocated nodes
4182 `arc'. */
4183 static int allocated_arcs_num = 0;
4184 #endif
4186 /* The function frees node ARC. */
4187 static void
4188 free_arc (arc)
4189 arc_t arc;
4191 arc->next_out_arc = first_free_arc;
4192 first_free_arc = arc;
4195 /* The function removes and frees ARC staring from FROM_STATE. */
4196 static void
4197 remove_arc (from_state, arc)
4198 state_t from_state;
4199 arc_t arc;
4201 arc_t prev_arc;
4202 arc_t curr_arc;
4204 if (arc == NULL)
4205 abort ();
4206 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
4207 curr_arc != NULL;
4208 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4209 if (curr_arc == arc)
4210 break;
4211 if (curr_arc == NULL)
4212 abort ();
4213 if (prev_arc == NULL)
4214 from_state->first_out_arc = arc->next_out_arc;
4215 else
4216 prev_arc->next_out_arc = arc->next_out_arc;
4217 free_arc (arc);
4220 /* The functions returns arc with given characteristics (or NULL if
4221 the arc does not exist). */
4222 static arc_t
4223 find_arc (from_state, to_state, insn)
4224 state_t from_state;
4225 state_t to_state;
4226 ainsn_t insn;
4228 arc_t arc;
4230 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4231 if (arc->to_state == to_state && arc->insn == insn)
4232 return arc;
4233 return NULL;
4236 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4237 and with given STATE_ALTS. The function returns added arc (or
4238 already existing arc). */
4239 static arc_t
4240 add_arc (from_state, to_state, ainsn, state_alts)
4241 state_t from_state;
4242 state_t to_state;
4243 ainsn_t ainsn;
4244 int state_alts;
4246 arc_t new_arc;
4248 new_arc = find_arc (from_state, to_state, ainsn);
4249 if (new_arc != NULL)
4250 return new_arc;
4251 if (first_free_arc == NULL)
4253 #ifndef NDEBUG
4254 allocated_arcs_num++;
4255 #endif
4256 new_arc = create_node (sizeof (struct arc));
4257 new_arc->to_state = NULL;
4258 new_arc->insn = NULL;
4259 new_arc->next_out_arc = NULL;
4261 else
4263 new_arc = first_free_arc;
4264 first_free_arc = first_free_arc->next_out_arc;
4266 new_arc->to_state = to_state;
4267 new_arc->insn = ainsn;
4268 ainsn->arc_exists_p = 1;
4269 new_arc->next_out_arc = from_state->first_out_arc;
4270 from_state->first_out_arc = new_arc;
4271 new_arc->next_arc_marked_by_insn = NULL;
4272 new_arc->state_alts = state_alts;
4273 return new_arc;
4276 /* The function returns the first arc starting from STATE. */
4277 static arc_t
4278 first_out_arc (state)
4279 state_t state;
4281 return state->first_out_arc;
4284 /* The function returns next out arc after ARC. */
4285 static arc_t
4286 next_out_arc (arc)
4287 arc_t arc;
4289 return arc->next_out_arc;
4292 /* Initialization of the abstract data. */
4293 static void
4294 initiate_arcs ()
4296 first_free_arc = NULL;
4299 /* Finishing work with the abstract data. */
4300 static void
4301 finish_arcs ()
4307 /* Abstract data `automata lists'. */
4309 /* List of free states. */
4310 static automata_list_el_t first_free_automata_list_el;
4312 /* The list being formed. */
4313 static automata_list_el_t current_automata_list;
4315 /* Hash table of automata lists. */
4316 static htab_t automata_list_table;
4318 /* The following function returns free automata list el. It may be
4319 new allocated node or node freed earlier. */
4320 static automata_list_el_t
4321 get_free_automata_list_el ()
4323 automata_list_el_t result;
4325 if (first_free_automata_list_el != NULL)
4327 result = first_free_automata_list_el;
4328 first_free_automata_list_el
4329 = first_free_automata_list_el->next_automata_list_el;
4331 else
4332 result = create_node (sizeof (struct automata_list_el));
4333 result->automaton = NULL;
4334 result->next_automata_list_el = NULL;
4335 return result;
4338 /* The function frees node AUTOMATA_LIST_EL. */
4339 static void
4340 free_automata_list_el (automata_list_el)
4341 automata_list_el_t automata_list_el;
4343 if (automata_list_el == NULL)
4344 return;
4345 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4346 first_free_automata_list_el = automata_list_el;
4349 /* The function frees list AUTOMATA_LIST. */
4350 static void
4351 free_automata_list (automata_list)
4352 automata_list_el_t automata_list;
4354 automata_list_el_t curr_automata_list_el;
4355 automata_list_el_t next_automata_list_el;
4357 for (curr_automata_list_el = automata_list;
4358 curr_automata_list_el != NULL;
4359 curr_automata_list_el = next_automata_list_el)
4361 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4362 free_automata_list_el (curr_automata_list_el);
4366 /* Hash value of AUTOMATA_LIST. */
4367 static unsigned
4368 automata_list_hash (automata_list)
4369 const void *automata_list;
4371 unsigned int hash_value;
4372 automata_list_el_t curr_automata_list_el;
4374 hash_value = 0;
4375 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4376 curr_automata_list_el != NULL;
4377 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4378 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4379 | (hash_value << CHAR_BIT))
4380 + curr_automata_list_el->automaton->automaton_order_num);
4381 return hash_value;
4384 /* Return nonzero value if the automata_lists are the same. */
4385 static int
4386 automata_list_eq_p (automata_list_1, automata_list_2)
4387 const void *automata_list_1;
4388 const void *automata_list_2;
4390 automata_list_el_t automata_list_el_1;
4391 automata_list_el_t automata_list_el_2;
4393 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4394 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4395 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4396 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4397 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4398 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4399 return 0;
4400 return automata_list_el_1 == automata_list_el_2;
4403 /* Initialization of the abstract data. */
4404 static void
4405 initiate_automata_lists ()
4407 first_free_automata_list_el = NULL;
4408 automata_list_table = htab_create (1500, automata_list_hash,
4409 automata_list_eq_p, (htab_del) 0);
4412 /* The following function starts new automata list and makes it the
4413 current one. */
4414 static void
4415 automata_list_start ()
4417 current_automata_list = NULL;
4420 /* The following function adds AUTOMATON to the current list. */
4421 static void
4422 automata_list_add (automaton)
4423 automaton_t automaton;
4425 automata_list_el_t el;
4427 el = get_free_automata_list_el ();
4428 el->automaton = automaton;
4429 el->next_automata_list_el = current_automata_list;
4430 current_automata_list = el;
4433 /* The following function finishes forming the current list, inserts
4434 it into the table and returns it. */
4435 static automata_list_el_t
4436 automata_list_finish ()
4438 void **entry_ptr;
4440 if (current_automata_list == NULL)
4441 return NULL;
4442 entry_ptr = htab_find_slot (automata_list_table,
4443 (void *) current_automata_list, 1);
4444 if (*entry_ptr == NULL)
4445 *entry_ptr = (void *) current_automata_list;
4446 else
4447 free_automata_list (current_automata_list);
4448 current_automata_list = NULL;
4449 return (automata_list_el_t) *entry_ptr;
4452 /* Finishing work with the abstract data. */
4453 static void
4454 finish_automata_lists ()
4456 htab_delete (automata_list_table);
4461 /* The page contains abstract data for work with exclusion sets (see
4462 exclusion_set in file rtl.def). */
4464 /* The following variable refers to an exclusion set returned by
4465 get_excl_set. This is bit string of length equal to cpu units
4466 number. If exclusion set for given unit contains 1 for a unit,
4467 then simultaneous reservation of the units is prohibited. */
4468 static reserv_sets_t excl_set;
4470 /* The array contains exclusion sets for each unit. */
4471 static reserv_sets_t *unit_excl_set_table;
4473 /* The following function forms the array containing exclusion sets
4474 for each unit. */
4475 static void
4476 initiate_excl_sets ()
4478 decl_t decl;
4479 reserv_sets_t unit_excl_set;
4480 unit_set_el_t el;
4481 int i;
4483 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4484 excl_set = (reserv_sets_t) obstack_base (&irp);
4485 obstack_finish (&irp);
4486 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4487 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4488 obstack_finish (&irp);
4489 /* Evaluate unit exclusion sets. */
4490 for (i = 0; i < description->decls_num; i++)
4492 decl = description->decls [i];
4493 if (decl->mode == dm_unit)
4495 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4496 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4497 obstack_finish (&irp);
4498 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4499 for (el = DECL_UNIT (decl)->excl_list;
4500 el != NULL;
4501 el = el->next_unit_set_el)
4502 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4503 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4508 /* The function sets up and return EXCL_SET which is union of
4509 exclusion sets for each unit in IN_SET. */
4510 static reserv_sets_t
4511 get_excl_set (in_set)
4512 reserv_sets_t in_set;
4514 int excl_char_num;
4515 int chars_num;
4516 int i;
4517 int start_unit_num;
4518 int unit_num;
4520 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4521 memset (excl_set, 0, chars_num);
4522 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4523 if (((unsigned char *) in_set) [excl_char_num])
4524 for (i = CHAR_BIT - 1; i >= 0; i--)
4525 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4527 start_unit_num = excl_char_num * CHAR_BIT + i;
4528 if (start_unit_num >= description->units_num)
4529 return excl_set;
4530 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4532 excl_set [unit_num]
4533 |= unit_excl_set_table [start_unit_num] [unit_num];
4536 return excl_set;
4541 /* The page contains abstract data for work with presence/absence sets
4542 (see presence_set/absence_set in file rtl.def). */
4544 /* The following variables refer to correspondingly an presence and an
4545 absence set returned by get_presence_absence_set. This is bit
4546 string of length equal to cpu units number. */
4547 static reserv_sets_t presence_set, absence_set;
4549 /* The following arrays contain correspondingly presence and absence
4550 sets for each unit. */
4551 static reserv_sets_t *unit_presence_set_table, *unit_absence_set_table;
4553 /* The following function forms the array containing presence and
4554 absence sets for each unit */
4555 static void
4556 initiate_presence_absence_sets ()
4558 decl_t decl;
4559 reserv_sets_t unit_set;
4560 unit_set_el_t el;
4561 int i;
4563 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4564 presence_set = (reserv_sets_t) obstack_base (&irp);
4565 obstack_finish (&irp);
4566 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4567 unit_presence_set_table = (reserv_sets_t *) obstack_base (&irp);
4568 obstack_finish (&irp);
4569 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4570 absence_set = (reserv_sets_t) obstack_base (&irp);
4571 obstack_finish (&irp);
4572 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4573 unit_absence_set_table = (reserv_sets_t *) obstack_base (&irp);
4574 obstack_finish (&irp);
4575 /* Evaluate unit presence/absence sets. */
4576 for (i = 0; i < description->decls_num; i++)
4578 decl = description->decls [i];
4579 if (decl->mode == dm_unit)
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)->presence_list;
4586 el != NULL;
4587 el = el->next_unit_set_el)
4588 SET_BIT (unit_set, el->unit_decl->unit_num);
4589 unit_presence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4591 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4592 unit_set = (reserv_sets_t) obstack_base (&irp);
4593 obstack_finish (&irp);
4594 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4595 for (el = DECL_UNIT (decl)->absence_list;
4596 el != NULL;
4597 el = el->next_unit_set_el)
4598 SET_BIT (unit_set, el->unit_decl->unit_num);
4599 unit_absence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4604 /* The function sets up and return PRESENCE_SET (if PRESENCE_P) or
4605 ABSENCE_SET which is union of corresponding sets for each unit in
4606 IN_SET. */
4607 static reserv_sets_t
4608 get_presence_absence_set (in_set, presence_p)
4609 reserv_sets_t in_set;
4610 int presence_p;
4612 int char_num;
4613 int chars_num;
4614 int i;
4615 int start_unit_num;
4616 int unit_num;
4618 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4619 if (presence_p)
4620 memset (presence_set, 0, chars_num);
4621 else
4622 memset (absence_set, 0, chars_num);
4623 for (char_num = 0; char_num < chars_num; char_num++)
4624 if (((unsigned char *) in_set) [char_num])
4625 for (i = CHAR_BIT - 1; i >= 0; i--)
4626 if ((((unsigned char *) in_set) [char_num] >> i) & 1)
4628 start_unit_num = char_num * CHAR_BIT + i;
4629 if (start_unit_num >= description->units_num)
4630 return (presence_p ? presence_set : absence_set);
4631 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4632 if (presence_p)
4633 presence_set [unit_num]
4634 |= unit_presence_set_table [start_unit_num] [unit_num];
4635 else
4636 absence_set [unit_num]
4637 |= unit_absence_set_table [start_unit_num] [unit_num];
4639 return (presence_p ? presence_set : absence_set);
4644 /* This page contains code for transformation of original reservations
4645 described in .md file. The main goal of transformations is
4646 simplifying reservation and lifting up all `|' on the top of IR
4647 reservation representation. */
4650 /* The following function makes copy of IR representation of
4651 reservation. The function also substitutes all reservations
4652 defined by define_reservation by corresponding value during making
4653 the copy. */
4654 static regexp_t
4655 copy_insn_regexp (regexp)
4656 regexp_t regexp;
4658 regexp_t result;
4659 int i;
4661 if (regexp->mode == rm_reserv)
4662 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4663 else if (regexp->mode == rm_unit)
4664 result = copy_node (regexp, sizeof (struct regexp));
4665 else if (regexp->mode == rm_repeat)
4667 result = copy_node (regexp, sizeof (struct regexp));
4668 REGEXP_REPEAT (result)->regexp
4669 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4671 else if (regexp->mode == rm_sequence)
4673 result = copy_node (regexp,
4674 sizeof (struct regexp) + sizeof (regexp_t)
4675 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4676 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4677 REGEXP_SEQUENCE (result)->regexps [i]
4678 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4680 else if (regexp->mode == rm_allof)
4682 result = copy_node (regexp,
4683 sizeof (struct regexp) + sizeof (regexp_t)
4684 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4685 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4686 REGEXP_ALLOF (result)->regexps [i]
4687 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4689 else if (regexp->mode == rm_oneof)
4691 result = copy_node (regexp,
4692 sizeof (struct regexp) + sizeof (regexp_t)
4693 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4694 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4695 REGEXP_ONEOF (result)->regexps [i]
4696 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4698 else
4700 if (regexp->mode != rm_nothing)
4701 abort ();
4702 result = copy_node (regexp, sizeof (struct regexp));
4704 return result;
4707 /* The following variable is set up 1 if a transformation has been
4708 applied. */
4709 static int regexp_transformed_p;
4711 /* The function makes transformation
4712 A*N -> A, A, ... */
4713 static regexp_t
4714 transform_1 (regexp)
4715 regexp_t regexp;
4717 int i;
4718 int repeat_num;
4719 regexp_t operand;
4720 pos_t pos;
4722 if (regexp->mode == rm_repeat)
4724 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4725 if (repeat_num <= 1)
4726 abort ();
4727 operand = REGEXP_REPEAT (regexp)->regexp;
4728 pos = regexp->mode;
4729 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4730 * (repeat_num - 1));
4731 regexp->mode = rm_sequence;
4732 regexp->pos = pos;
4733 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4734 for (i = 0; i < repeat_num; i++)
4735 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4736 regexp_transformed_p = 1;
4738 return regexp;
4741 /* The function makes transformations
4742 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4743 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4744 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4745 static regexp_t
4746 transform_2 (regexp)
4747 regexp_t regexp;
4749 if (regexp->mode == rm_sequence)
4751 regexp_t sequence = NULL;
4752 regexp_t result;
4753 int sequence_index = 0;
4754 int i, j;
4756 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4757 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4759 sequence_index = i;
4760 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4761 break;
4763 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4765 if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
4766 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4767 abort ();
4768 result = create_node (sizeof (struct regexp)
4769 + sizeof (regexp_t)
4770 * (REGEXP_SEQUENCE (regexp)->regexps_num
4771 + REGEXP_SEQUENCE (sequence)->regexps_num
4772 - 2));
4773 result->mode = rm_sequence;
4774 result->pos = regexp->pos;
4775 REGEXP_SEQUENCE (result)->regexps_num
4776 = (REGEXP_SEQUENCE (regexp)->regexps_num
4777 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4778 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4779 if (i < sequence_index)
4780 REGEXP_SEQUENCE (result)->regexps [i]
4781 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4782 else if (i > sequence_index)
4783 REGEXP_SEQUENCE (result)->regexps
4784 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4785 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4786 else
4787 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4788 REGEXP_SEQUENCE (result)->regexps [i + j]
4789 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4790 regexp_transformed_p = 1;
4791 regexp = result;
4794 else if (regexp->mode == rm_allof)
4796 regexp_t allof = NULL;
4797 regexp_t result;
4798 int allof_index = 0;
4799 int i, j;
4801 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4802 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4804 allof_index = i;
4805 allof = REGEXP_ALLOF (regexp)->regexps [i];
4806 break;
4808 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4810 if (REGEXP_ALLOF (allof)->regexps_num <= 1
4811 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4812 abort ();
4813 result = create_node (sizeof (struct regexp)
4814 + sizeof (regexp_t)
4815 * (REGEXP_ALLOF (regexp)->regexps_num
4816 + REGEXP_ALLOF (allof)->regexps_num - 2));
4817 result->mode = rm_allof;
4818 result->pos = regexp->pos;
4819 REGEXP_ALLOF (result)->regexps_num
4820 = (REGEXP_ALLOF (regexp)->regexps_num
4821 + REGEXP_ALLOF (allof)->regexps_num - 1);
4822 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4823 if (i < allof_index)
4824 REGEXP_ALLOF (result)->regexps [i]
4825 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4826 else if (i > allof_index)
4827 REGEXP_ALLOF (result)->regexps
4828 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4829 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4830 else
4831 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4832 REGEXP_ALLOF (result)->regexps [i + j]
4833 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4834 regexp_transformed_p = 1;
4835 regexp = result;
4838 else if (regexp->mode == rm_oneof)
4840 regexp_t oneof = NULL;
4841 regexp_t result;
4842 int oneof_index = 0;
4843 int i, j;
4845 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4846 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4848 oneof_index = i;
4849 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4850 break;
4852 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4854 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4855 || REGEXP_ONEOF (regexp)->regexps_num <= 1)
4856 abort ();
4857 result = create_node (sizeof (struct regexp)
4858 + sizeof (regexp_t)
4859 * (REGEXP_ONEOF (regexp)->regexps_num
4860 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4861 result->mode = rm_oneof;
4862 result->pos = regexp->pos;
4863 REGEXP_ONEOF (result)->regexps_num
4864 = (REGEXP_ONEOF (regexp)->regexps_num
4865 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4866 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4867 if (i < oneof_index)
4868 REGEXP_ONEOF (result)->regexps [i]
4869 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4870 else if (i > oneof_index)
4871 REGEXP_ONEOF (result)->regexps
4872 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4873 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4874 else
4875 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4876 REGEXP_ONEOF (result)->regexps [i + j]
4877 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4878 regexp_transformed_p = 1;
4879 regexp = result;
4882 return regexp;
4885 /* The function makes transformations
4886 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4887 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4888 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4889 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4890 static regexp_t
4891 transform_3 (regexp)
4892 regexp_t regexp;
4894 if (regexp->mode == rm_sequence)
4896 regexp_t oneof = NULL;
4897 int oneof_index = 0;
4898 regexp_t result;
4899 regexp_t sequence;
4900 int i, j;
4902 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4903 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4905 oneof_index = i;
4906 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4907 break;
4909 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4911 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4912 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4913 abort ();
4914 result = create_node (sizeof (struct regexp)
4915 + sizeof (regexp_t)
4916 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4917 result->mode = rm_oneof;
4918 result->pos = regexp->pos;
4919 REGEXP_ONEOF (result)->regexps_num
4920 = REGEXP_ONEOF (oneof)->regexps_num;
4921 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4923 sequence
4924 = create_node (sizeof (struct regexp)
4925 + sizeof (regexp_t)
4926 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4927 sequence->mode = rm_sequence;
4928 sequence->pos = regexp->pos;
4929 REGEXP_SEQUENCE (sequence)->regexps_num
4930 = REGEXP_SEQUENCE (regexp)->regexps_num;
4931 REGEXP_ONEOF (result)->regexps [i] = sequence;
4932 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4933 if (j != oneof_index)
4934 REGEXP_SEQUENCE (sequence)->regexps [j]
4935 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4936 else
4937 REGEXP_SEQUENCE (sequence)->regexps [j]
4938 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4940 regexp_transformed_p = 1;
4941 regexp = result;
4944 else if (regexp->mode == rm_allof)
4946 regexp_t oneof = NULL, seq;
4947 int oneof_index = 0, max_seq_length, allof_length;
4948 regexp_t result;
4949 regexp_t allof = NULL, allof_op = NULL;
4950 int i, j;
4952 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4953 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4955 oneof_index = i;
4956 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4957 break;
4959 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4961 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4962 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4963 abort ();
4964 result = create_node (sizeof (struct regexp)
4965 + sizeof (regexp_t)
4966 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4967 result->mode = rm_oneof;
4968 result->pos = regexp->pos;
4969 REGEXP_ONEOF (result)->regexps_num
4970 = REGEXP_ONEOF (oneof)->regexps_num;
4971 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4973 allof
4974 = create_node (sizeof (struct regexp)
4975 + sizeof (regexp_t)
4976 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4977 allof->mode = rm_allof;
4978 allof->pos = regexp->pos;
4979 REGEXP_ALLOF (allof)->regexps_num
4980 = REGEXP_ALLOF (regexp)->regexps_num;
4981 REGEXP_ONEOF (result)->regexps [i] = allof;
4982 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4983 if (j != oneof_index)
4984 REGEXP_ALLOF (allof)->regexps [j]
4985 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4986 else
4987 REGEXP_ALLOF (allof)->regexps [j]
4988 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4990 regexp_transformed_p = 1;
4991 regexp = result;
4993 max_seq_length = 0;
4994 if (regexp->mode == rm_allof)
4995 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4996 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
4998 seq = REGEXP_ALLOF (regexp)->regexps [i];
4999 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
5000 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
5002 else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit)
5004 max_seq_length = 0;
5005 break;
5007 if (max_seq_length != 0)
5009 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5010 abort ();
5011 result = create_node (sizeof (struct regexp)
5012 + sizeof (regexp_t) * (max_seq_length - 1));
5013 result->mode = rm_sequence;
5014 result->pos = regexp->pos;
5015 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5016 for (i = 0; i < max_seq_length; i++)
5018 allof_length = 0;
5019 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5020 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5021 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5022 ->regexps [j])->regexps_num)))
5024 allof_op
5025 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5026 ->regexps [i]);
5027 allof_length++;
5029 else if (i == 0
5030 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5031 == rm_unit))
5033 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5034 allof_length++;
5036 if (allof_length == 1)
5037 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5038 else
5040 allof = create_node (sizeof (struct regexp)
5041 + sizeof (regexp_t)
5042 * (allof_length - 1));
5043 allof->mode = rm_allof;
5044 allof->pos = regexp->pos;
5045 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5046 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5047 allof_length = 0;
5048 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5049 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5050 && (i <
5051 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5052 ->regexps [j])->regexps_num)))
5054 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5055 ->regexps [j])
5056 ->regexps [i]);
5057 REGEXP_ALLOF (allof)->regexps [allof_length]
5058 = allof_op;
5059 allof_length++;
5061 else if (i == 0
5062 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5063 == rm_unit))
5065 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5066 REGEXP_ALLOF (allof)->regexps [allof_length]
5067 = allof_op;
5068 allof_length++;
5072 regexp_transformed_p = 1;
5073 regexp = result;
5076 return regexp;
5079 /* The function traverses IR of reservation and applies transformations
5080 implemented by FUNC. */
5081 static regexp_t
5082 regexp_transform_func (regexp, func)
5083 regexp_t regexp;
5084 regexp_t (*func) PARAMS ((regexp_t regexp));
5086 int i;
5088 if (regexp->mode == rm_sequence)
5089 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5090 REGEXP_SEQUENCE (regexp)->regexps [i]
5091 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5092 else if (regexp->mode == rm_allof)
5093 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5094 REGEXP_ALLOF (regexp)->regexps [i]
5095 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5096 else if (regexp->mode == rm_oneof)
5097 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5098 REGEXP_ONEOF (regexp)->regexps [i]
5099 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5100 else if (regexp->mode == rm_repeat)
5101 REGEXP_REPEAT (regexp)->regexp
5102 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5103 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5104 abort ();
5105 return (*func) (regexp);
5108 /* The function applies all transformations for IR representation of
5109 reservation REGEXP. */
5110 static regexp_t
5111 transform_regexp (regexp)
5112 regexp_t regexp;
5114 regexp = regexp_transform_func (regexp, transform_1);
5117 regexp_transformed_p = 0;
5118 regexp = regexp_transform_func (regexp, transform_2);
5119 regexp = regexp_transform_func (regexp, transform_3);
5121 while (regexp_transformed_p);
5122 return regexp;
5125 /* The function applys all transformations for reservations of all
5126 insn declarations. */
5127 static void
5128 transform_insn_regexps ()
5130 decl_t decl;
5131 int i;
5133 transform_time = create_ticker ();
5134 add_advance_cycle_insn_decl ();
5135 fprintf (stderr, "Reservation transformation...");
5136 fflush (stderr);
5137 for (i = 0; i < description->decls_num; i++)
5139 decl = description->decls [i];
5140 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5141 DECL_INSN_RESERV (decl)->transformed_regexp
5142 = transform_regexp (copy_insn_regexp
5143 (DECL_INSN_RESERV (decl)->regexp));
5145 fprintf (stderr, "done\n");
5146 ticker_off (&transform_time);
5147 fflush (stderr);
5152 /* The following variable is an array indexed by cycle. Each element
5153 contains cyclic list of units which should be in the same cycle. */
5154 static unit_decl_t *the_same_automaton_lists;
5156 /* The function processes all alternative reservations on CYCLE in
5157 given REGEXP to check the UNIT is not reserved on the all
5158 alternatives. If it is true, the unit should be in the same
5159 automaton with other analogous units reserved on CYCLE in given
5160 REGEXP. */
5161 static void
5162 process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
5163 regexp_t unit;
5164 regexp_t regexp;
5165 int cycle;
5167 int i, k;
5168 regexp_t seq, allof;
5169 unit_decl_t unit_decl, last;
5171 if (regexp == NULL || regexp->mode != rm_oneof)
5172 abort ();
5173 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5174 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5176 seq = REGEXP_ONEOF (regexp)->regexps [i];
5177 if (seq->mode == rm_sequence)
5179 if (cycle >= REGEXP_SEQUENCE (seq)->regexps_num)
5180 break;
5181 allof = REGEXP_SEQUENCE (seq)->regexps [cycle];
5182 if (allof->mode == rm_allof)
5184 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5185 if (REGEXP_ALLOF (allof)->regexps [k]->mode == rm_unit
5186 && (REGEXP_UNIT (REGEXP_ALLOF (allof)->regexps [k])
5187 ->unit_decl == unit_decl))
5188 break;
5189 if (k >= REGEXP_ALLOF (allof)->regexps_num)
5190 break;
5192 else if (allof->mode == rm_unit
5193 && REGEXP_UNIT (allof)->unit_decl != unit_decl)
5194 break;
5196 else if (cycle != 0)
5197 break;
5198 else if (seq->mode == rm_allof)
5200 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5201 if (REGEXP_ALLOF (seq)->regexps [k]->mode == rm_unit
5202 && (REGEXP_UNIT (REGEXP_ALLOF (seq)->regexps [k])->unit_decl
5203 == unit_decl))
5204 break;
5205 if (k >= REGEXP_ALLOF (seq)->regexps_num)
5206 break;
5208 else if (seq->mode == rm_unit
5209 && REGEXP_UNIT (seq)->unit_decl != unit_decl)
5210 break;
5212 if (i >= 0)
5214 if (the_same_automaton_lists [cycle] == NULL)
5215 the_same_automaton_lists [cycle] = unit_decl;
5216 else
5218 for (last = the_same_automaton_lists [cycle];;)
5220 if (last == unit_decl)
5221 return;
5222 if (last->the_same_automaton_unit
5223 == the_same_automaton_lists [cycle])
5224 break;
5225 last = last->the_same_automaton_unit;
5227 last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
5228 unit_decl->the_same_automaton_unit
5229 = the_same_automaton_lists [cycle];
5234 /* The function processes given REGEXP to find units which should be
5235 in the same automaton. */
5236 static void
5237 form_the_same_automaton_unit_lists_from_regexp (regexp)
5238 regexp_t regexp;
5240 int i, j, k;
5241 regexp_t seq, allof, unit;
5243 if (regexp == NULL || regexp->mode != rm_oneof)
5244 return;
5245 for (i = 0; i < description->max_insn_reserv_cycles; i++)
5246 the_same_automaton_lists [i] = NULL;
5247 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5249 seq = REGEXP_ONEOF (regexp)->regexps [i];
5250 if (seq->mode == rm_sequence)
5251 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5253 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5254 if (allof->mode == rm_allof)
5255 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5257 unit = REGEXP_ALLOF (allof)->regexps [k];
5258 if (unit->mode == rm_unit)
5259 process_unit_to_form_the_same_automaton_unit_lists
5260 (unit, regexp, j);
5261 else if (unit->mode != rm_nothing)
5262 abort ();
5264 else if (allof->mode == rm_unit)
5265 process_unit_to_form_the_same_automaton_unit_lists
5266 (allof, regexp, j);
5267 else if (allof->mode != rm_nothing)
5268 abort ();
5270 else if (seq->mode == rm_allof)
5271 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5273 unit = REGEXP_ALLOF (seq)->regexps [k];
5274 if (unit->mode == rm_unit)
5275 process_unit_to_form_the_same_automaton_unit_lists
5276 (unit, regexp, 0);
5277 else if (unit->mode != rm_nothing)
5278 abort ();
5280 else if (seq->mode == rm_unit)
5281 process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
5282 else if (seq->mode != rm_nothing)
5283 abort ();
5287 /* The function initializes data to search for units which should be
5288 in the same automaton and call function
5289 `form_the_same_automaton_unit_lists_from_regexp' for each insn
5290 reservation regexp. */
5291 static void
5292 form_the_same_automaton_unit_lists ()
5294 decl_t decl;
5295 int i;
5297 the_same_automaton_lists
5298 = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
5299 * sizeof (unit_decl_t));
5300 for (i = 0; i < description->decls_num; i++)
5302 decl = description->decls [i];
5303 if (decl->mode == dm_unit)
5305 DECL_UNIT (decl)->the_same_automaton_message_reported_p = FALSE;
5306 DECL_UNIT (decl)->the_same_automaton_unit = DECL_UNIT (decl);
5309 for (i = 0; i < description->decls_num; i++)
5311 decl = description->decls [i];
5312 if (decl->mode == dm_insn_reserv)
5313 form_the_same_automaton_unit_lists_from_regexp
5314 (DECL_INSN_RESERV (decl)->transformed_regexp);
5316 free (the_same_automaton_lists);
5319 /* The function finds units which should be in the same automaton and,
5320 if they are not, reports about it. */
5321 static void
5322 check_unit_distributions_to_automata ()
5324 decl_t decl;
5325 unit_decl_t start_unit_decl, unit_decl;
5326 int i;
5328 form_the_same_automaton_unit_lists ();
5329 for (i = 0; i < description->decls_num; i++)
5331 decl = description->decls [i];
5332 if (decl->mode == dm_unit)
5334 start_unit_decl = DECL_UNIT (decl);
5335 if (!start_unit_decl->the_same_automaton_message_reported_p)
5336 for (unit_decl = start_unit_decl->the_same_automaton_unit;
5337 unit_decl != start_unit_decl;
5338 unit_decl = unit_decl->the_same_automaton_unit)
5339 if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
5341 error ("Units `%s' and `%s' should be in the same automaton",
5342 start_unit_decl->name, unit_decl->name);
5343 unit_decl->the_same_automaton_message_reported_p = TRUE;
5351 /* The page contains code for building alt_states (see comments for
5352 IR) describing all possible insns reservations of an automaton. */
5354 /* Current state being formed for which the current alt_state
5355 refers. */
5356 static state_t state_being_formed;
5358 /* Current alt_state being formed. */
5359 static alt_state_t alt_state_being_formed;
5361 /* This recursive function processes `,' and units in reservation
5362 REGEXP for forming alt_states of AUTOMATON. It is believed that
5363 CURR_CYCLE is start cycle of all reservation REGEXP. */
5364 static int
5365 process_seq_for_forming_states (regexp, automaton, curr_cycle)
5366 regexp_t regexp;
5367 automaton_t automaton;
5368 int curr_cycle;
5370 int i;
5372 if (regexp == NULL)
5373 return curr_cycle;
5374 else if (regexp->mode == rm_unit)
5376 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5377 == automaton->automaton_order_num)
5378 set_state_reserv (state_being_formed, curr_cycle,
5379 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5380 return curr_cycle;
5382 else if (regexp->mode == rm_sequence)
5384 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5385 curr_cycle
5386 = process_seq_for_forming_states
5387 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5388 return curr_cycle;
5390 else if (regexp->mode == rm_allof)
5392 int finish_cycle = 0;
5393 int cycle;
5395 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5397 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5398 ->regexps [i],
5399 automaton, curr_cycle);
5400 if (finish_cycle < cycle)
5401 finish_cycle = cycle;
5403 return finish_cycle;
5405 else
5407 if (regexp->mode != rm_nothing)
5408 abort ();
5409 return curr_cycle;
5413 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5414 inserts alt_state into the table. */
5415 static void
5416 finish_forming_alt_state (alt_state, automaton)
5417 alt_state_t alt_state;
5418 automaton_t automaton ATTRIBUTE_UNUSED;
5420 state_t state_in_table;
5421 state_t corresponding_state;
5423 corresponding_state = alt_state->state;
5424 state_in_table = insert_state (corresponding_state);
5425 if (state_in_table != corresponding_state)
5427 free_state (corresponding_state);
5428 alt_state->state = state_in_table;
5432 /* The following variable value is current automaton insn for whose
5433 reservation the alt states are created. */
5434 static ainsn_t curr_ainsn;
5436 /* This recursive function processes `|' in reservation REGEXP for
5437 forming alt_states of AUTOMATON. List of the alt states should
5438 have the same order as in the description. */
5439 static void
5440 process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5441 regexp_t regexp;
5442 automaton_t automaton;
5443 int inside_oneof_p;
5445 int i;
5447 if (regexp->mode != rm_oneof)
5449 alt_state_being_formed = get_free_alt_state ();
5450 state_being_formed = get_free_state (1, automaton);
5451 alt_state_being_formed->state = state_being_formed;
5452 /* We inserts in reverse order but we process alternatives also
5453 in reverse order. So we have the same order of alternative
5454 as in the description. */
5455 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5456 curr_ainsn->alt_states = alt_state_being_formed;
5457 (void) process_seq_for_forming_states (regexp, automaton, 0);
5458 finish_forming_alt_state (alt_state_being_formed, automaton);
5460 else
5462 if (inside_oneof_p)
5463 abort ();
5464 /* We processes it in reverse order to get list with the same
5465 order as in the description. See also the previous
5466 commentary. */
5467 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5468 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5469 automaton, 1);
5473 /* Create nodes alt_state for all AUTOMATON insns. */
5474 static void
5475 create_alt_states (automaton)
5476 automaton_t automaton;
5478 struct insn_reserv_decl *reserv_decl;
5480 for (curr_ainsn = automaton->ainsn_list;
5481 curr_ainsn != NULL;
5482 curr_ainsn = curr_ainsn->next_ainsn)
5484 reserv_decl = curr_ainsn->insn_reserv_decl;
5485 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5487 curr_ainsn->alt_states = NULL;
5488 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5489 automaton, 0);
5490 curr_ainsn->sorted_alt_states
5491 = uniq_sort_alt_states (curr_ainsn->alt_states);
5498 /* The page contains major code for building DFA(s) for fast pipeline
5499 hazards recognition. */
5501 /* The function forms list of ainsns of AUTOMATON with the same
5502 reservation. */
5503 static void
5504 form_ainsn_with_same_reservs (automaton)
5505 automaton_t automaton;
5507 ainsn_t curr_ainsn;
5508 size_t i;
5509 vla_ptr_t first_insns;
5510 vla_ptr_t last_insns;
5512 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5513 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5514 for (curr_ainsn = automaton->ainsn_list;
5515 curr_ainsn != NULL;
5516 curr_ainsn = curr_ainsn->next_ainsn)
5517 if (curr_ainsn->insn_reserv_decl
5518 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5520 curr_ainsn->next_same_reservs_insn = NULL;
5521 curr_ainsn->first_insn_with_same_reservs = 1;
5523 else
5525 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5526 if (alt_states_eq
5527 (curr_ainsn->sorted_alt_states,
5528 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5529 break;
5530 curr_ainsn->next_same_reservs_insn = NULL;
5531 if (i < VLA_PTR_LENGTH (first_insns))
5533 curr_ainsn->first_insn_with_same_reservs = 0;
5534 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5535 = curr_ainsn;
5536 VLA_PTR (last_insns, i) = curr_ainsn;
5538 else
5540 VLA_PTR_ADD (first_insns, curr_ainsn);
5541 VLA_PTR_ADD (last_insns, curr_ainsn);
5542 curr_ainsn->first_insn_with_same_reservs = 1;
5545 VLA_PTR_DELETE (first_insns);
5546 VLA_PTR_DELETE (last_insns);
5549 /* The following function creates all states of nondeterministic (if
5550 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5551 static void
5552 make_automaton (automaton)
5553 automaton_t automaton;
5555 ainsn_t ainsn;
5556 struct insn_reserv_decl *insn_reserv_decl;
5557 alt_state_t alt_state;
5558 state_t state;
5559 state_t start_state;
5560 state_t state2;
5561 ainsn_t advance_cycle_ainsn;
5562 arc_t added_arc;
5563 vla_ptr_t state_stack;
5565 VLA_PTR_CREATE (state_stack, 150, "state stack");
5566 /* Create the start state (empty state). */
5567 start_state = insert_state (get_free_state (1, automaton));
5568 automaton->start_state = start_state;
5569 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5570 VLA_PTR_ADD (state_stack, start_state);
5571 while (VLA_PTR_LENGTH (state_stack) != 0)
5573 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5574 VLA_PTR_SHORTEN (state_stack, 1);
5575 advance_cycle_ainsn = NULL;
5576 for (ainsn = automaton->ainsn_list;
5577 ainsn != NULL;
5578 ainsn = ainsn->next_ainsn)
5579 if (ainsn->first_insn_with_same_reservs)
5581 insn_reserv_decl = ainsn->insn_reserv_decl;
5582 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5584 /* We process alt_states in the same order as they are
5585 present in the description. */
5586 added_arc = NULL;
5587 for (alt_state = ainsn->alt_states;
5588 alt_state != NULL;
5589 alt_state = alt_state->next_alt_state)
5591 state2 = alt_state->state;
5592 if (!intersected_state_reservs_p (state, state2))
5594 state2 = states_union (state, state2);
5595 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5597 state2->it_was_placed_in_stack_for_NDFA_forming
5598 = 1;
5599 VLA_PTR_ADD (state_stack, state2);
5601 added_arc = add_arc (state, state2, ainsn, 1);
5602 if (!ndfa_flag)
5603 break;
5606 if (!ndfa_flag && added_arc != NULL)
5608 added_arc->state_alts = 0;
5609 for (alt_state = ainsn->alt_states;
5610 alt_state != NULL;
5611 alt_state = alt_state->next_alt_state)
5613 state2 = alt_state->state;
5614 if (!intersected_state_reservs_p (state, state2))
5615 added_arc->state_alts++;
5619 else
5620 advance_cycle_ainsn = ainsn;
5622 /* Add transition to advance cycle. */
5623 state2 = state_shift (state);
5624 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5626 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5627 VLA_PTR_ADD (state_stack, state2);
5629 if (advance_cycle_ainsn == NULL)
5630 abort ();
5631 add_arc (state, state2, advance_cycle_ainsn, 1);
5633 VLA_PTR_DELETE (state_stack);
5636 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5637 static void
5638 form_arcs_marked_by_insn (state)
5639 state_t state;
5641 decl_t decl;
5642 arc_t arc;
5643 int i;
5645 for (i = 0; i < description->decls_num; i++)
5647 decl = description->decls [i];
5648 if (decl->mode == dm_insn_reserv)
5649 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5651 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5653 if (arc->insn == NULL)
5654 abort ();
5655 arc->next_arc_marked_by_insn
5656 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5657 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5661 /* The function creates composed state (see comments for IR) from
5662 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5663 same insn. If the composed state is not in STATE_STACK yet, it is
5664 popped to STATE_STACK. */
5665 static void
5666 create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5667 state_t original_state;
5668 arc_t arcs_marked_by_insn;
5669 vla_ptr_t *state_stack;
5671 state_t state;
5672 alt_state_t curr_alt_state;
5673 alt_state_t new_alt_state;
5674 arc_t curr_arc;
5675 arc_t next_arc;
5676 state_t state_in_table;
5677 state_t temp_state;
5678 alt_state_t canonical_alt_states_list;
5679 int alts_number;
5681 if (arcs_marked_by_insn == NULL)
5682 return;
5683 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5684 state = arcs_marked_by_insn->to_state;
5685 else
5687 if (!ndfa_flag)
5688 abort ();
5689 /* Create composed state. */
5690 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5691 curr_alt_state = NULL;
5692 for (curr_arc = arcs_marked_by_insn;
5693 curr_arc != NULL;
5694 curr_arc = curr_arc->next_arc_marked_by_insn)
5696 new_alt_state = get_free_alt_state ();
5697 new_alt_state->next_alt_state = curr_alt_state;
5698 new_alt_state->state = curr_arc->to_state;
5699 if (curr_arc->to_state->component_states != NULL)
5700 abort ();
5701 curr_alt_state = new_alt_state;
5703 /* There are not identical sets in the alt state list. */
5704 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5705 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5707 temp_state = state;
5708 state = canonical_alt_states_list->state;
5709 free_state (temp_state);
5711 else
5713 state->component_states = canonical_alt_states_list;
5714 state_in_table = insert_state (state);
5715 if (state_in_table != state)
5717 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5718 abort ();
5719 free_state (state);
5720 state = state_in_table;
5722 else
5724 if (state->it_was_placed_in_stack_for_DFA_forming)
5725 abort ();
5726 for (curr_alt_state = state->component_states;
5727 curr_alt_state != NULL;
5728 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5729 for (curr_arc = first_out_arc (curr_alt_state->state);
5730 curr_arc != NULL;
5731 curr_arc = next_out_arc (curr_arc))
5732 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5734 arcs_marked_by_insn->to_state = state;
5735 for (alts_number = 0,
5736 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5737 curr_arc != NULL;
5738 curr_arc = next_arc)
5740 next_arc = curr_arc->next_arc_marked_by_insn;
5741 remove_arc (original_state, curr_arc);
5742 alts_number++;
5744 arcs_marked_by_insn->state_alts = alts_number;
5747 if (!state->it_was_placed_in_stack_for_DFA_forming)
5749 state->it_was_placed_in_stack_for_DFA_forming = 1;
5750 VLA_PTR_ADD (*state_stack, state);
5754 /* The function transformes nondeterminstic AUTOMATON into
5755 deterministic. */
5756 static void
5757 NDFA_to_DFA (automaton)
5758 automaton_t automaton;
5760 state_t start_state;
5761 state_t state;
5762 decl_t decl;
5763 vla_ptr_t state_stack;
5764 int i;
5766 VLA_PTR_CREATE (state_stack, 150, "state stack");
5767 /* Create the start state (empty state). */
5768 start_state = automaton->start_state;
5769 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5770 VLA_PTR_ADD (state_stack, start_state);
5771 while (VLA_PTR_LENGTH (state_stack) != 0)
5773 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5774 VLA_PTR_SHORTEN (state_stack, 1);
5775 form_arcs_marked_by_insn (state);
5776 for (i = 0; i < description->decls_num; i++)
5778 decl = description->decls [i];
5779 if (decl->mode == dm_insn_reserv)
5780 create_composed_state
5781 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5782 &state_stack);
5785 VLA_PTR_DELETE (state_stack);
5788 /* The following variable value is current number (1, 2, ...) of passing
5789 graph of states. */
5790 static int curr_state_graph_pass_num;
5792 /* This recursive function passes all states achieved from START_STATE
5793 and applies APPLIED_FUNC to them. */
5794 static void
5795 pass_state_graph (start_state, applied_func)
5796 state_t start_state;
5797 void (*applied_func) PARAMS ((state_t state));
5799 arc_t arc;
5801 if (start_state->pass_num == curr_state_graph_pass_num)
5802 return;
5803 start_state->pass_num = curr_state_graph_pass_num;
5804 (*applied_func) (start_state);
5805 for (arc = first_out_arc (start_state);
5806 arc != NULL;
5807 arc = next_out_arc (arc))
5808 pass_state_graph (arc->to_state, applied_func);
5811 /* This recursive function passes all states of AUTOMATON and applies
5812 APPLIED_FUNC to them. */
5813 static void
5814 pass_states (automaton, applied_func)
5815 automaton_t automaton;
5816 void (*applied_func) PARAMS ((state_t state));
5818 curr_state_graph_pass_num++;
5819 pass_state_graph (automaton->start_state, applied_func);
5822 /* The function initializes code for passing of all states. */
5823 static void
5824 initiate_pass_states ()
5826 curr_state_graph_pass_num = 0;
5829 /* The following vla is used for storing pointers to all achieved
5830 states. */
5831 static vla_ptr_t all_achieved_states;
5833 /* This function is called by function pass_states to add an achieved
5834 STATE. */
5835 static void
5836 add_achieved_state (state)
5837 state_t state;
5839 VLA_PTR_ADD (all_achieved_states, state);
5842 /* The function sets up equivalence numbers of insns which mark all
5843 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5844 nonzero value) or by equiv_class_num_2 of the destination state.
5845 The function returns number of out arcs of STATE. */
5846 static int
5847 set_out_arc_insns_equiv_num (state, odd_iteration_flag)
5848 state_t state;
5849 int odd_iteration_flag;
5851 int state_out_arcs_num;
5852 arc_t arc;
5854 state_out_arcs_num = 0;
5855 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5857 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
5858 || arc->insn->insn_reserv_decl->state_alts != 0)
5859 abort ();
5860 state_out_arcs_num++;
5861 arc->insn->insn_reserv_decl->equiv_class_num
5862 = (odd_iteration_flag
5863 ? arc->to_state->equiv_class_num_1
5864 : arc->to_state->equiv_class_num_2);
5865 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
5866 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
5867 || arc->insn->insn_reserv_decl->state_alts <= 0)
5868 abort ();
5870 return state_out_arcs_num;
5873 /* The function clears equivalence numbers and alt_states in all insns
5874 which mark all out arcs of STATE. */
5875 static void
5876 clear_arc_insns_equiv_num (state)
5877 state_t state;
5879 arc_t arc;
5881 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5883 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5884 arc->insn->insn_reserv_decl->state_alts = 0;
5888 /* The function copies pointers to equivalent states from vla FROM
5889 into vla TO. */
5890 static void
5891 copy_equiv_class (to, from)
5892 vla_ptr_t *to;
5893 const vla_ptr_t *from;
5895 state_t *class_ptr;
5897 VLA_PTR_NULLIFY (*to);
5898 for (class_ptr = VLA_PTR_BEGIN (*from);
5899 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
5900 class_ptr++)
5901 VLA_PTR_ADD (*to, *class_ptr);
5904 /* The function returns nonzero value if STATE is not equivalent to
5905 another state from the same current partition on equivalence
5906 classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of
5907 output arcs. Iteration of making equivalence partition is defined
5908 by ODD_ITERATION_FLAG. */
5909 static int
5910 state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag)
5911 state_t state;
5912 int original_state_out_arcs_num;
5913 int odd_iteration_flag;
5915 arc_t arc;
5916 int state_out_arcs_num;
5918 state_out_arcs_num = 0;
5919 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5921 state_out_arcs_num++;
5922 if ((odd_iteration_flag
5923 ? arc->to_state->equiv_class_num_1
5924 : arc->to_state->equiv_class_num_2)
5925 != arc->insn->insn_reserv_decl->equiv_class_num
5926 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
5927 return 1;
5929 return state_out_arcs_num != original_state_out_arcs_num;
5932 /* The function makes initial partition of STATES on equivalent
5933 classes. */
5934 static state_t
5935 init_equiv_class (states, states_num)
5936 state_t *states;
5937 int states_num;
5939 state_t *state_ptr;
5940 state_t result_equiv_class;
5942 result_equiv_class = NULL;
5943 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
5945 (*state_ptr)->equiv_class_num_1 = 1;
5946 (*state_ptr)->next_equiv_class_state = result_equiv_class;
5947 result_equiv_class = *state_ptr;
5949 return result_equiv_class;
5952 /* The function processes equivalence class given by its pointer
5953 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
5954 are not equvalent states, the function partitions the class
5955 removing nonequivalent states and placing them in
5956 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5957 assigns it to the state equivalence number. If the class has been
5958 partitioned, the function returns nonzero value. */
5959 static int
5960 partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5961 next_iteration_classes, new_equiv_class_num_ptr)
5962 state_t *equiv_class_ptr;
5963 int odd_iteration_flag;
5964 vla_ptr_t *next_iteration_classes;
5965 int *new_equiv_class_num_ptr;
5967 state_t new_equiv_class;
5968 int partition_p;
5969 state_t first_state;
5970 state_t curr_state;
5971 state_t prev_state;
5972 state_t next_state;
5973 int out_arcs_num;
5975 partition_p = 0;
5976 if (*equiv_class_ptr == NULL)
5977 abort ();
5978 for (first_state = *equiv_class_ptr;
5979 first_state != NULL;
5980 first_state = new_equiv_class)
5982 new_equiv_class = NULL;
5983 if (first_state->next_equiv_class_state != NULL)
5985 /* There are more one states in the class equivalence. */
5986 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
5987 odd_iteration_flag);
5988 for (prev_state = first_state,
5989 curr_state = first_state->next_equiv_class_state;
5990 curr_state != NULL;
5991 curr_state = next_state)
5993 next_state = curr_state->next_equiv_class_state;
5994 if (state_is_differed (curr_state, out_arcs_num,
5995 odd_iteration_flag))
5997 /* Remove curr state from the class equivalence. */
5998 prev_state->next_equiv_class_state = next_state;
5999 /* Add curr state to the new class equivalence. */
6000 curr_state->next_equiv_class_state = new_equiv_class;
6001 if (new_equiv_class == NULL)
6002 (*new_equiv_class_num_ptr)++;
6003 if (odd_iteration_flag)
6004 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6005 else
6006 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6007 new_equiv_class = curr_state;
6008 partition_p = 1;
6010 else
6011 prev_state = curr_state;
6013 clear_arc_insns_equiv_num (first_state);
6015 if (new_equiv_class != NULL)
6016 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
6018 return partition_p;
6021 /* The function finds equivalent states of AUTOMATON. */
6022 static void
6023 evaluate_equiv_classes (automaton, equiv_classes)
6024 automaton_t automaton;
6025 vla_ptr_t *equiv_classes;
6027 state_t new_equiv_class;
6028 int new_equiv_class_num;
6029 int odd_iteration_flag;
6030 int finish_flag;
6031 vla_ptr_t next_iteration_classes;
6032 state_t *equiv_class_ptr;
6033 state_t *state_ptr;
6035 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6036 pass_states (automaton, add_achieved_state);
6037 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6038 VLA_PTR_LENGTH (all_achieved_states));
6039 odd_iteration_flag = 0;
6040 new_equiv_class_num = 1;
6041 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6042 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6045 odd_iteration_flag = !odd_iteration_flag;
6046 finish_flag = 1;
6047 copy_equiv_class (equiv_classes, &next_iteration_classes);
6048 /* Transfer equiv numbers for the next iteration. */
6049 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6050 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6051 state_ptr++)
6052 if (odd_iteration_flag)
6053 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6054 else
6055 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6056 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6057 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6058 equiv_class_ptr++)
6059 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6060 &next_iteration_classes,
6061 &new_equiv_class_num))
6062 finish_flag = 0;
6064 while (!finish_flag);
6065 VLA_PTR_DELETE (next_iteration_classes);
6066 VLA_PTR_DELETE (all_achieved_states);
6069 /* The function merges equivalent states of AUTOMATON. */
6070 static void
6071 merge_states (automaton, equiv_classes)
6072 automaton_t automaton;
6073 vla_ptr_t *equiv_classes;
6075 state_t *equiv_class_ptr;
6076 state_t curr_state;
6077 state_t new_state;
6078 state_t first_class_state;
6079 alt_state_t alt_states;
6080 alt_state_t new_alt_state;
6081 arc_t curr_arc;
6082 arc_t next_arc;
6084 /* Create states corresponding to equivalence classes containing two
6085 or more states. */
6086 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6087 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6088 equiv_class_ptr++)
6089 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6091 /* There are more one states in the class equivalence. */
6092 /* Create new compound state. */
6093 new_state = get_free_state (0, automaton);
6094 alt_states = NULL;
6095 first_class_state = *equiv_class_ptr;
6096 for (curr_state = first_class_state;
6097 curr_state != NULL;
6098 curr_state = curr_state->next_equiv_class_state)
6100 curr_state->equiv_class_state = new_state;
6101 new_alt_state = get_free_alt_state ();
6102 new_alt_state->state = curr_state;
6103 new_alt_state->next_sorted_alt_state = alt_states;
6104 alt_states = new_alt_state;
6106 new_state->component_states = alt_states;
6108 else
6109 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6110 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6111 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6112 equiv_class_ptr++)
6113 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6115 first_class_state = *equiv_class_ptr;
6116 /* Create new arcs output from the state corresponding to
6117 equiv class. */
6118 for (curr_arc = first_out_arc (first_class_state);
6119 curr_arc != NULL;
6120 curr_arc = next_out_arc (curr_arc))
6121 add_arc (first_class_state->equiv_class_state,
6122 curr_arc->to_state->equiv_class_state,
6123 curr_arc->insn, curr_arc->state_alts);
6124 /* Delete output arcs from states of given class equivalence. */
6125 for (curr_state = first_class_state;
6126 curr_state != NULL;
6127 curr_state = curr_state->next_equiv_class_state)
6129 if (automaton->start_state == curr_state)
6130 automaton->start_state = curr_state->equiv_class_state;
6131 /* Delete the state and its output arcs. */
6132 for (curr_arc = first_out_arc (curr_state);
6133 curr_arc != NULL;
6134 curr_arc = next_arc)
6136 next_arc = next_out_arc (curr_arc);
6137 free_arc (curr_arc);
6141 else
6143 /* Change `to_state' of arcs output from the state of given
6144 equivalence class. */
6145 for (curr_arc = first_out_arc (*equiv_class_ptr);
6146 curr_arc != NULL;
6147 curr_arc = next_out_arc (curr_arc))
6148 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6152 /* The function sets up new_cycle_p for states if there is arc to the
6153 state marked by advance_cycle_insn_decl. */
6154 static void
6155 set_new_cycle_flags (state)
6156 state_t state;
6158 arc_t arc;
6160 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6161 if (arc->insn->insn_reserv_decl
6162 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6163 arc->to_state->new_cycle_p = 1;
6166 /* The top level function for minimization of deterministic
6167 AUTOMATON. */
6168 static void
6169 minimize_DFA (automaton)
6170 automaton_t automaton;
6172 vla_ptr_t equiv_classes;
6174 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6175 evaluate_equiv_classes (automaton, &equiv_classes);
6176 merge_states (automaton, &equiv_classes);
6177 pass_states (automaton, set_new_cycle_flags);
6178 VLA_PTR_DELETE (equiv_classes);
6181 /* Values of two variables are counted number of states and arcs in an
6182 automaton. */
6183 static int curr_counted_states_num;
6184 static int curr_counted_arcs_num;
6186 /* The function is called by function `pass_states' to count states
6187 and arcs of an automaton. */
6188 static void
6189 incr_states_and_arcs_nums (state)
6190 state_t state;
6192 arc_t arc;
6194 curr_counted_states_num++;
6195 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6196 curr_counted_arcs_num++;
6199 /* The function counts states and arcs of AUTOMATON. */
6200 static void
6201 count_states_and_arcs (automaton, states_num, arcs_num)
6202 automaton_t automaton;
6203 int *states_num;
6204 int *arcs_num;
6206 curr_counted_states_num = 0;
6207 curr_counted_arcs_num = 0;
6208 pass_states (automaton, incr_states_and_arcs_nums);
6209 *states_num = curr_counted_states_num;
6210 *arcs_num = curr_counted_arcs_num;
6213 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6214 recognition after checking and simplifying IR of the
6215 description. */
6216 static void
6217 build_automaton (automaton)
6218 automaton_t automaton;
6220 int states_num;
6221 int arcs_num;
6223 ticker_on (&NDFA_time);
6224 make_automaton (automaton);
6225 ticker_off (&NDFA_time);
6226 count_states_and_arcs (automaton, &states_num, &arcs_num);
6227 automaton->NDFA_states_num = states_num;
6228 automaton->NDFA_arcs_num = arcs_num;
6229 ticker_on (&NDFA_to_DFA_time);
6230 NDFA_to_DFA (automaton);
6231 ticker_off (&NDFA_to_DFA_time);
6232 count_states_and_arcs (automaton, &states_num, &arcs_num);
6233 automaton->DFA_states_num = states_num;
6234 automaton->DFA_arcs_num = arcs_num;
6235 if (!no_minimization_flag)
6237 ticker_on (&minimize_time);
6238 minimize_DFA (automaton);
6239 ticker_off (&minimize_time);
6240 count_states_and_arcs (automaton, &states_num, &arcs_num);
6241 automaton->minimal_DFA_states_num = states_num;
6242 automaton->minimal_DFA_arcs_num = arcs_num;
6248 /* The page contains code for enumeration of all states of an automaton. */
6250 /* Variable used for enumeration of all states of an automaton. Its
6251 value is current number of automaton states. */
6252 static int curr_state_order_num;
6254 /* The function is called by function `pass_states' for enumerating
6255 states. */
6256 static void
6257 set_order_state_num (state)
6258 state_t state;
6260 state->order_state_num = curr_state_order_num;
6261 curr_state_order_num++;
6264 /* The function enumerates all states of AUTOMATON. */
6265 static void
6266 enumerate_states (automaton)
6267 automaton_t automaton;
6269 curr_state_order_num = 0;
6270 pass_states (automaton, set_order_state_num);
6271 automaton->achieved_states_num = curr_state_order_num;
6276 /* The page contains code for finding equivalent automaton insns
6277 (ainsns). */
6279 /* The function inserts AINSN into cyclic list
6280 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6281 static ainsn_t
6282 insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6283 ainsn_t ainsn;
6284 ainsn_t cyclic_equiv_class_insn_list;
6286 if (cyclic_equiv_class_insn_list == NULL)
6287 ainsn->next_equiv_class_insn = ainsn;
6288 else
6290 ainsn->next_equiv_class_insn
6291 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6292 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6294 return ainsn;
6297 /* The function deletes equiv_class_insn into cyclic list of
6298 equivalent ainsns. */
6299 static void
6300 delete_ainsn_from_equiv_class (equiv_class_insn)
6301 ainsn_t equiv_class_insn;
6303 ainsn_t curr_equiv_class_insn;
6304 ainsn_t prev_equiv_class_insn;
6306 prev_equiv_class_insn = equiv_class_insn;
6307 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6308 curr_equiv_class_insn != equiv_class_insn;
6309 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6310 prev_equiv_class_insn = curr_equiv_class_insn;
6311 if (prev_equiv_class_insn != equiv_class_insn)
6312 prev_equiv_class_insn->next_equiv_class_insn
6313 = equiv_class_insn->next_equiv_class_insn;
6316 /* The function processes AINSN of a state in order to find equivalent
6317 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6318 state. */
6319 static void
6320 process_insn_equiv_class (ainsn, insn_arcs_array)
6321 ainsn_t ainsn;
6322 arc_t *insn_arcs_array;
6324 ainsn_t next_insn;
6325 ainsn_t curr_insn;
6326 ainsn_t cyclic_insn_list;
6327 arc_t arc;
6329 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6330 abort ();
6331 curr_insn = ainsn;
6332 /* New class of ainsns which are not equivalent to given ainsn. */
6333 cyclic_insn_list = NULL;
6336 next_insn = curr_insn->next_equiv_class_insn;
6337 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6338 if (arc == NULL
6339 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6340 != arc->to_state))
6342 delete_ainsn_from_equiv_class (curr_insn);
6343 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6344 cyclic_insn_list);
6346 curr_insn = next_insn;
6348 while (curr_insn != ainsn);
6351 /* The function processes STATE in order to find equivalent ainsns. */
6352 static void
6353 process_state_for_insn_equiv_partition (state)
6354 state_t state;
6356 arc_t arc;
6357 arc_t *insn_arcs_array;
6358 int i;
6359 vla_ptr_t insn_arcs_vect;
6361 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6362 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6363 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6364 /* Process insns of the arcs. */
6365 for (i = 0; i < description->insns_num; i++)
6366 insn_arcs_array [i] = NULL;
6367 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6368 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6369 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6370 process_insn_equiv_class (arc->insn, insn_arcs_array);
6371 VLA_PTR_DELETE (insn_arcs_vect);
6374 /* The function searches for equivalent ainsns of AUTOMATON. */
6375 static void
6376 set_insn_equiv_classes (automaton)
6377 automaton_t automaton;
6379 ainsn_t ainsn;
6380 ainsn_t first_insn;
6381 ainsn_t curr_insn;
6382 ainsn_t cyclic_insn_list;
6383 ainsn_t insn_with_same_reservs;
6384 int equiv_classes_num;
6386 /* All insns are included in one equivalence class. */
6387 cyclic_insn_list = NULL;
6388 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6389 if (ainsn->first_insn_with_same_reservs)
6390 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6391 cyclic_insn_list);
6392 /* Process insns in order to make equivalence partition. */
6393 pass_states (automaton, process_state_for_insn_equiv_partition);
6394 /* Enumerate equiv classes. */
6395 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6396 /* Set undefined value. */
6397 ainsn->insn_equiv_class_num = -1;
6398 equiv_classes_num = 0;
6399 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6400 if (ainsn->insn_equiv_class_num < 0)
6402 first_insn = ainsn;
6403 if (!first_insn->first_insn_with_same_reservs)
6404 abort ();
6405 first_insn->first_ainsn_with_given_equialence_num = 1;
6406 curr_insn = first_insn;
6409 for (insn_with_same_reservs = curr_insn;
6410 insn_with_same_reservs != NULL;
6411 insn_with_same_reservs
6412 = insn_with_same_reservs->next_same_reservs_insn)
6413 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6414 curr_insn = curr_insn->next_equiv_class_insn;
6416 while (curr_insn != first_insn);
6417 equiv_classes_num++;
6419 automaton->insn_equiv_classes_num = equiv_classes_num;
6424 /* This page contains code for creating DFA(s) and calls functions
6425 building them. */
6428 /* The following value is used to prevent floating point overflow for
6429 estimating an automaton bound. The value should be less DBL_MAX on
6430 the host machine. We use here approximate minimum of maximal
6431 double floating point value required by ANSI C standard. It
6432 will work for non ANSI sun compiler too. */
6434 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6436 /* The function estimate size of the single DFA used by PHR (pipeline
6437 hazards recognizer). */
6438 static double
6439 estimate_one_automaton_bound ()
6441 decl_t decl;
6442 double one_automaton_estimation_bound;
6443 double root_value;
6444 int i;
6446 one_automaton_estimation_bound = 1.0;
6447 for (i = 0; i < description->decls_num; i++)
6449 decl = description->decls [i];
6450 if (decl->mode == dm_unit)
6452 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num + 1.0)
6453 / automata_num);
6454 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6455 > one_automaton_estimation_bound)
6456 one_automaton_estimation_bound *= root_value;
6459 return one_automaton_estimation_bound;
6462 /* The function compares unit declarations acoording to their maximal
6463 cycle in reservations. */
6464 static int
6465 compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6466 const void *unit_decl_1;
6467 const void *unit_decl_2;
6469 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6470 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6471 return 1;
6472 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6473 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6474 return 0;
6475 else
6476 return -1;
6479 /* The function makes heuristic assigning automata to units. Actually
6480 efficacy of the algorithm has been checked yet??? */
6481 static void
6482 units_to_automata_heuristic_distr ()
6484 double estimation_bound;
6485 decl_t decl;
6486 decl_t *unit_decl_ptr;
6487 int automaton_num;
6488 int rest_units_num;
6489 double bound_value;
6490 vla_ptr_t unit_decls;
6491 int i;
6493 if (description->units_num == 0)
6494 return;
6495 estimation_bound = estimate_one_automaton_bound ();
6496 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6497 for (i = 0; i < description->decls_num; i++)
6499 decl = description->decls [i];
6500 if (decl->mode == dm_unit)
6501 VLA_PTR_ADD (unit_decls, decl);
6503 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6504 sizeof (decl_t), compare_max_occ_cycle_nums);
6505 automaton_num = 0;
6506 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6507 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6508 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6509 for (unit_decl_ptr++;
6510 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6511 unit_decl_ptr++)
6513 rest_units_num
6514 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6515 if (automata_num - automaton_num - 1 > rest_units_num)
6516 abort ();
6517 if (automaton_num < automata_num - 1
6518 && ((automata_num - automaton_num - 1 == rest_units_num)
6519 || (bound_value
6520 > (estimation_bound
6521 / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6523 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6524 automaton_num++;
6526 else
6527 bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6528 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6530 if (automaton_num != automata_num - 1)
6531 abort ();
6532 VLA_PTR_DELETE (unit_decls);
6535 /* The functions creates automaton insns for each automata. Automaton
6536 insn is simply insn for given automaton which makes reservation
6537 only of units of the automaton. */
6538 static ainsn_t
6539 create_ainsns ()
6541 decl_t decl;
6542 ainsn_t first_ainsn;
6543 ainsn_t curr_ainsn;
6544 ainsn_t prev_ainsn;
6545 int i;
6547 first_ainsn = NULL;
6548 prev_ainsn = NULL;
6549 for (i = 0; i < description->decls_num; i++)
6551 decl = description->decls [i];
6552 if (decl->mode == dm_insn_reserv)
6554 curr_ainsn = create_node (sizeof (struct ainsn));
6555 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6556 curr_ainsn->important_p = FALSE;
6557 curr_ainsn->next_ainsn = NULL;
6558 if (prev_ainsn == NULL)
6559 first_ainsn = curr_ainsn;
6560 else
6561 prev_ainsn->next_ainsn = curr_ainsn;
6562 prev_ainsn = curr_ainsn;
6565 return first_ainsn;
6568 /* The function assigns automata to units according to constructions
6569 `define_automaton' in the description. */
6570 static void
6571 units_to_automata_distr ()
6573 decl_t decl;
6574 int i;
6576 for (i = 0; i < description->decls_num; i++)
6578 decl = description->decls [i];
6579 if (decl->mode == dm_unit)
6581 if (DECL_UNIT (decl)->automaton_decl == NULL
6582 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6583 == NULL))
6584 /* Distribute to the first automaton. */
6585 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6586 else
6587 DECL_UNIT (decl)->corresponding_automaton_num
6588 = (DECL_UNIT (decl)->automaton_decl
6589 ->corresponding_automaton->automaton_order_num);
6594 /* The function creates DFA(s) for fast pipeline hazards recognition
6595 after checking and simplifying IR of the description. */
6596 static void
6597 create_automata ()
6599 automaton_t curr_automaton;
6600 automaton_t prev_automaton;
6601 decl_t decl;
6602 int curr_automaton_num;
6603 int i;
6605 if (automata_num != 0)
6607 units_to_automata_heuristic_distr ();
6608 for (prev_automaton = NULL, curr_automaton_num = 0;
6609 curr_automaton_num < automata_num;
6610 curr_automaton_num++, prev_automaton = curr_automaton)
6612 curr_automaton = create_node (sizeof (struct automaton));
6613 curr_automaton->ainsn_list = create_ainsns ();
6614 curr_automaton->corresponding_automaton_decl = NULL;
6615 curr_automaton->next_automaton = NULL;
6616 curr_automaton->automaton_order_num = curr_automaton_num;
6617 if (prev_automaton == NULL)
6618 description->first_automaton = curr_automaton;
6619 else
6620 prev_automaton->next_automaton = curr_automaton;
6623 else
6625 curr_automaton_num = 0;
6626 prev_automaton = NULL;
6627 for (i = 0; i < description->decls_num; i++)
6629 decl = description->decls [i];
6630 if (decl->mode == dm_automaton
6631 && DECL_AUTOMATON (decl)->automaton_is_used)
6633 curr_automaton = create_node (sizeof (struct automaton));
6634 curr_automaton->ainsn_list = create_ainsns ();
6635 curr_automaton->corresponding_automaton_decl
6636 = DECL_AUTOMATON (decl);
6637 curr_automaton->next_automaton = NULL;
6638 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6639 curr_automaton->automaton_order_num = curr_automaton_num;
6640 if (prev_automaton == NULL)
6641 description->first_automaton = curr_automaton;
6642 else
6643 prev_automaton->next_automaton = curr_automaton;
6644 curr_automaton_num++;
6645 prev_automaton = curr_automaton;
6648 if (curr_automaton_num == 0)
6650 curr_automaton = create_node (sizeof (struct automaton));
6651 curr_automaton->ainsn_list = create_ainsns ();
6652 curr_automaton->corresponding_automaton_decl = NULL;
6653 curr_automaton->next_automaton = NULL;
6654 description->first_automaton = curr_automaton;
6656 units_to_automata_distr ();
6658 NDFA_time = create_ticker ();
6659 ticker_off (&NDFA_time);
6660 NDFA_to_DFA_time = create_ticker ();
6661 ticker_off (&NDFA_to_DFA_time);
6662 minimize_time = create_ticker ();
6663 ticker_off (&minimize_time);
6664 equiv_time = create_ticker ();
6665 ticker_off (&equiv_time);
6666 for (curr_automaton = description->first_automaton;
6667 curr_automaton != NULL;
6668 curr_automaton = curr_automaton->next_automaton)
6670 if (curr_automaton->corresponding_automaton_decl == NULL)
6671 fprintf (stderr, "Create anonymous automaton ...");
6672 else
6673 fprintf (stderr, "Create automaton `%s'...",
6674 curr_automaton->corresponding_automaton_decl->name);
6675 create_alt_states (curr_automaton);
6676 form_ainsn_with_same_reservs (curr_automaton);
6677 build_automaton (curr_automaton);
6678 enumerate_states (curr_automaton);
6679 ticker_on (&equiv_time);
6680 set_insn_equiv_classes (curr_automaton);
6681 ticker_off (&equiv_time);
6682 fprintf (stderr, "done\n");
6688 /* This page contains code for forming string representation of
6689 regexp. The representation is formed on IR obstack. So you should
6690 not work with IR obstack between regexp_representation and
6691 finish_regexp_representation calls. */
6693 /* This recursive function forms string representation of regexp
6694 (without tailing '\0'). */
6695 static void
6696 form_regexp (regexp)
6697 regexp_t regexp;
6699 int i;
6701 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6703 const char *name = (regexp->mode == rm_unit
6704 ? REGEXP_UNIT (regexp)->name
6705 : REGEXP_RESERV (regexp)->name);
6707 obstack_grow (&irp, name, strlen (name));
6709 else if (regexp->mode == rm_sequence)
6710 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6712 if (i != 0)
6713 obstack_1grow (&irp, ',');
6714 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6716 else if (regexp->mode == rm_allof)
6718 obstack_1grow (&irp, '(');
6719 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6721 if (i != 0)
6722 obstack_1grow (&irp, '+');
6723 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6724 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6725 obstack_1grow (&irp, '(');
6726 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6727 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6728 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6729 obstack_1grow (&irp, ')');
6731 obstack_1grow (&irp, ')');
6733 else if (regexp->mode == rm_oneof)
6734 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6736 if (i != 0)
6737 obstack_1grow (&irp, '|');
6738 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6739 obstack_1grow (&irp, '(');
6740 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6741 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6742 obstack_1grow (&irp, ')');
6744 else if (regexp->mode == rm_repeat)
6746 char digits [30];
6748 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6749 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6750 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6751 obstack_1grow (&irp, '(');
6752 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6753 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6754 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6755 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6756 obstack_1grow (&irp, ')');
6757 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6758 obstack_grow (&irp, digits, strlen (digits));
6760 else if (regexp->mode == rm_nothing)
6761 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6762 else
6763 abort ();
6766 /* The function returns string representation of REGEXP on IR
6767 obstack. */
6768 static const char *
6769 regexp_representation (regexp)
6770 regexp_t regexp;
6772 form_regexp (regexp);
6773 obstack_1grow (&irp, '\0');
6774 return obstack_base (&irp);
6777 /* The function frees memory allocated for last formed string
6778 representation of regexp. */
6779 static void
6780 finish_regexp_representation ()
6782 int length = obstack_object_size (&irp);
6784 obstack_blank_fast (&irp, -length);
6789 /* This page contains code for output PHR (pipeline hazards recognizer). */
6791 /* The function outputs minimal C type which is sufficient for
6792 representation numbers in range min_range_value and
6793 max_range_value. Because host machine and build machine may be
6794 different, we use here minimal values required by ANSI C standard
6795 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6796 approximation. */
6798 static void
6799 output_range_type (f, min_range_value, max_range_value)
6800 FILE *f;
6801 long int min_range_value;
6802 long int max_range_value;
6804 if (min_range_value >= 0 && max_range_value <= 255)
6805 fprintf (f, "unsigned char");
6806 else if (min_range_value >= -127 && max_range_value <= 127)
6807 fprintf (f, "signed char");
6808 else if (min_range_value >= 0 && max_range_value <= 65535)
6809 fprintf (f, "unsigned short");
6810 else if (min_range_value >= -32767 && max_range_value <= 32767)
6811 fprintf (f, "short");
6812 else
6813 fprintf (f, "int");
6816 /* The following macro value is used as value of member
6817 `longest_path_length' of state when we are processing path and the
6818 state on the path. */
6820 #define ON_THE_PATH -2
6822 /* The following recursive function searches for the length of the
6823 longest path starting from STATE which does not contain cycles and
6824 `cycle advance' arcs. */
6826 static int
6827 longest_path_length (state)
6828 state_t state;
6830 arc_t arc;
6831 int length, result;
6833 if (state->longest_path_length == ON_THE_PATH)
6834 /* We don't expect the path cycle here. Our graph may contain
6835 only cycles with one state on the path not containing `cycle
6836 advance' arcs -- see comment below. */
6837 abort ();
6838 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6839 /* We alreday visited the state. */
6840 return state->longest_path_length;
6842 result = 0;
6843 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6844 /* Ignore cycles containing one state and `cycle advance' arcs. */
6845 if (arc->to_state != state
6846 && (arc->insn->insn_reserv_decl
6847 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6849 length = longest_path_length (arc->to_state);
6850 if (length > result)
6851 result = length;
6853 state->longest_path_length = result + 1;
6854 return result;
6857 /* The following variable value is value of the corresponding global
6858 variable in the automaton based pipeline interface. */
6860 static int max_dfa_issue_rate;
6862 /* The following function processes the longest path length staring
6863 from STATE to find MAX_DFA_ISSUE_RATE. */
6865 static void
6866 process_state_longest_path_length (state)
6867 state_t state;
6869 int value;
6871 value = longest_path_length (state);
6872 if (value > max_dfa_issue_rate)
6873 max_dfa_issue_rate = value;
6876 /* The following nacro value is name of the corresponding global
6877 variable in the automaton based pipeline interface. */
6879 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
6881 /* The following function calculates value of the the corresponding
6882 global variable and outputs its declaration. */
6884 static void
6885 output_dfa_max_issue_rate ()
6887 automaton_t automaton;
6889 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
6890 abort ();
6891 max_dfa_issue_rate = 0;
6892 for (automaton = description->first_automaton;
6893 automaton != NULL;
6894 automaton = automaton->next_automaton)
6895 pass_states (automaton, process_state_longest_path_length);
6896 fprintf (output_file, "\nint %s = %d;\n",
6897 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
6900 /* The function outputs all initialization values of VECT with length
6901 vect_length. */
6902 static void
6903 output_vect (vect, vect_length)
6904 vect_el_t *vect;
6905 int vect_length;
6907 int els_on_line;
6909 els_on_line = 1;
6910 if (vect_length == 0)
6911 fprintf (output_file,
6912 "0 /* This is dummy el because the vect is empty */");
6913 else
6917 fprintf (output_file, "%5ld", (long) *vect);
6918 vect_length--;
6919 if (els_on_line == 10)
6921 els_on_line = 0;
6922 fprintf (output_file, ",\n");
6924 else if (vect_length != 0)
6925 fprintf (output_file, ", ");
6926 els_on_line++;
6927 vect++;
6929 while (vect_length != 0);
6933 /* The following is name of the structure which represents DFA(s) for
6934 PHR. */
6935 #define CHIP_NAME "DFA_chip"
6937 /* The following is name of member which represents state of a DFA for
6938 PHR. */
6939 static void
6940 output_chip_member_name (f, automaton)
6941 FILE *f;
6942 automaton_t automaton;
6944 if (automaton->corresponding_automaton_decl == NULL)
6945 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6946 else
6947 fprintf (f, "%s_automaton_state",
6948 automaton->corresponding_automaton_decl->name);
6951 /* The following is name of temporary variable which stores state of a
6952 DFA for PHR. */
6953 static void
6954 output_temp_chip_member_name (f, automaton)
6955 FILE *f;
6956 automaton_t automaton;
6958 fprintf (f, "_");
6959 output_chip_member_name (f, automaton);
6962 /* This is name of macro value which is code of pseudo_insn
6963 representing advancing cpu cycle. Its value is used as internal
6964 code unknown insn. */
6965 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6967 /* Output name of translate vector for given automaton. */
6968 static void
6969 output_translate_vect_name (f, automaton)
6970 FILE *f;
6971 automaton_t automaton;
6973 if (automaton->corresponding_automaton_decl == NULL)
6974 fprintf (f, "translate_%d", automaton->automaton_order_num);
6975 else
6976 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6979 /* Output name for simple transition table representation. */
6980 static void
6981 output_trans_full_vect_name (f, automaton)
6982 FILE *f;
6983 automaton_t automaton;
6985 if (automaton->corresponding_automaton_decl == NULL)
6986 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6987 else
6988 fprintf (f, "%s_transitions",
6989 automaton->corresponding_automaton_decl->name);
6992 /* Output name of comb vector of the transition table for given
6993 automaton. */
6994 static void
6995 output_trans_comb_vect_name (f, automaton)
6996 FILE *f;
6997 automaton_t automaton;
6999 if (automaton->corresponding_automaton_decl == NULL)
7000 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7001 else
7002 fprintf (f, "%s_transitions",
7003 automaton->corresponding_automaton_decl->name);
7006 /* Output name of check vector of the transition table for given
7007 automaton. */
7008 static void
7009 output_trans_check_vect_name (f, automaton)
7010 FILE *f;
7011 automaton_t automaton;
7013 if (automaton->corresponding_automaton_decl == NULL)
7014 fprintf (f, "check_%d", automaton->automaton_order_num);
7015 else
7016 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7019 /* Output name of base vector of the transition table for given
7020 automaton. */
7021 static void
7022 output_trans_base_vect_name (f, automaton)
7023 FILE *f;
7024 automaton_t automaton;
7026 if (automaton->corresponding_automaton_decl == NULL)
7027 fprintf (f, "base_%d", automaton->automaton_order_num);
7028 else
7029 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7032 /* Output name for simple alternatives number representation. */
7033 static void
7034 output_state_alts_full_vect_name (f, automaton)
7035 FILE *f;
7036 automaton_t automaton;
7038 if (automaton->corresponding_automaton_decl == NULL)
7039 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7040 else
7041 fprintf (f, "%s_state_alts",
7042 automaton->corresponding_automaton_decl->name);
7045 /* Output name of comb vector of the alternatives number table for given
7046 automaton. */
7047 static void
7048 output_state_alts_comb_vect_name (f, automaton)
7049 FILE *f;
7050 automaton_t automaton;
7052 if (automaton->corresponding_automaton_decl == NULL)
7053 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7054 else
7055 fprintf (f, "%s_state_alts",
7056 automaton->corresponding_automaton_decl->name);
7059 /* Output name of check vector of the alternatives number table for given
7060 automaton. */
7061 static void
7062 output_state_alts_check_vect_name (f, automaton)
7063 FILE *f;
7064 automaton_t automaton;
7066 if (automaton->corresponding_automaton_decl == NULL)
7067 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7068 else
7069 fprintf (f, "%s_check_state_alts",
7070 automaton->corresponding_automaton_decl->name);
7073 /* Output name of base vector of the alternatives number table for given
7074 automaton. */
7075 static void
7076 output_state_alts_base_vect_name (f, automaton)
7077 FILE *f;
7078 automaton_t automaton;
7080 if (automaton->corresponding_automaton_decl == NULL)
7081 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7082 else
7083 fprintf (f, "%s_base_state_alts",
7084 automaton->corresponding_automaton_decl->name);
7087 /* Output name of simple min issue delay table representation. */
7088 static void
7089 output_min_issue_delay_vect_name (f, automaton)
7090 FILE *f;
7091 automaton_t automaton;
7093 if (automaton->corresponding_automaton_decl == NULL)
7094 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7095 else
7096 fprintf (f, "%s_min_issue_delay",
7097 automaton->corresponding_automaton_decl->name);
7100 /* Output name of deadlock vector for given automaton. */
7101 static void
7102 output_dead_lock_vect_name (f, automaton)
7103 FILE *f;
7104 automaton_t automaton;
7106 if (automaton->corresponding_automaton_decl == NULL)
7107 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7108 else
7109 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7112 /* Output name of reserved units table for AUTOMATON into file F. */
7113 static void
7114 output_reserved_units_table_name (f, automaton)
7115 FILE *f;
7116 automaton_t automaton;
7118 if (automaton->corresponding_automaton_decl == NULL)
7119 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7120 else
7121 fprintf (f, "%s_reserved_units",
7122 automaton->corresponding_automaton_decl->name);
7125 /* Name of the PHR interface macro. */
7126 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7128 /* Name of the PHR interface macro. */
7129 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7131 /* Names of an internal functions: */
7132 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7134 /* This is external type of DFA(s) state. */
7135 #define STATE_TYPE_NAME "state_t"
7137 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7139 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7141 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7143 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7145 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7147 /* Name of cache of insn dfa codes. */
7148 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7150 /* Name of length of cache of insn dfa codes. */
7151 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7153 /* Names of the PHR interface functions: */
7154 #define SIZE_FUNC_NAME "state_size"
7156 #define TRANSITION_FUNC_NAME "state_transition"
7158 #define STATE_ALTS_FUNC_NAME "state_alts"
7160 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7162 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7164 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7166 #define RESET_FUNC_NAME "state_reset"
7168 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7170 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7172 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7174 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7176 #define DFA_START_FUNC_NAME "dfa_start"
7178 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7180 /* Names of parameters of the PHR interface functions. */
7181 #define STATE_NAME "state"
7183 #define INSN_PARAMETER_NAME "insn"
7185 #define INSN2_PARAMETER_NAME "insn2"
7187 #define CHIP_PARAMETER_NAME "chip"
7189 #define FILE_PARAMETER_NAME "f"
7191 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7193 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7195 /* Names of the variables whose values are internal insn code of rtx
7196 insn. */
7197 #define INTERNAL_INSN_CODE_NAME "insn_code"
7199 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7201 /* Names of temporary variables in some functions. */
7202 #define TEMPORARY_VARIABLE_NAME "temp"
7204 #define I_VARIABLE_NAME "i"
7206 /* Name of result variable in some functions. */
7207 #define RESULT_VARIABLE_NAME "res"
7209 /* Name of function (attribute) to translate insn into number of insn
7210 alternatives reservation. */
7211 #define INSN_ALTS_FUNC_NAME "insn_alts"
7213 /* Name of function (attribute) to translate insn into internal insn
7214 code. */
7215 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7217 /* Name of function (attribute) to translate insn into internal insn
7218 code with caching. */
7219 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7221 /* Name of function (attribute) to translate insn into internal insn
7222 code. */
7223 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7225 /* Name of function (attribute) to translate insn into internal insn
7226 code. */
7227 #define BYPASS_P_FUNC_NAME "bypass_p"
7229 /* Output C type which is used for representation of codes of states
7230 of AUTOMATON. */
7231 static void
7232 output_state_member_type (f, automaton)
7233 FILE *f;
7234 automaton_t automaton;
7236 output_range_type (f, 0, automaton->achieved_states_num);
7239 /* Output definition of the structure representing current DFA(s)
7240 state(s). */
7241 static void
7242 output_chip_definitions ()
7244 automaton_t automaton;
7246 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7247 for (automaton = description->first_automaton;
7248 automaton != NULL;
7249 automaton = automaton->next_automaton)
7251 fprintf (output_file, " ");
7252 output_state_member_type (output_file, automaton);
7253 fprintf (output_file, " ");
7254 output_chip_member_name (output_file, automaton);
7255 fprintf (output_file, ";\n");
7257 fprintf (output_file, "};\n\n");
7258 #if 0
7259 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7260 #endif
7264 /* The function outputs translate vector of internal insn code into
7265 insn equivalence class number. The equivalence class number is
7266 used to access to table and vectors reprewsenting DFA(s). */
7267 static void
7268 output_translate_vect (automaton)
7269 automaton_t automaton;
7271 ainsn_t ainsn;
7272 int insn_value;
7273 vla_hwint_t translate_vect;
7275 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7276 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7277 for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
7278 /* Undefined value */
7279 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7280 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7281 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7282 = ainsn->insn_equiv_class_num;
7283 fprintf (output_file,
7284 "/* Vector translating external insn codes to internal ones.*/\n");
7285 fprintf (output_file, "static const ");
7286 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7287 fprintf (output_file, " ");
7288 output_translate_vect_name (output_file, automaton);
7289 fprintf (output_file, "[] = {\n");
7290 output_vect (VLA_HWINT_BEGIN (translate_vect),
7291 VLA_HWINT_LENGTH (translate_vect));
7292 fprintf (output_file, "};\n\n");
7293 VLA_HWINT_DELETE (translate_vect);
7296 /* The value in a table state x ainsn -> something which represents
7297 undefined value. */
7298 static int undefined_vect_el_value;
7300 /* The following function returns nonzero value if the best
7301 representation of the table is comb vector. */
7302 static int
7303 comb_vect_p (tab)
7304 state_ainsn_table_t tab;
7306 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7307 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7310 /* The following function creates new table for AUTOMATON. */
7311 static state_ainsn_table_t
7312 create_state_ainsn_table (automaton)
7313 automaton_t automaton;
7315 state_ainsn_table_t tab;
7316 int full_vect_length;
7317 int i;
7319 tab = create_node (sizeof (struct state_ainsn_table));
7320 tab->automaton = automaton;
7321 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7322 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7323 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7324 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7325 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7326 full_vect_length = (automaton->insn_equiv_classes_num
7327 * automaton->achieved_states_num);
7328 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7329 for (i = 0; i < full_vect_length; i++)
7330 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7331 tab->min_base_vect_el_value = 0;
7332 tab->max_base_vect_el_value = 0;
7333 tab->min_comb_vect_el_value = 0;
7334 tab->max_comb_vect_el_value = 0;
7335 return tab;
7338 /* The following function outputs the best C representation of the
7339 table TAB of given TABLE_NAME. */
7340 static void
7341 output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7342 output_comb_vect_name_func,
7343 output_check_vect_name_func,
7344 output_base_vect_name_func)
7345 state_ainsn_table_t tab;
7346 char *table_name;
7347 void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7348 void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7349 void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7350 void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7352 if (!comb_vect_p (tab))
7354 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7355 fprintf (output_file, "static const ");
7356 output_range_type (output_file, tab->min_comb_vect_el_value,
7357 tab->max_comb_vect_el_value);
7358 fprintf (output_file, " ");
7359 (*output_full_vect_name_func) (output_file, tab->automaton);
7360 fprintf (output_file, "[] = {\n");
7361 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7362 VLA_HWINT_LENGTH (tab->full_vect));
7363 fprintf (output_file, "};\n\n");
7365 else
7367 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7368 fprintf (output_file, "static const ");
7369 output_range_type (output_file, tab->min_comb_vect_el_value,
7370 tab->max_comb_vect_el_value);
7371 fprintf (output_file, " ");
7372 (*output_comb_vect_name_func) (output_file, tab->automaton);
7373 fprintf (output_file, "[] = {\n");
7374 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7375 VLA_HWINT_LENGTH (tab->comb_vect));
7376 fprintf (output_file, "};\n\n");
7377 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7378 fprintf (output_file, "static const ");
7379 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7380 fprintf (output_file, " ");
7381 (*output_check_vect_name_func) (output_file, tab->automaton);
7382 fprintf (output_file, "[] = {\n");
7383 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7384 VLA_HWINT_LENGTH (tab->check_vect));
7385 fprintf (output_file, "};\n\n");
7386 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7387 fprintf (output_file, "static const ");
7388 output_range_type (output_file, tab->min_base_vect_el_value,
7389 tab->max_base_vect_el_value);
7390 fprintf (output_file, " ");
7391 (*output_base_vect_name_func) (output_file, tab->automaton);
7392 fprintf (output_file, "[] = {\n");
7393 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7394 VLA_HWINT_LENGTH (tab->base_vect));
7395 fprintf (output_file, "};\n\n");
7399 /* The following function adds vector with length VECT_LENGTH and
7400 elements pointed by VECT to table TAB as its line with number
7401 VECT_NUM. */
7402 static void
7403 add_vect (tab, vect_num, vect, vect_length)
7404 state_ainsn_table_t tab;
7405 int vect_num;
7406 vect_el_t *vect;
7407 int vect_length;
7409 int real_vect_length;
7410 vect_el_t *comb_vect_start;
7411 vect_el_t *check_vect_start;
7412 int comb_vect_index;
7413 int comb_vect_els_num;
7414 int vect_index;
7415 int first_unempty_vect_index;
7416 int additional_els_num;
7417 int no_state_value;
7418 vect_el_t vect_el;
7419 int i;
7421 if (vect_length == 0)
7422 abort ();
7423 real_vect_length = tab->automaton->insn_equiv_classes_num;
7424 if (vect [vect_length - 1] == undefined_vect_el_value)
7425 abort ();
7426 /* Form full vector in the table: */
7427 for (i = 0; i < vect_length; i++)
7428 VLA_HWINT (tab->full_vect,
7429 i + tab->automaton->insn_equiv_classes_num * vect_num)
7430 = vect [i];
7431 /* Form comb vector in the table: */
7432 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7433 abort ();
7434 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7435 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7436 for (first_unempty_vect_index = 0;
7437 first_unempty_vect_index < vect_length;
7438 first_unempty_vect_index++)
7439 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7440 break;
7441 /* Search for the place in comb vect for the inserted vect. */
7442 for (comb_vect_index = 0;
7443 comb_vect_index < comb_vect_els_num;
7444 comb_vect_index++)
7446 for (vect_index = first_unempty_vect_index;
7447 vect_index < vect_length
7448 && vect_index + comb_vect_index < comb_vect_els_num;
7449 vect_index++)
7450 if (vect [vect_index] != undefined_vect_el_value
7451 && (comb_vect_start [vect_index + comb_vect_index]
7452 != undefined_vect_el_value))
7453 break;
7454 if (vect_index >= vect_length
7455 || vect_index + comb_vect_index >= comb_vect_els_num)
7456 break;
7458 /* Slot was found. */
7459 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7460 if (additional_els_num < 0)
7461 additional_els_num = 0;
7462 /* Expand comb and check vectors. */
7463 vect_el = undefined_vect_el_value;
7464 no_state_value = tab->automaton->achieved_states_num;
7465 while (additional_els_num > 0)
7467 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7468 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7469 additional_els_num--;
7471 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7472 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7473 if (VLA_HWINT_LENGTH (tab->comb_vect)
7474 < (size_t) (comb_vect_index + real_vect_length))
7475 abort ();
7476 /* Fill comb and check vectors. */
7477 for (vect_index = 0; vect_index < vect_length; vect_index++)
7478 if (vect [vect_index] != undefined_vect_el_value)
7480 if (comb_vect_start [comb_vect_index + vect_index]
7481 != undefined_vect_el_value)
7482 abort ();
7483 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7484 if (vect [vect_index] < 0)
7485 abort ();
7486 if (tab->max_comb_vect_el_value < vect [vect_index])
7487 tab->max_comb_vect_el_value = vect [vect_index];
7488 if (tab->min_comb_vect_el_value > vect [vect_index])
7489 tab->min_comb_vect_el_value = vect [vect_index];
7490 check_vect_start [comb_vect_index + vect_index] = vect_num;
7492 if (tab->max_base_vect_el_value < comb_vect_index)
7493 tab->max_base_vect_el_value = comb_vect_index;
7494 if (tab->min_base_vect_el_value > comb_vect_index)
7495 tab->min_base_vect_el_value = comb_vect_index;
7496 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7499 /* Return number of out arcs of STATE. */
7500 static int
7501 out_state_arcs_num (state)
7502 state_t state;
7504 int result;
7505 arc_t arc;
7507 result = 0;
7508 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7510 if (arc->insn == NULL)
7511 abort ();
7512 if (arc->insn->first_ainsn_with_given_equialence_num)
7513 result++;
7515 return result;
7518 /* Compare number of possible transitions from the states. */
7519 static int
7520 compare_transition_els_num (state_ptr_1, state_ptr_2)
7521 const void *state_ptr_1;
7522 const void *state_ptr_2;
7524 int transition_els_num_1;
7525 int transition_els_num_2;
7527 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7528 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7529 if (transition_els_num_1 < transition_els_num_2)
7530 return 1;
7531 else if (transition_els_num_1 == transition_els_num_2)
7532 return 0;
7533 else
7534 return -1;
7537 /* The function adds element EL_VALUE to vector VECT for a table state
7538 x AINSN. */
7539 static void
7540 add_vect_el (vect, ainsn, el_value)
7541 vla_hwint_t *vect;
7542 ainsn_t ainsn;
7543 int el_value;
7545 int equiv_class_num;
7546 int vect_index;
7548 if (ainsn == NULL)
7549 abort ();
7550 equiv_class_num = ainsn->insn_equiv_class_num;
7551 for (vect_index = VLA_HWINT_LENGTH (*vect);
7552 vect_index <= equiv_class_num;
7553 vect_index++)
7554 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7555 VLA_HWINT (*vect, equiv_class_num) = el_value;
7558 /* This is for forming vector of states of an automaton. */
7559 static vla_ptr_t output_states_vect;
7561 /* The function is called by function pass_states. The function adds
7562 STATE to `output_states_vect'. */
7563 static void
7564 add_states_vect_el (state)
7565 state_t state;
7567 VLA_PTR_ADD (output_states_vect, state);
7570 /* Form and output vectors (comb, check, base or full vector)
7571 representing transition table of AUTOMATON. */
7572 static void
7573 output_trans_table (automaton)
7574 automaton_t automaton;
7576 state_t *state_ptr;
7577 arc_t arc;
7578 vla_hwint_t transition_vect;
7580 undefined_vect_el_value = automaton->achieved_states_num;
7581 automaton->trans_table = create_state_ainsn_table (automaton);
7582 /* Create vect of pointers to states ordered by num of transitions
7583 from the state (state with the maximum num is the first). */
7584 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7585 pass_states (automaton, add_states_vect_el);
7586 qsort (VLA_PTR_BEGIN (output_states_vect),
7587 VLA_PTR_LENGTH (output_states_vect),
7588 sizeof (state_t), compare_transition_els_num);
7589 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7590 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7591 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7592 state_ptr++)
7594 VLA_HWINT_NULLIFY (transition_vect);
7595 for (arc = first_out_arc (*state_ptr);
7596 arc != NULL;
7597 arc = next_out_arc (arc))
7599 if (arc->insn == NULL)
7600 abort ();
7601 if (arc->insn->first_ainsn_with_given_equialence_num)
7602 add_vect_el (&transition_vect, arc->insn,
7603 arc->to_state->order_state_num);
7605 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7606 VLA_HWINT_BEGIN (transition_vect),
7607 VLA_HWINT_LENGTH (transition_vect));
7609 output_state_ainsn_table
7610 (automaton->trans_table, (char *) "state transitions",
7611 output_trans_full_vect_name, output_trans_comb_vect_name,
7612 output_trans_check_vect_name, output_trans_base_vect_name);
7613 VLA_PTR_DELETE (output_states_vect);
7614 VLA_HWINT_DELETE (transition_vect);
7617 /* Form and output vectors (comb, check, base or simple vect)
7618 representing alts number table of AUTOMATON. The table is state x
7619 ainsn -> number of possible alternative reservations by the
7620 ainsn. */
7621 static void
7622 output_state_alts_table (automaton)
7623 automaton_t automaton;
7625 state_t *state_ptr;
7626 arc_t arc;
7627 vla_hwint_t state_alts_vect;
7629 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7630 automaton->state_alts_table = create_state_ainsn_table (automaton);
7631 /* Create vect of pointers to states ordered by num of transitions
7632 from the state (state with the maximum num is the first). */
7633 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7634 pass_states (automaton, add_states_vect_el);
7635 qsort (VLA_PTR_BEGIN (output_states_vect),
7636 VLA_PTR_LENGTH (output_states_vect),
7637 sizeof (state_t), compare_transition_els_num);
7638 /* Create base, comb, and check vectors. */
7639 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7640 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7641 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7642 state_ptr++)
7644 VLA_HWINT_NULLIFY (state_alts_vect);
7645 for (arc = first_out_arc (*state_ptr);
7646 arc != NULL;
7647 arc = next_out_arc (arc))
7649 if (arc->insn == NULL)
7650 abort ();
7651 if (arc->insn->first_ainsn_with_given_equialence_num)
7652 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7654 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7655 VLA_HWINT_BEGIN (state_alts_vect),
7656 VLA_HWINT_LENGTH (state_alts_vect));
7658 output_state_ainsn_table
7659 (automaton->state_alts_table, (char *) "state insn alternatives",
7660 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7661 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7662 VLA_PTR_DELETE (output_states_vect);
7663 VLA_HWINT_DELETE (state_alts_vect);
7666 /* The current number of passing states to find minimal issue delay
7667 value for an ainsn and state. */
7668 static int curr_state_pass_num;
7671 /* This recursive function passes states to find minimal issue delay
7672 value for AINSN. The state being visited is STATE. The function
7673 returns minimal issue delay value for AINSN in STATE or -1 if we
7674 enter into a loop. */
7675 static int
7676 min_issue_delay_pass_states (state, ainsn)
7677 state_t state;
7678 ainsn_t ainsn;
7680 arc_t arc;
7681 int min_insn_issue_delay, insn_issue_delay;
7683 if (state->state_pass_num == curr_state_pass_num
7684 || state->min_insn_issue_delay != -1)
7685 /* We've entered into a loop or already have the correct value for
7686 given state and ainsn. */
7687 return state->min_insn_issue_delay;
7688 state->state_pass_num = curr_state_pass_num;
7689 min_insn_issue_delay = -1;
7690 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7691 if (arc->insn == ainsn)
7693 min_insn_issue_delay = 0;
7694 break;
7696 else
7698 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7699 if (insn_issue_delay != -1)
7701 if (arc->insn->insn_reserv_decl
7702 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7703 insn_issue_delay++;
7704 if (min_insn_issue_delay == -1
7705 || min_insn_issue_delay > insn_issue_delay)
7707 min_insn_issue_delay = insn_issue_delay;
7708 if (insn_issue_delay == 0)
7709 break;
7713 return min_insn_issue_delay;
7716 /* The function searches minimal issue delay value for AINSN in STATE.
7717 The function can return negative value if we can not issue AINSN. We
7718 will report about it later. */
7719 static int
7720 min_issue_delay (state, ainsn)
7721 state_t state;
7722 ainsn_t ainsn;
7724 curr_state_pass_num++;
7725 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7726 return state->min_insn_issue_delay;
7729 /* The function initiates code for finding minimal issue delay values.
7730 It should be called only once. */
7731 static void
7732 initiate_min_issue_delay_pass_states ()
7734 curr_state_pass_num = 0;
7737 /* Form and output vectors representing minimal issue delay table of
7738 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7739 the ainsn. */
7740 static void
7741 output_min_issue_delay_table (automaton)
7742 automaton_t automaton;
7744 vla_hwint_t min_issue_delay_vect;
7745 vla_hwint_t compressed_min_issue_delay_vect;
7746 vect_el_t min_delay;
7747 ainsn_t ainsn;
7748 state_t *state_ptr;
7749 int i;
7751 /* Create vect of pointers to states ordered by num of transitions
7752 from the state (state with the maximum num is the first). */
7753 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7754 pass_states (automaton, add_states_vect_el);
7755 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7756 VLA_HWINT_EXPAND (min_issue_delay_vect,
7757 VLA_HWINT_LENGTH (output_states_vect)
7758 * automaton->insn_equiv_classes_num);
7759 for (i = 0;
7760 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7761 * automaton->insn_equiv_classes_num);
7762 i++)
7763 VLA_HWINT (min_issue_delay_vect, i) = 0;
7764 automaton->max_min_delay = 0;
7765 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7766 if (ainsn->first_ainsn_with_given_equialence_num)
7768 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7769 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7770 state_ptr++)
7771 (*state_ptr)->min_insn_issue_delay = -1;
7772 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7773 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7774 state_ptr++)
7776 min_delay = min_issue_delay (*state_ptr, ainsn);
7777 if (automaton->max_min_delay < min_delay)
7778 automaton->max_min_delay = min_delay;
7779 VLA_HWINT (min_issue_delay_vect,
7780 (*state_ptr)->order_state_num
7781 * automaton->insn_equiv_classes_num
7782 + ainsn->insn_equiv_class_num) = min_delay;
7785 fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
7786 fprintf (output_file, "static const ");
7787 output_range_type (output_file, 0, automaton->max_min_delay);
7788 fprintf (output_file, " ");
7789 output_min_issue_delay_vect_name (output_file, automaton);
7790 fprintf (output_file, "[] = {\n");
7791 /* Compress the vector */
7792 if (automaton->max_min_delay < 2)
7793 automaton->min_issue_delay_table_compression_factor = 8;
7794 else if (automaton->max_min_delay < 4)
7795 automaton->min_issue_delay_table_compression_factor = 4;
7796 else if (automaton->max_min_delay < 16)
7797 automaton->min_issue_delay_table_compression_factor = 2;
7798 else
7799 automaton->min_issue_delay_table_compression_factor = 1;
7800 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7801 "compressed min issue delay vector");
7802 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7803 (VLA_HWINT_LENGTH (min_issue_delay_vect)
7804 + automaton->min_issue_delay_table_compression_factor
7805 - 1)
7806 / automaton->min_issue_delay_table_compression_factor);
7807 for (i = 0;
7808 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7809 i++)
7810 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7811 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7812 VLA_HWINT (compressed_min_issue_delay_vect,
7813 i / automaton->min_issue_delay_table_compression_factor)
7814 |= (VLA_HWINT (min_issue_delay_vect, i)
7815 << (8 - (i % automaton->min_issue_delay_table_compression_factor
7816 + 1)
7817 * (8 / automaton->min_issue_delay_table_compression_factor)));
7818 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7819 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7820 fprintf (output_file, "};\n\n");
7821 VLA_PTR_DELETE (output_states_vect);
7822 VLA_HWINT_DELETE (min_issue_delay_vect);
7823 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7826 #ifndef NDEBUG
7827 /* Number of states which contains transition only by advancing cpu
7828 cycle. */
7829 static int locked_states_num;
7830 #endif
7832 /* Form and output vector representing the locked states of
7833 AUTOMATON. */
7834 static void
7835 output_dead_lock_vect (automaton)
7836 automaton_t automaton;
7838 state_t *state_ptr;
7839 arc_t arc;
7840 vla_hwint_t dead_lock_vect;
7842 /* Create vect of pointers to states ordered by num of
7843 transitions from the state (state with the maximum num is the
7844 first). */
7845 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7846 pass_states (automaton, add_states_vect_el);
7847 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7848 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7849 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7850 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7851 state_ptr++)
7853 arc = first_out_arc (*state_ptr);
7854 if (arc == NULL)
7855 abort ();
7856 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
7857 = (next_out_arc (arc) == NULL
7858 && (arc->insn->insn_reserv_decl
7859 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
7860 #ifndef NDEBUG
7861 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
7862 locked_states_num++;
7863 #endif
7865 fprintf (output_file, "/* Vector for locked state flags. */\n");
7866 fprintf (output_file, "static const ");
7867 output_range_type (output_file, 0, 1);
7868 fprintf (output_file, " ");
7869 output_dead_lock_vect_name (output_file, automaton);
7870 fprintf (output_file, "[] = {\n");
7871 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
7872 VLA_HWINT_LENGTH (dead_lock_vect));
7873 fprintf (output_file, "};\n\n");
7874 VLA_HWINT_DELETE (dead_lock_vect);
7875 VLA_PTR_DELETE (output_states_vect);
7878 /* Form and output vector representing reserved units of the states of
7879 AUTOMATON. */
7880 static void
7881 output_reserved_units_table (automaton)
7882 automaton_t automaton;
7884 state_t *curr_state_ptr;
7885 vla_hwint_t reserved_units_table;
7886 size_t state_byte_size;
7887 int i;
7889 /* Create vect of pointers to states. */
7890 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7891 pass_states (automaton, add_states_vect_el);
7892 /* Create vector. */
7893 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
7894 state_byte_size = (description->query_units_num + 7) / 8;
7895 VLA_HWINT_EXPAND (reserved_units_table,
7896 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7897 for (i = 0;
7898 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7899 i++)
7900 VLA_HWINT (reserved_units_table, i) = 0;
7901 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
7902 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7903 curr_state_ptr++)
7905 for (i = 0; i < description->units_num; i++)
7906 if (units_array [i]->query_p)
7908 if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i))
7909 VLA_HWINT (reserved_units_table,
7910 (*curr_state_ptr)->order_state_num * state_byte_size
7911 + units_array [i]->query_num / 8)
7912 += (1 << (units_array [i]->query_num % 8));
7915 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7916 fprintf (output_file, "static const ");
7917 output_range_type (output_file, 0, 255);
7918 fprintf (output_file, " ");
7919 output_reserved_units_table_name (output_file, automaton);
7920 fprintf (output_file, "[] = {\n");
7921 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
7922 VLA_HWINT_LENGTH (reserved_units_table));
7923 fprintf (output_file, "};\n\n");
7924 VLA_HWINT_DELETE (reserved_units_table);
7925 VLA_PTR_DELETE (output_states_vect);
7928 /* The function outputs all tables representing DFA(s) used for fast
7929 pipeline hazards recognition. */
7930 static void
7931 output_tables ()
7933 automaton_t automaton;
7935 #ifndef NDEBUG
7936 locked_states_num = 0;
7937 #endif
7938 initiate_min_issue_delay_pass_states ();
7939 for (automaton = description->first_automaton;
7940 automaton != NULL;
7941 automaton = automaton->next_automaton)
7943 output_translate_vect (automaton);
7944 output_trans_table (automaton);
7945 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
7946 output_state_alts_table (automaton);
7947 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7948 AUTOMATON_STATE_ALTS_MACRO_NAME);
7949 output_min_issue_delay_table (automaton);
7950 output_dead_lock_vect (automaton);
7951 if (no_minimization_flag)
7953 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
7954 output_reserved_units_table (automaton);
7955 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7956 CPU_UNITS_QUERY_MACRO_NAME);
7959 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7960 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7963 /* The function outputs definition and value of PHR interface variable
7964 `max_insn_queue_index' */
7965 static void
7966 output_max_insn_queue_index_def ()
7968 int i;
7970 for (i = 0; (1 << i) <= description->max_insn_reserv_cycles; i++)
7972 if (i < 0)
7973 abort ();
7974 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
7978 /* The function outputs switch cases for insn reseravtions using
7979 function *output_automata_list_code. */
7980 static void
7981 output_insn_code_cases (output_automata_list_code)
7982 void (*output_automata_list_code) (automata_list_el_t);
7984 decl_t decl, decl2;
7985 int i, j;
7987 for (i = 0; i < description->decls_num; i++)
7989 decl = description->decls [i];
7990 if (decl->mode == dm_insn_reserv)
7991 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7993 for (i = 0; i < description->decls_num; i++)
7995 decl = description->decls [i];
7996 if (decl->mode == dm_insn_reserv
7997 && !DECL_INSN_RESERV (decl)->processed_p)
7999 for (j = i; j < description->decls_num; j++)
8001 decl2 = description->decls [j];
8002 if (decl2->mode == dm_insn_reserv
8003 && (DECL_INSN_RESERV (decl2)->important_automata_list
8004 == DECL_INSN_RESERV (decl)->important_automata_list))
8006 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8007 fprintf (output_file, " case %d: /* %s */\n",
8008 DECL_INSN_RESERV (decl2)->insn_num,
8009 DECL_INSN_RESERV (decl2)->name);
8012 (*output_automata_list_code)
8013 (DECL_INSN_RESERV (decl)->important_automata_list);
8019 /* The function outputs a code for evaluation of a minimal delay of
8020 issue of insns which have reservations in given AUTOMATA_LIST. */
8021 static void
8022 output_automata_list_min_issue_delay_code (automata_list)
8023 automata_list_el_t automata_list;
8025 automata_list_el_t el;
8026 automaton_t automaton;
8028 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8030 automaton = el->automaton;
8031 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8032 output_min_issue_delay_vect_name (output_file, automaton);
8033 fprintf (output_file,
8034 (automaton->min_issue_delay_table_compression_factor != 1
8035 ? " [(" : " ["));
8036 output_translate_vect_name (output_file, automaton);
8037 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8038 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8039 output_chip_member_name (output_file, automaton);
8040 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8041 if (automaton->min_issue_delay_table_compression_factor == 1)
8042 fprintf (output_file, "];\n");
8043 else
8045 fprintf (output_file, ") / %d];\n",
8046 automaton->min_issue_delay_table_compression_factor);
8047 fprintf (output_file, " %s = (%s >> (8 - (",
8048 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8049 output_translate_vect_name (output_file, automaton);
8050 fprintf
8051 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8052 INTERNAL_INSN_CODE_NAME,
8053 automaton->min_issue_delay_table_compression_factor,
8054 8 / automaton->min_issue_delay_table_compression_factor,
8055 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8056 - 1);
8058 if (el == automata_list)
8059 fprintf (output_file, " %s = %s;\n",
8060 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8061 else
8063 fprintf (output_file, " if (%s > %s)\n",
8064 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8065 fprintf (output_file, " %s = %s;\n",
8066 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8069 fprintf (output_file, " break;\n\n");
8072 /* Output function `internal_min_issue_delay'. */
8073 static void
8074 output_internal_min_issue_delay_func ()
8076 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8077 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
8078 fprintf (output_file,
8079 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8080 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8081 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8082 CHIP_PARAMETER_NAME);
8083 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s;\n",
8084 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8085 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8086 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8087 fprintf (output_file,
8088 "\n default:\n %s = -1;\n break;\n }\n",
8089 RESULT_VARIABLE_NAME);
8090 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8091 fprintf (output_file, "}\n\n");
8094 /* The function outputs a code changing state after issue of insns
8095 which have reservations in given AUTOMATA_LIST. */
8096 static void
8097 output_automata_list_transition_code (automata_list)
8098 automata_list_el_t automata_list;
8100 automata_list_el_t el, next_el;
8102 fprintf (output_file, " {\n");
8103 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8104 for (el = automata_list;; el = next_el)
8106 next_el = el->next_automata_list_el;
8107 if (next_el == NULL)
8108 break;
8109 fprintf (output_file, " ");
8110 output_state_member_type (output_file, el->automaton);
8111 fprintf (output_file, " ");
8112 output_temp_chip_member_name (output_file, el->automaton);
8113 fprintf (output_file, ";\n");
8115 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8116 if (comb_vect_p (el->automaton->trans_table))
8118 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8119 output_trans_base_vect_name (output_file, el->automaton);
8120 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8121 output_chip_member_name (output_file, el->automaton);
8122 fprintf (output_file, "] + ");
8123 output_translate_vect_name (output_file, el->automaton);
8124 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8125 fprintf (output_file, " if (");
8126 output_trans_check_vect_name (output_file, el->automaton);
8127 fprintf (output_file, " [%s] != %s->",
8128 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8129 output_chip_member_name (output_file, el->automaton);
8130 fprintf (output_file, ")\n");
8131 fprintf (output_file, " return %s (%s, %s);\n",
8132 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8133 CHIP_PARAMETER_NAME);
8134 fprintf (output_file, " else\n");
8135 fprintf (output_file, " ");
8136 if (el->next_automata_list_el != NULL)
8137 output_temp_chip_member_name (output_file, el->automaton);
8138 else
8140 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8141 output_chip_member_name (output_file, el->automaton);
8143 fprintf (output_file, " = ");
8144 output_trans_comb_vect_name (output_file, el->automaton);
8145 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8147 else
8149 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8150 output_trans_full_vect_name (output_file, el->automaton);
8151 fprintf (output_file, " [");
8152 output_translate_vect_name (output_file, el->automaton);
8153 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8154 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8155 output_chip_member_name (output_file, el->automaton);
8156 fprintf (output_file, " * %d];\n",
8157 el->automaton->insn_equiv_classes_num);
8158 fprintf (output_file, " if (%s >= %d)\n",
8159 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8160 fprintf (output_file, " return %s (%s, %s);\n",
8161 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8162 CHIP_PARAMETER_NAME);
8163 fprintf (output_file, " else\n ");
8164 if (el->next_automata_list_el != NULL)
8165 output_temp_chip_member_name (output_file, el->automaton);
8166 else
8168 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8169 output_chip_member_name (output_file, el->automaton);
8171 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8173 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8174 for (el = automata_list;; el = next_el)
8176 next_el = el->next_automata_list_el;
8177 if (next_el == NULL)
8178 break;
8179 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8180 output_chip_member_name (output_file, el->automaton);
8181 fprintf (output_file, " = ");
8182 output_temp_chip_member_name (output_file, el->automaton);
8183 fprintf (output_file, ";\n");
8185 fprintf (output_file, " return -1;\n");
8186 fprintf (output_file, " }\n");
8189 /* Output function `internal_state_transition'. */
8190 static void
8191 output_internal_trans_func ()
8193 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8194 INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
8195 fprintf (output_file,
8196 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8197 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8198 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
8199 CHIP_NAME, CHIP_PARAMETER_NAME);
8200 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8201 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8202 output_insn_code_cases (output_automata_list_transition_code);
8203 fprintf (output_file, "\n default:\n return -1;\n }\n");
8204 fprintf (output_file, "}\n\n");
8207 /* Output code
8209 if (insn != 0)
8211 insn_code = dfa_insn_code (insn);
8212 if (insn_code > DFA__ADVANCE_CYCLE)
8213 return code;
8215 else
8216 insn_code = DFA__ADVANCE_CYCLE;
8218 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8219 code denotes CODE. */
8220 static void
8221 output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
8222 const char *insn_name;
8223 const char *insn_code_name;
8224 int code;
8226 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8227 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8228 DFA_INSN_CODE_FUNC_NAME, insn_name);
8229 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8230 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8231 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8232 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8236 /* The function outputs function `dfa_insn_code'. */
8237 static void
8238 output_dfa_insn_code_func ()
8240 fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n");
8241 fprintf (output_file, "static int %s PARAMS ((rtx));\n",
8242 DFA_INSN_CODE_FUNC_NAME);
8243 fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
8244 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
8245 fprintf (output_file, "{\n int %s;\n int %s;\n\n",
8246 INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
8247 fprintf (output_file, " if (INSN_UID (%s) >= %s)\n {\n",
8248 INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8249 fprintf (output_file, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
8250 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8251 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
8252 fprintf (output_file, " %s = xrealloc (%s, %s * sizeof (int));\n",
8253 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8254 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8255 fprintf (output_file,
8256 " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
8257 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8258 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8259 TEMPORARY_VARIABLE_NAME);
8260 fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
8261 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8262 INSN_PARAMETER_NAME);
8263 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8264 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8265 fprintf (output_file, " %s [INSN_UID (%s)] = %s;\n",
8266 DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME,
8267 INTERNAL_INSN_CODE_NAME);
8268 fprintf (output_file, " }\n return %s;\n}\n\n",
8269 INTERNAL_INSN_CODE_NAME);
8272 /* The function outputs PHR interface function `state_transition'. */
8273 static void
8274 output_trans_func ()
8276 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8277 TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8278 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8279 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8280 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8281 INTERNAL_INSN_CODE_NAME, -1);
8282 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8283 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8286 /* The function outputs a code for evaluation of alternative states
8287 number for insns which have reservations in given AUTOMATA_LIST. */
8288 static void
8289 output_automata_list_state_alts_code (automata_list)
8290 automata_list_el_t automata_list;
8292 automata_list_el_t el;
8293 automaton_t automaton;
8295 fprintf (output_file, " {\n");
8296 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8297 if (comb_vect_p (el->automaton->state_alts_table))
8299 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8300 break;
8302 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8304 automaton = el->automaton;
8305 if (comb_vect_p (automaton->state_alts_table))
8307 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8308 output_state_alts_base_vect_name (output_file, automaton);
8309 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8310 output_chip_member_name (output_file, automaton);
8311 fprintf (output_file, "] + ");
8312 output_translate_vect_name (output_file, automaton);
8313 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8314 fprintf (output_file, " if (");
8315 output_state_alts_check_vect_name (output_file, automaton);
8316 fprintf (output_file, " [%s] != %s->",
8317 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8318 output_chip_member_name (output_file, automaton);
8319 fprintf (output_file, ")\n");
8320 fprintf (output_file, " return 0;\n");
8321 fprintf (output_file, " else\n");
8322 fprintf (output_file,
8323 (el == automata_list
8324 ? " %s = " : " %s += "),
8325 RESULT_VARIABLE_NAME);
8326 output_state_alts_comb_vect_name (output_file, automaton);
8327 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8329 else
8331 fprintf (output_file,
8332 (el == automata_list
8333 ? "\n %s = " : " %s += "),
8334 RESULT_VARIABLE_NAME);
8335 output_state_alts_full_vect_name (output_file, automaton);
8336 fprintf (output_file, " [");
8337 output_translate_vect_name (output_file, automaton);
8338 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8339 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8340 output_chip_member_name (output_file, automaton);
8341 fprintf (output_file, " * %d];\n",
8342 automaton->insn_equiv_classes_num);
8345 fprintf (output_file, " break;\n }\n\n");
8348 /* Output function `internal_state_alts'. */
8349 static void
8350 output_internal_state_alts_func ()
8352 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8353 INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8354 fprintf (output_file,
8355 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8356 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8357 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8358 CHIP_PARAMETER_NAME);
8359 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8360 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8361 output_insn_code_cases (output_automata_list_state_alts_code);
8362 fprintf (output_file,
8363 "\n default:\n %s = 0;\n break;\n }\n",
8364 RESULT_VARIABLE_NAME);
8365 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8366 fprintf (output_file, "}\n\n");
8369 /* The function outputs PHR interface function `state_alts'. */
8370 static void
8371 output_state_alts_func ()
8373 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8374 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8375 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8376 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8377 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8378 INTERNAL_INSN_CODE_NAME, 0);
8379 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8380 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8383 /* Output function `min_issue_delay'. */
8384 static void
8385 output_min_issue_delay_func ()
8387 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8388 MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8389 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8390 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8391 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8392 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8393 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8394 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8395 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8396 fprintf (output_file, " }\n else\n %s = %s;\n",
8397 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8398 fprintf (output_file, "\n return %s (%s, %s);\n",
8399 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8400 STATE_NAME);
8401 fprintf (output_file, "}\n\n");
8404 /* Output function `internal_dead_lock'. */
8405 static void
8406 output_internal_dead_lock_func ()
8408 automaton_t automaton;
8410 fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8411 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8412 fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8413 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8414 CHIP_PARAMETER_NAME);
8415 fprintf (output_file, "{\n");
8416 for (automaton = description->first_automaton;
8417 automaton != NULL;
8418 automaton = automaton->next_automaton)
8420 fprintf (output_file, " if (");
8421 output_dead_lock_vect_name (output_file, automaton);
8422 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8423 output_chip_member_name (output_file, automaton);
8424 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8426 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8429 /* The function outputs PHR interface function `state_dead_lock_p'. */
8430 static void
8431 output_dead_lock_func ()
8433 fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8434 DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8435 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8436 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8439 /* Output function `internal_reset'. */
8440 static void
8441 output_internal_reset_func ()
8443 fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8444 INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8445 fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8446 INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8447 CHIP_NAME, CHIP_PARAMETER_NAME);
8448 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8449 CHIP_PARAMETER_NAME, CHIP_NAME);
8452 /* The function outputs PHR interface function `state_size'. */
8453 static void
8454 output_size_func ()
8456 fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8457 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8460 /* The function outputs PHR interface function `state_reset'. */
8461 static void
8462 output_reset_func ()
8464 fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8465 RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8466 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8467 STATE_NAME);
8470 /* Output function `min_insn_conflict_delay'. */
8471 static void
8472 output_min_insn_conflict_delay_func ()
8474 fprintf (output_file,
8475 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8476 MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8477 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8478 STATE_TYPE_NAME, STATE_NAME,
8479 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8480 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8481 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8482 INTERNAL_INSN2_CODE_NAME);
8483 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8484 INTERNAL_INSN_CODE_NAME, 0);
8485 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8486 INTERNAL_INSN2_CODE_NAME, 0);
8487 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8488 CHIP_NAME, STATE_NAME, CHIP_NAME);
8489 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8490 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8491 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8492 fprintf (output_file, " return %s (%s, &%s);\n",
8493 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8494 CHIP_NAME);
8495 fprintf (output_file, "}\n\n");
8498 /* Output function `internal_insn_latency'. */
8499 static void
8500 output_internal_insn_latency_func ()
8502 decl_t decl;
8503 struct bypass_decl *bypass;
8504 int i;
8506 fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8507 INTERNAL_INSN_LATENCY_FUNC_NAME);
8508 fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8509 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8510 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8511 INSN2_PARAMETER_NAME);
8512 fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
8513 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8514 fprintf (output_file,
8515 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
8516 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8517 fprintf (output_file, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8518 for (i = 0; i < description->decls_num; i++)
8520 decl = description->decls [i];
8521 if (decl->mode == dm_insn_reserv)
8523 fprintf (output_file, " case %d:\n",
8524 DECL_INSN_RESERV (decl)->insn_num);
8525 if (DECL_INSN_RESERV (decl)->bypass_list == NULL)
8526 fprintf (output_file, " return (%s != %s ? %d : 0);\n",
8527 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8528 DECL_INSN_RESERV (decl)->default_latency);
8529 else
8531 fprintf (output_file, " switch (%s)\n {\n",
8532 INTERNAL_INSN2_CODE_NAME);
8533 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8534 bypass != NULL;
8535 bypass = bypass->next)
8537 fprintf (output_file, " case %d:\n",
8538 bypass->in_insn_reserv->insn_num);
8539 if (bypass->bypass_guard_name == NULL)
8540 fprintf (output_file, " return %d;\n",
8541 bypass->latency);
8542 else
8543 fprintf (output_file,
8544 " return (%s (%s, %s) ? %d : %d);\n",
8545 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8546 INSN2_PARAMETER_NAME, bypass->latency,
8547 DECL_INSN_RESERV (decl)->default_latency);
8549 fprintf (output_file, " default:\n");
8550 fprintf (output_file,
8551 " return (%s != %s ? %d : 0);\n }\n",
8552 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8553 DECL_INSN_RESERV (decl)->default_latency);
8558 fprintf (output_file, " default:\n return 0;\n }\n}\n\n");
8561 /* The function outputs PHR interface function `insn_latency'. */
8562 static void
8563 output_insn_latency_func ()
8565 fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
8566 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8567 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8568 fprintf (output_file, "{\n int %s, %s;\n",
8569 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8570 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8571 INTERNAL_INSN_CODE_NAME, 0);
8572 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8573 INTERNAL_INSN2_CODE_NAME, 0);
8574 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8575 INTERNAL_INSN_LATENCY_FUNC_NAME,
8576 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8577 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8580 /* The function outputs PHR interface function `print_reservation'. */
8581 static void
8582 output_print_reservation_func ()
8584 decl_t decl;
8585 int i;
8587 fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
8588 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8589 INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
8590 INSN_PARAMETER_NAME);
8591 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8592 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8593 fprintf (output_file, " %s = %s (%s);\n",
8594 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8595 INSN_PARAMETER_NAME);
8596 fprintf (output_file, " if (%s > %s)\n",
8597 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8598 fprintf (output_file, " {\n fprintf (%s, \"%s\");\n",
8599 FILE_PARAMETER_NAME, NOTHING_NAME);
8600 fprintf (output_file, " return;\n }\n");
8601 fprintf (output_file, " }\n else\n");
8602 fprintf (output_file,
8603 " {\n fprintf (%s, \"%s\");\n return;\n }\n",
8604 FILE_PARAMETER_NAME, NOTHING_NAME);
8605 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8606 for (i = 0; i < description->decls_num; i++)
8608 decl = description->decls [i];
8609 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8611 fprintf (output_file,
8612 " case %d:\n", DECL_INSN_RESERV (decl)->insn_num);
8613 fprintf (output_file,
8614 " fprintf (%s, \"%s\");\n break;\n",
8615 FILE_PARAMETER_NAME,
8616 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8617 finish_regexp_representation ();
8620 fprintf (output_file, " default:\n fprintf (%s, \"%s\");\n }\n",
8621 FILE_PARAMETER_NAME, NOTHING_NAME);
8622 fprintf (output_file, "}\n\n");
8625 /* The following function is used to sort unit declaration by their
8626 names. */
8627 static int
8628 units_cmp (unit1, unit2)
8629 const void *unit1, *unit2;
8631 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8632 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8634 return strcmp (u1->name, u2->name);
8637 /* The following macro value is name of struct containing unit name
8638 and unit code. */
8639 #define NAME_CODE_STRUCT_NAME "name_code"
8641 /* The following macro value is name of table of struct name_code. */
8642 #define NAME_CODE_TABLE_NAME "name_code_table"
8644 /* The following macro values are member names for struct name_code. */
8645 #define NAME_MEMBER_NAME "name"
8646 #define CODE_MEMBER_NAME "code"
8648 /* The following macro values are local variable names for function
8649 `get_cpu_unit_code'. */
8650 #define CMP_VARIABLE_NAME "cmp"
8651 #define LOW_VARIABLE_NAME "l"
8652 #define MIDDLE_VARIABLE_NAME "m"
8653 #define HIGH_VARIABLE_NAME "h"
8655 /* The following function outputs function to obtain internal cpu unit
8656 code by the cpu unit name. */
8657 static void
8658 output_get_cpu_unit_code_func ()
8660 int i;
8661 unit_decl_t *units;
8663 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8664 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8665 CPU_UNIT_NAME_PARAMETER_NAME);
8666 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8667 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8668 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8669 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8670 fprintf (output_file, " static struct %s %s [] =\n {\n",
8671 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8672 units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
8673 * description->units_num);
8674 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8675 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8676 for (i = 0; i < description->units_num; i++)
8677 if (units [i]->query_p)
8678 fprintf (output_file, " {\"%s\", %d},\n",
8679 units[i]->name, units[i]->query_num);
8680 fprintf (output_file, " };\n\n");
8681 fprintf (output_file, " /* The following is binary search: */\n");
8682 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8683 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8684 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8685 fprintf (output_file, " while (%s <= %s)\n {\n",
8686 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8687 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8688 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8689 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8690 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8691 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8692 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8693 fprintf (output_file, " %s = %s - 1;\n",
8694 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8695 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8696 fprintf (output_file, " %s = %s + 1;\n",
8697 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8698 fprintf (output_file, " else\n");
8699 fprintf (output_file, " return %s [%s].%s;\n }\n",
8700 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8701 fprintf (output_file, " return -1;\n}\n\n");
8702 free (units);
8705 /* The following function outputs function to check reservation of cpu
8706 unit (its internal code will be passed as the function argument) in
8707 given cpu state. */
8708 static void
8709 output_cpu_unit_reservation_p ()
8711 automaton_t automaton;
8713 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8714 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8715 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8716 CPU_CODE_PARAMETER_NAME);
8717 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8718 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8719 description->query_units_num);
8720 for (automaton = description->first_automaton;
8721 automaton != NULL;
8722 automaton = automaton->next_automaton)
8724 fprintf (output_file, " if ((");
8725 output_reserved_units_table_name (output_file, automaton);
8726 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8727 output_chip_member_name (output_file, automaton);
8728 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8729 (description->query_units_num + 7) / 8,
8730 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8731 fprintf (output_file, " return 1;\n");
8733 fprintf (output_file, " return 0;\n}\n\n");
8736 /* The function outputs PHR interface function `dfa_start'. */
8737 static void
8738 output_dfa_start_func ()
8740 fprintf (output_file,
8741 "void\n%s ()\n{\n int %s;\n\n %s = get_max_uid ();\n",
8742 DFA_START_FUNC_NAME, I_VARIABLE_NAME,
8743 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8744 fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
8745 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8746 fprintf (output_file,
8747 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8748 I_VARIABLE_NAME, I_VARIABLE_NAME,
8749 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8750 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8753 /* The function outputs PHR interface function `dfa_finish'. */
8754 static void
8755 output_dfa_finish_func ()
8757 fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
8758 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8763 /* The page contains code for output description file (readable
8764 representation of original description and generated DFA(s). */
8766 /* The function outputs string representation of IR reservation. */
8767 static void
8768 output_regexp (regexp)
8769 regexp_t regexp;
8771 fprintf (output_description_file, "%s", regexp_representation (regexp));
8772 finish_regexp_representation ();
8775 /* Output names of units in LIST separated by comma. */
8776 static void
8777 output_unit_set_el_list (list)
8778 unit_set_el_t list;
8780 unit_set_el_t el;
8782 for (el = list; el != NULL; el = el->next_unit_set_el)
8784 if (el != list)
8785 fprintf (output_description_file, ",");
8786 fprintf (output_description_file, "%s", el->unit_decl->name);
8790 /* The function outputs string representation of IR define_reservation
8791 and define_insn_reservation. */
8792 static void
8793 output_description ()
8795 decl_t decl;
8796 int i;
8798 for (i = 0; i < description->decls_num; i++)
8800 decl = description->decls [i];
8801 if (decl->mode == dm_unit)
8803 if (DECL_UNIT (decl)->excl_list != NULL)
8805 fprintf (output_description_file, "unit %s exlusion_set: ",
8806 DECL_UNIT (decl)->name);
8807 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8808 fprintf (output_description_file, "\n");
8810 if (DECL_UNIT (decl)->presence_list != NULL)
8812 fprintf (output_description_file, "unit %s presence_set: ",
8813 DECL_UNIT (decl)->name);
8814 output_unit_set_el_list (DECL_UNIT (decl)->presence_list);
8815 fprintf (output_description_file, "\n");
8817 if (DECL_UNIT (decl)->absence_list != NULL)
8819 fprintf (output_description_file, "unit %s absence_set: ",
8820 DECL_UNIT (decl)->name);
8821 output_unit_set_el_list (DECL_UNIT (decl)->absence_list);
8822 fprintf (output_description_file, "\n");
8826 fprintf (output_description_file, "\n");
8827 for (i = 0; i < description->decls_num; i++)
8829 decl = description->decls [i];
8830 if (decl->mode == dm_reserv)
8832 fprintf (output_description_file, "reservation ");
8833 fprintf (output_description_file, DECL_RESERV (decl)->name);
8834 fprintf (output_description_file, ": ");
8835 output_regexp (DECL_RESERV (decl)->regexp);
8836 fprintf (output_description_file, "\n");
8838 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8840 fprintf (output_description_file, "insn reservation %s ",
8841 DECL_INSN_RESERV (decl)->name);
8842 print_rtl (output_description_file,
8843 DECL_INSN_RESERV (decl)->condexp);
8844 fprintf (output_description_file, ": ");
8845 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8846 fprintf (output_description_file, "\n");
8848 else if (decl->mode == dm_bypass)
8849 fprintf (output_description_file, "bypass %d %s %s\n",
8850 DECL_BYPASS (decl)->latency,
8851 DECL_BYPASS (decl)->out_insn_name,
8852 DECL_BYPASS (decl)->in_insn_name);
8854 fprintf (output_description_file, "\n\f\n");
8857 /* The function outputs name of AUTOMATON. */
8858 static void
8859 output_automaton_name (f, automaton)
8860 FILE *f;
8861 automaton_t automaton;
8863 if (automaton->corresponding_automaton_decl == NULL)
8864 fprintf (f, "#%d", automaton->automaton_order_num);
8865 else
8866 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8869 /* Maximal length of line for pretty printing into description
8870 file. */
8871 #define MAX_LINE_LENGTH 70
8873 /* The function outputs units name belonging to AUTOMATON. */
8874 static void
8875 output_automaton_units (automaton)
8876 automaton_t automaton;
8878 decl_t decl;
8879 char *name;
8880 int curr_line_length;
8881 int there_is_an_automaton_unit;
8882 int i;
8884 fprintf (output_description_file, "\n Coresponding units:\n");
8885 fprintf (output_description_file, " ");
8886 curr_line_length = 4;
8887 there_is_an_automaton_unit = 0;
8888 for (i = 0; i < description->decls_num; i++)
8890 decl = description->decls [i];
8891 if (decl->mode == dm_unit
8892 && (DECL_UNIT (decl)->corresponding_automaton_num
8893 == automaton->automaton_order_num))
8895 there_is_an_automaton_unit = 1;
8896 name = DECL_UNIT (decl)->name;
8897 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8899 curr_line_length = strlen (name) + 4;
8900 fprintf (output_description_file, "\n ");
8902 else
8904 curr_line_length += strlen (name) + 1;
8905 fprintf (output_description_file, " ");
8907 fprintf (output_description_file, name);
8910 if (!there_is_an_automaton_unit)
8911 fprintf (output_description_file, "<None>");
8912 fprintf (output_description_file, "\n\n");
8915 /* The following variable is used for forming array of all possible cpu unit
8916 reservations described by the current DFA state. */
8917 static vla_ptr_t state_reservs;
8919 /* The function forms `state_reservs' for STATE. */
8920 static void
8921 add_state_reservs (state)
8922 state_t state;
8924 alt_state_t curr_alt_state;
8925 reserv_sets_t reservs;
8927 if (state->component_states != NULL)
8928 for (curr_alt_state = state->component_states;
8929 curr_alt_state != NULL;
8930 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8931 add_state_reservs (curr_alt_state->state);
8932 else
8934 reservs = state->reservs;
8935 VLA_PTR_ADD (state_reservs, reservs);
8939 /* The function outputs readable represenatation of all out arcs of
8940 STATE. */
8941 static void
8942 output_state_arcs (state)
8943 state_t state;
8945 arc_t arc;
8946 ainsn_t ainsn;
8947 char *insn_name;
8948 int curr_line_length;
8950 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8952 ainsn = arc->insn;
8953 if (!ainsn->first_insn_with_same_reservs)
8954 abort ();
8955 fprintf (output_description_file, " ");
8956 curr_line_length = 7;
8957 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8960 insn_name = ainsn->insn_reserv_decl->name;
8961 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8963 if (ainsn != arc->insn)
8965 fprintf (output_description_file, ",\n ");
8966 curr_line_length = strlen (insn_name) + 6;
8968 else
8969 curr_line_length += strlen (insn_name);
8971 else
8973 curr_line_length += strlen (insn_name);
8974 if (ainsn != arc->insn)
8976 curr_line_length += 2;
8977 fprintf (output_description_file, ", ");
8980 fprintf (output_description_file, insn_name);
8981 ainsn = ainsn->next_same_reservs_insn;
8983 while (ainsn != NULL);
8984 fprintf (output_description_file, " %d (%d)\n",
8985 arc->to_state->order_state_num, arc->state_alts);
8987 fprintf (output_description_file, "\n");
8990 /* The following function is used for sorting possible cpu unit
8991 reservation of a DFA state. */
8992 static int
8993 state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
8994 const void *reservs_ptr_1;
8995 const void *reservs_ptr_2;
8997 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
8998 *(reserv_sets_t *) reservs_ptr_2);
9001 /* The following function is used for sorting possible cpu unit
9002 reservation of a DFA state. */
9003 static void
9004 remove_state_duplicate_reservs ()
9006 reserv_sets_t *reservs_ptr;
9007 reserv_sets_t *last_formed_reservs_ptr;
9009 last_formed_reservs_ptr = NULL;
9010 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9011 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9012 reservs_ptr++)
9013 if (last_formed_reservs_ptr == NULL)
9014 last_formed_reservs_ptr = reservs_ptr;
9015 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9017 ++last_formed_reservs_ptr;
9018 *last_formed_reservs_ptr = *reservs_ptr;
9020 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9023 /* The following function output readable representation of DFA(s)
9024 state used for fast recognition of pipeline hazards. State is
9025 described by possible (current and scehduled) cpu unit
9026 reservations. */
9027 static void
9028 output_state (state)
9029 state_t state;
9031 reserv_sets_t *reservs_ptr;
9033 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9034 fprintf (output_description_file, " State #%d", state->order_state_num);
9035 fprintf (output_description_file,
9036 state->new_cycle_p ? " (new cycle)\n" : "\n");
9037 add_state_reservs (state);
9038 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9039 sizeof (reserv_sets_t), state_reservs_cmp);
9040 remove_state_duplicate_reservs ();
9041 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9042 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9043 reservs_ptr++)
9045 fprintf (output_description_file, " ");
9046 output_reserv_sets (output_description_file, *reservs_ptr);
9047 fprintf (output_description_file, "\n");
9049 fprintf (output_description_file, "\n");
9050 output_state_arcs (state);
9051 VLA_PTR_DELETE (state_reservs);
9054 /* The following function output readable representation of
9055 DFAs used for fast recognition of pipeline hazards. */
9056 static void
9057 output_automaton_descriptions ()
9059 automaton_t automaton;
9061 for (automaton = description->first_automaton;
9062 automaton != NULL;
9063 automaton = automaton->next_automaton)
9065 fprintf (output_description_file, "\nAutomaton ");
9066 output_automaton_name (output_description_file, automaton);
9067 fprintf (output_description_file, "\n");
9068 output_automaton_units (automaton);
9069 pass_states (automaton, output_state);
9075 /* The page contains top level function for generation DFA(s) used for
9076 PHR. */
9078 /* The function outputs statistics about work of different phases of
9079 DFA generator. */
9080 static void
9081 output_statistics (f)
9082 FILE *f;
9084 automaton_t automaton;
9085 #ifndef NDEBUG
9086 int transition_comb_vect_els = 0;
9087 int transition_full_vect_els = 0;
9088 int state_alts_comb_vect_els = 0;
9089 int state_alts_full_vect_els = 0;
9090 int min_issue_delay_vect_els = 0;
9091 #endif
9093 for (automaton = description->first_automaton;
9094 automaton != NULL;
9095 automaton = automaton->next_automaton)
9097 fprintf (f, "\nAutomaton ");
9098 output_automaton_name (f, automaton);
9099 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9100 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9101 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9102 automaton->DFA_states_num, automaton->DFA_arcs_num);
9103 if (!no_minimization_flag)
9104 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9105 automaton->minimal_DFA_states_num,
9106 automaton->minimal_DFA_arcs_num);
9107 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9108 description->insns_num, automaton->insn_equiv_classes_num);
9109 #ifndef NDEBUG
9110 fprintf
9111 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9112 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9113 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9114 (comb_vect_p (automaton->trans_table)
9115 ? "use comb vect" : "use simple vect"));
9116 fprintf
9117 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9118 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9119 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9120 (comb_vect_p (automaton->state_alts_table)
9121 ? "use comb vect" : "use simple vect"));
9122 fprintf
9123 (f, "%5ld min delay table els, compression factor %d\n",
9124 (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num,
9125 automaton->min_issue_delay_table_compression_factor);
9126 transition_comb_vect_els
9127 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9128 transition_full_vect_els
9129 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9130 state_alts_comb_vect_els
9131 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9132 state_alts_full_vect_els
9133 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9134 min_issue_delay_vect_els
9135 += automaton->DFA_states_num * automaton->insn_equiv_classes_num;
9136 #endif
9138 #ifndef NDEBUG
9139 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9140 allocated_states_num, allocated_arcs_num);
9141 fprintf (f, "%5d all allocated alternative states\n",
9142 allocated_alt_states_num);
9143 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9144 transition_comb_vect_els, transition_full_vect_els);
9145 fprintf
9146 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9147 state_alts_comb_vect_els, state_alts_full_vect_els);
9148 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9149 fprintf (f, "%5d locked states num\n", locked_states_num);
9150 #endif
9153 /* The function output times of work of different phases of DFA
9154 generator. */
9155 static void
9156 output_time_statistics (f)
9157 FILE *f;
9159 fprintf (f, "\n transformation: ");
9160 print_active_time (f, transform_time);
9161 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9162 print_active_time (f, NDFA_time);
9163 if (ndfa_flag)
9165 fprintf (f, ", NDFA -> DFA: ");
9166 print_active_time (f, NDFA_to_DFA_time);
9168 fprintf (f, "\n DFA minimization: ");
9169 print_active_time (f, minimize_time);
9170 fprintf (f, ", making insn equivalence: ");
9171 print_active_time (f, equiv_time);
9172 fprintf (f, "\n all automaton generation: ");
9173 print_active_time (f, automaton_generation_time);
9174 fprintf (f, ", output: ");
9175 print_active_time (f, output_time);
9176 fprintf (f, "\n");
9179 /* The function generates DFA (deterministic finate state automaton)
9180 for fast recognition of pipeline hazards. No errors during
9181 checking must be fixed before this function call. */
9182 static void
9183 generate ()
9185 automata_num = split_argument;
9186 if (description->units_num < automata_num)
9187 automata_num = description->units_num;
9188 initiate_states ();
9189 initiate_arcs ();
9190 initiate_automata_lists ();
9191 initiate_pass_states ();
9192 initiate_excl_sets ();
9193 initiate_presence_absence_sets ();
9194 automaton_generation_time = create_ticker ();
9195 create_automata ();
9196 ticker_off (&automaton_generation_time);
9201 /* The following function creates insn attribute whose values are
9202 number alternatives in insn reservations. */
9203 static void
9204 make_insn_alts_attr ()
9206 int i, insn_num;
9207 decl_t decl;
9208 rtx condexp;
9210 condexp = rtx_alloc (COND);
9211 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9212 XEXP (condexp, 1) = make_numeric_value (0);
9213 for (i = insn_num = 0; i < description->decls_num; i++)
9215 decl = description->decls [i];
9216 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9218 XVECEXP (condexp, 0, 2 * insn_num)
9219 = DECL_INSN_RESERV (decl)->condexp;
9220 XVECEXP (condexp, 0, 2 * insn_num + 1)
9221 = make_numeric_value
9222 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9223 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9224 ->transformed_regexp)->regexps_num);
9225 insn_num++;
9228 if (description->insns_num != insn_num + 1)
9229 abort ();
9230 make_internal_attr (attr_printf (sizeof ("*")
9231 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9232 "*%s", INSN_ALTS_FUNC_NAME),
9233 condexp, 0);
9238 /* The following function creates attribute which is order number of
9239 insn in pipeline hazard description translator. */
9240 static void
9241 make_internal_dfa_insn_code_attr ()
9243 int i, insn_num;
9244 decl_t decl;
9245 rtx condexp;
9247 condexp = rtx_alloc (COND);
9248 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9249 XEXP (condexp, 1)
9250 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9251 ->insn_num + 1);
9252 for (i = insn_num = 0; i < description->decls_num; i++)
9254 decl = description->decls [i];
9255 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9257 XVECEXP (condexp, 0, 2 * insn_num)
9258 = DECL_INSN_RESERV (decl)->condexp;
9259 XVECEXP (condexp, 0, 2 * insn_num + 1)
9260 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9261 insn_num++;
9264 if (description->insns_num != insn_num + 1)
9265 abort ();
9266 make_internal_attr
9267 (attr_printf (sizeof ("*")
9268 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9269 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9270 condexp, 0);
9275 /* The following function creates attribute which order number of insn
9276 in pipeline hazard description translator. */
9277 static void
9278 make_default_insn_latency_attr ()
9280 int i, insn_num;
9281 decl_t decl;
9282 rtx condexp;
9284 condexp = rtx_alloc (COND);
9285 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9286 XEXP (condexp, 1) = make_numeric_value (0);
9287 for (i = insn_num = 0; i < description->decls_num; i++)
9289 decl = description->decls [i];
9290 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9292 XVECEXP (condexp, 0, 2 * insn_num)
9293 = DECL_INSN_RESERV (decl)->condexp;
9294 XVECEXP (condexp, 0, 2 * insn_num + 1)
9295 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9296 insn_num++;
9299 if (description->insns_num != insn_num + 1)
9300 abort ();
9301 make_internal_attr (attr_printf (sizeof ("*")
9302 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9303 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9304 condexp, 0);
9309 /* The following function creates attribute which returns 1 if given
9310 output insn has bypassing and 0 otherwise. */
9311 static void
9312 make_bypass_attr ()
9314 int i, bypass_insn;
9315 int bypass_insns_num = 0;
9316 decl_t decl;
9317 rtx result_rtx;
9319 for (i = 0; i < description->decls_num; i++)
9321 decl = description->decls [i];
9322 if (decl->mode == dm_insn_reserv
9323 && DECL_INSN_RESERV (decl)->condexp != NULL
9324 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9325 bypass_insns_num++;
9327 if (bypass_insns_num == 0)
9328 result_rtx = make_numeric_value (0);
9329 else
9331 result_rtx = rtx_alloc (COND);
9332 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9333 XEXP (result_rtx, 1) = make_numeric_value (0);
9335 for (i = bypass_insn = 0; i < description->decls_num; i++)
9337 decl = description->decls [i];
9338 if (decl->mode == dm_insn_reserv
9339 && DECL_INSN_RESERV (decl)->condexp != NULL
9340 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9342 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9343 = DECL_INSN_RESERV (decl)->condexp;
9344 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9345 = make_numeric_value (1);
9346 bypass_insn++;
9350 make_internal_attr (attr_printf (sizeof ("*")
9351 + strlen (BYPASS_P_FUNC_NAME) + 1,
9352 "*%s", BYPASS_P_FUNC_NAME),
9353 result_rtx, 0);
9358 /* This page mainly contains top level functions of pipeline hazards
9359 description translator. */
9361 /* The following macro value is suffix of name of description file of
9362 pipeline hazards description translator. */
9363 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9365 /* The function returns suffix of given file name. The returned
9366 string can not be changed. */
9367 static const char *
9368 file_name_suffix (file_name)
9369 const char *file_name;
9371 const char *last_period;
9373 for (last_period = NULL; *file_name != '\0'; file_name++)
9374 if (*file_name == '.')
9375 last_period = file_name;
9376 return (last_period == NULL ? file_name : last_period);
9379 /* The function returns base name of given file name, i.e. pointer to
9380 first char after last `/' (or `\' for WIN32) in given file name,
9381 given file name itself if the directory name is absent. The
9382 returned string can not be changed. */
9383 static const char *
9384 base_file_name (file_name)
9385 const char *file_name;
9387 int directory_name_length;
9389 directory_name_length = strlen (file_name);
9390 #ifdef WIN32
9391 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9392 && file_name[directory_name_length] != '\\')
9393 #else
9394 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9395 #endif
9396 directory_name_length--;
9397 return file_name + directory_name_length + 1;
9400 /* The following is top level function to initialize the work of
9401 pipeline hazards description translator. */
9402 void
9403 initiate_automaton_gen (argc, argv)
9404 int argc;
9405 char **argv;
9407 const char *base_name;
9408 int i;
9410 ndfa_flag = 0;
9411 split_argument = 0; /* default value */
9412 no_minimization_flag = 0;
9413 time_flag = 0;
9414 v_flag = 0;
9415 w_flag = 0;
9416 for (i = 2; i < argc; i++)
9417 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9418 no_minimization_flag = 1;
9419 else if (strcmp (argv [i], TIME_OPTION) == 0)
9420 time_flag = 1;
9421 else if (strcmp (argv [i], V_OPTION) == 0)
9422 v_flag = 1;
9423 else if (strcmp (argv [i], W_OPTION) == 0)
9424 w_flag = 1;
9425 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9426 ndfa_flag = 1;
9427 else if (strcmp (argv [i], "-split") == 0)
9429 if (i + 1 >= argc)
9430 fatal ("-split has no argument.");
9431 fatal ("option `-split' has not been implemented yet\n");
9432 /* split_argument = atoi (argument_vect [i + 1]); */
9434 VLA_PTR_CREATE (decls, 150, "decls");
9435 /* Initialize IR storage. */
9436 obstack_init (&irp);
9437 initiate_automaton_decl_table ();
9438 initiate_insn_decl_table ();
9439 initiate_decl_table ();
9440 output_file = stdout;
9441 output_description_file = NULL;
9442 base_name = base_file_name (argv[1]);
9443 obstack_grow (&irp, base_name,
9444 strlen (base_name) - strlen (file_name_suffix (base_name)));
9445 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9446 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9447 obstack_1grow (&irp, '\0');
9448 output_description_file_name = obstack_base (&irp);
9449 obstack_finish (&irp);
9452 /* The following function checks existence at least one arc marked by
9453 each insn. */
9454 static void
9455 check_automata_insn_issues ()
9457 automaton_t automaton;
9458 ainsn_t ainsn, reserv_ainsn;
9460 for (automaton = description->first_automaton;
9461 automaton != NULL;
9462 automaton = automaton->next_automaton)
9464 for (ainsn = automaton->ainsn_list;
9465 ainsn != NULL;
9466 ainsn = ainsn->next_ainsn)
9467 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9469 for (reserv_ainsn = ainsn;
9470 reserv_ainsn != NULL;
9471 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9472 if (automaton->corresponding_automaton_decl != NULL)
9474 if (!w_flag)
9475 error ("Automaton `%s': Insn `%s' will never be issued",
9476 automaton->corresponding_automaton_decl->name,
9477 reserv_ainsn->insn_reserv_decl->name);
9478 else
9479 warning
9480 ("Automaton `%s': Insn `%s' will never be issued",
9481 automaton->corresponding_automaton_decl->name,
9482 reserv_ainsn->insn_reserv_decl->name);
9484 else
9486 if (!w_flag)
9487 error ("Insn `%s' will never be issued",
9488 reserv_ainsn->insn_reserv_decl->name);
9489 else
9490 warning ("Insn `%s' will never be issued",
9491 reserv_ainsn->insn_reserv_decl->name);
9497 /* The following vla is used for storing pointers to all achieved
9498 states. */
9499 static vla_ptr_t automaton_states;
9501 /* This function is called by function pass_states to add an achieved
9502 STATE. */
9503 static void
9504 add_automaton_state (state)
9505 state_t state;
9507 VLA_PTR_ADD (automaton_states, state);
9510 /* The following function forms list of important automata (whose
9511 states may be changed after the insn issue) for each insn. */
9512 static void
9513 form_important_insn_automata_lists ()
9515 automaton_t automaton;
9516 state_t *state_ptr;
9517 decl_t decl;
9518 ainsn_t ainsn;
9519 arc_t arc;
9520 int i;
9522 VLA_PTR_CREATE (automaton_states, 1500,
9523 "automaton states for forming important insn automata sets");
9524 /* Mark important ainsns. */
9525 for (automaton = description->first_automaton;
9526 automaton != NULL;
9527 automaton = automaton->next_automaton)
9529 VLA_PTR_NULLIFY (automaton_states);
9530 pass_states (automaton, add_automaton_state);
9531 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9532 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9533 state_ptr++)
9535 for (arc = first_out_arc (*state_ptr);
9536 arc != NULL;
9537 arc = next_out_arc (arc))
9538 if (arc->to_state != *state_ptr)
9540 if (!arc->insn->first_insn_with_same_reservs)
9541 abort ();
9542 for (ainsn = arc->insn;
9543 ainsn != NULL;
9544 ainsn = ainsn->next_same_reservs_insn)
9545 ainsn->important_p = TRUE;
9549 VLA_PTR_DELETE (automaton_states);
9550 /* Create automata sets for the insns. */
9551 for (i = 0; i < description->decls_num; i++)
9553 decl = description->decls [i];
9554 if (decl->mode == dm_insn_reserv)
9556 automata_list_start ();
9557 for (automaton = description->first_automaton;
9558 automaton != NULL;
9559 automaton = automaton->next_automaton)
9560 for (ainsn = automaton->ainsn_list;
9561 ainsn != NULL;
9562 ainsn = ainsn->next_ainsn)
9563 if (ainsn->important_p
9564 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9566 automata_list_add (automaton);
9567 break;
9569 DECL_INSN_RESERV (decl)->important_automata_list
9570 = automata_list_finish ();
9576 /* The following is top level function to generate automat(a,on) for
9577 fast recognition of pipeline hazards. */
9578 void
9579 expand_automata ()
9581 int i;
9583 description = create_node (sizeof (struct description)
9584 /* One entry for cycle advancing insn. */
9585 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9586 description->decls_num = VLA_PTR_LENGTH (decls);
9587 description->query_units_num = 0;
9588 for (i = 0; i < description->decls_num; i++)
9590 description->decls [i] = VLA_PTR (decls, i);
9591 if (description->decls [i]->mode == dm_unit
9592 && DECL_UNIT (description->decls [i])->query_p)
9593 DECL_UNIT (description->decls [i])->query_num
9594 = description->query_units_num++;
9596 all_time = create_ticker ();
9597 check_time = create_ticker ();
9598 fprintf (stderr, "Check description...");
9599 fflush (stderr);
9600 check_all_description ();
9601 fprintf (stderr, "done\n");
9602 ticker_off (&check_time);
9603 generation_time = create_ticker ();
9604 if (!have_error)
9606 transform_insn_regexps ();
9607 check_unit_distributions_to_automata ();
9609 if (!have_error)
9611 generate ();
9612 check_automata_insn_issues ();
9614 if (!have_error)
9616 form_important_insn_automata_lists ();
9617 fprintf (stderr, "Generation of attributes...");
9618 fflush (stderr);
9619 make_internal_dfa_insn_code_attr ();
9620 make_insn_alts_attr ();
9621 make_default_insn_latency_attr ();
9622 make_bypass_attr ();
9623 fprintf (stderr, "done\n");
9625 ticker_off (&generation_time);
9626 ticker_off (&all_time);
9627 fprintf (stderr, "All other genattrtab stuff...");
9628 fflush (stderr);
9631 /* The following is top level function to output PHR and to finish
9632 work with pipeline description translator. */
9633 void
9634 write_automata ()
9636 fprintf (stderr, "done\n");
9637 if (have_error)
9638 fatal ("Errors in DFA description");
9639 ticker_on (&all_time);
9640 output_time = create_ticker ();
9641 fprintf (stderr, "Forming and outputing automata tables...");
9642 fflush (stderr);
9643 output_dfa_max_issue_rate ();
9644 output_tables ();
9645 fprintf (stderr, "done\n");
9646 fprintf (stderr, "Output functions to work with automata...");
9647 fflush (stderr);
9648 output_chip_definitions ();
9649 output_max_insn_queue_index_def ();
9650 output_internal_min_issue_delay_func ();
9651 output_internal_trans_func ();
9652 /* Cache of insn dfa codes: */
9653 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9654 fprintf (output_file, "\nstatic int %s;\n\n",
9655 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9656 output_dfa_insn_code_func ();
9657 output_trans_func ();
9658 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9659 output_internal_state_alts_func ();
9660 output_state_alts_func ();
9661 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9662 AUTOMATON_STATE_ALTS_MACRO_NAME);
9663 output_min_issue_delay_func ();
9664 output_internal_dead_lock_func ();
9665 output_dead_lock_func ();
9666 output_size_func ();
9667 output_internal_reset_func ();
9668 output_reset_func ();
9669 output_min_insn_conflict_delay_func ();
9670 output_internal_insn_latency_func ();
9671 output_insn_latency_func ();
9672 output_print_reservation_func ();
9673 if (no_minimization_flag)
9675 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9676 output_get_cpu_unit_code_func ();
9677 output_cpu_unit_reservation_p ();
9678 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9679 CPU_UNITS_QUERY_MACRO_NAME);
9681 output_dfa_start_func ();
9682 output_dfa_finish_func ();
9683 fprintf (stderr, "done\n");
9684 if (v_flag)
9686 output_description_file = fopen (output_description_file_name, "w");
9687 if (output_description_file == NULL)
9689 perror (output_description_file_name);
9690 exit (FATAL_EXIT_CODE);
9692 fprintf (stderr, "Output automata description...");
9693 fflush (stderr);
9694 output_description ();
9695 output_automaton_descriptions ();
9696 fprintf (stderr, "done\n");
9697 output_statistics (output_description_file);
9699 output_statistics (stderr);
9700 ticker_off (&output_time);
9701 output_time_statistics (stderr);
9702 finish_states ();
9703 finish_arcs ();
9704 finish_automata_lists ();
9705 if (time_flag)
9707 fprintf (stderr, "Summary:\n");
9708 fprintf (stderr, " check time ");
9709 print_active_time (stderr, check_time);
9710 fprintf (stderr, ", generation time ");
9711 print_active_time (stderr, generation_time);
9712 fprintf (stderr, ", all time ");
9713 print_active_time (stderr, all_time);
9714 fprintf (stderr, "\n");
9716 /* Finish all work. */
9717 if (output_description_file != NULL)
9719 fflush (output_description_file);
9720 if (ferror (stdout) != 0)
9721 fatal ("Error in writing DFA description file %s",
9722 output_description_file_name);
9723 fclose (output_description_file);
9725 finish_automaton_decl_table ();
9726 finish_insn_decl_table ();
9727 finish_decl_table ();
9728 obstack_free (&irp, NULL);
9729 if (have_error && output_description_file != NULL)
9730 remove (output_description_file_name);