* arm.md (stack_tie): New insn. Use an idiom that the alias code
[official-gcc.git] / gcc / genautomata.c
blob0fddf2706e1279967224080d7b3536c29202721f
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 ((const 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 *const 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 *const expand_vla_ptr = &(vla); \
561 const 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 *const 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 *const 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 *const expand_vla_ptr = &(vla); \
612 const 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 *const 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 *const _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 *const _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 *const _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 *const _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 *const _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 *const _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 *const _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 *const _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 *const _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 *const _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 *const _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 *const _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 *const _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 *const _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 const void *from;
1482 size_t size;
1484 void *const result = create_node (size);
1485 memcpy (result, from, size);
1486 return result;
1489 /* The function checks that NAME does not contain quotes (`"'). */
1490 static char *
1491 check_name (name, pos)
1492 char * name;
1493 pos_t pos ATTRIBUTE_UNUSED;
1495 const char *str;
1497 for (str = name; *str != '\0'; str++)
1498 if (*str == '\"')
1499 error ("Name `%s' contains quotes", name);
1500 return name;
1503 /* Pointers top all declartions during IR generation are stored in the
1504 following. */
1505 static vla_ptr_t decls;
1507 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1508 string containing the next separated element, taking parentheses
1509 into account if PAR_FLAG has nonzero value. Advance the pointer to
1510 after the string scanned, or the end-of-string. Return NULL if at
1511 end of string. */
1512 static char *
1513 next_sep_el (pstr, sep, par_flag)
1514 char **pstr;
1515 int sep;
1516 int par_flag;
1518 char *out_str;
1519 char *p;
1520 int pars_num;
1521 int n_spaces;
1523 /* Remove leading whitespaces. */
1524 while (ISSPACE ((int) **pstr))
1525 (*pstr)++;
1527 if (**pstr == '\0')
1528 return NULL;
1530 n_spaces = 0;
1531 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1533 if (par_flag && *p == '(')
1534 pars_num++;
1535 else if (par_flag && *p == ')')
1536 pars_num--;
1537 else if (pars_num == 0 && *p == sep)
1538 break;
1539 if (pars_num == 0 && ISSPACE ((int) *p))
1540 n_spaces++;
1541 else
1543 for (; n_spaces != 0; n_spaces--)
1544 obstack_1grow (&irp, p [-n_spaces]);
1545 obstack_1grow (&irp, *p);
1548 obstack_1grow (&irp, '\0');
1549 out_str = obstack_base (&irp);
1550 obstack_finish (&irp);
1552 *pstr = p;
1553 if (**pstr == sep)
1554 (*pstr)++;
1556 return out_str;
1559 /* Given a string and a separator, return the number of separated
1560 elements in it, taking parentheses into account if PAR_FLAG has
1561 nonzero value. Return 0 for the null string, -1 if parantheses is
1562 not balanced. */
1563 static int
1564 n_sep_els (s, sep, par_flag)
1565 char *s;
1566 int sep;
1567 int par_flag;
1569 int n;
1570 int pars_num;
1572 if (*s == '\0')
1573 return 0;
1575 for (pars_num = 0, n = 1; *s; s++)
1576 if (par_flag && *s == '(')
1577 pars_num++;
1578 else if (par_flag && *s == ')')
1579 pars_num--;
1580 else if (pars_num == 0 && *s == sep)
1581 n++;
1583 return (pars_num != 0 ? -1 : n);
1586 /* Given a string and a separator, return vector of strings which are
1587 elements in the string and number of elements through els_num.
1588 Take parentheses into account if PAR_FLAG has nonzero value.
1589 Return 0 for the null string, -1 if parantheses are not balanced. */
1590 static char **
1591 get_str_vect (str, els_num, sep, par_flag)
1592 char *str;
1593 int *els_num;
1594 int sep;
1595 int par_flag;
1597 int i;
1598 char **vect;
1599 char **pstr;
1601 *els_num = n_sep_els (str, sep, par_flag);
1602 if (*els_num <= 0)
1603 return NULL;
1604 obstack_blank (&irp, sizeof (char *) * (*els_num));
1605 vect = (char **) obstack_base (&irp);
1606 obstack_finish (&irp);
1607 pstr = &str;
1608 for (i = 0; i < *els_num; i++)
1609 vect [i] = next_sep_el (pstr, sep, par_flag);
1610 if (next_sep_el (pstr, sep, par_flag) != NULL)
1611 abort ();
1612 return vect;
1615 /* Process a DEFINE_CPU_UNIT.
1617 This gives information about a unit contained in CPU. We fill a
1618 struct unit_decl with information used later by `expand_automata'. */
1619 void
1620 gen_cpu_unit (def)
1621 rtx def;
1623 decl_t decl;
1624 char **str_cpu_units;
1625 int vect_length;
1626 int i;
1628 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1629 if (str_cpu_units == NULL)
1630 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1631 for (i = 0; i < vect_length; i++)
1633 decl = create_node (sizeof (struct decl));
1634 decl->mode = dm_unit;
1635 decl->pos = 0;
1636 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1637 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1638 DECL_UNIT (decl)->query_p = 0;
1639 VLA_PTR_ADD (decls, decl);
1640 num_dfa_decls++;
1644 /* Process a DEFINE_QUERY_CPU_UNIT.
1646 This gives information about a unit contained in CPU. We fill a
1647 struct unit_decl with information used later by `expand_automata'. */
1648 void
1649 gen_query_cpu_unit (def)
1650 rtx def;
1652 decl_t decl;
1653 char **str_cpu_units;
1654 int vect_length;
1655 int i;
1657 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1658 if (str_cpu_units == NULL)
1659 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1660 for (i = 0; i < vect_length; i++)
1662 decl = create_node (sizeof (struct decl));
1663 decl->mode = dm_unit;
1664 decl->pos = 0;
1665 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1666 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1667 DECL_UNIT (decl)->query_p = 1;
1668 VLA_PTR_ADD (decls, decl);
1669 num_dfa_decls++;
1673 /* Process a DEFINE_BYPASS.
1675 This gives information about a unit contained in the CPU. We fill
1676 in a struct bypass_decl with information used later by
1677 `expand_automata'. */
1678 void
1679 gen_bypass (def)
1680 rtx def;
1682 decl_t decl;
1683 char **out_insns;
1684 int out_length;
1685 char **in_insns;
1686 int in_length;
1687 int i, j;
1689 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', 0);
1690 if (out_insns == NULL)
1691 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1692 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', 0);
1693 if (in_insns == NULL)
1694 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1695 for (i = 0; i < out_length; i++)
1696 for (j = 0; j < in_length; j++)
1698 decl = create_node (sizeof (struct decl));
1699 decl->mode = dm_bypass;
1700 decl->pos = 0;
1701 DECL_BYPASS (decl)->latency = XINT (def, 0);
1702 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1703 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1704 DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
1705 VLA_PTR_ADD (decls, decl);
1706 num_dfa_decls++;
1710 /* Process an EXCLUSION_SET.
1712 This gives information about a cpu unit conflicts. We fill a
1713 struct unit_rel_decl (excl) with information used later by
1714 `expand_automata'. */
1715 void
1716 gen_excl_set (def)
1717 rtx def;
1719 decl_t decl;
1720 char **first_str_cpu_units;
1721 char **second_str_cpu_units;
1722 int first_vect_length;
1723 int length;
1724 int i;
1726 first_str_cpu_units
1727 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1728 if (first_str_cpu_units == NULL)
1729 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1730 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1732 if (second_str_cpu_units == NULL)
1733 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1734 length += first_vect_length;
1735 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1736 decl->mode = dm_excl;
1737 decl->pos = 0;
1738 DECL_EXCL (decl)->names_num = length;
1739 DECL_EXCL (decl)->first_list_length = first_vect_length;
1740 for (i = 0; i < length; i++)
1741 if (i < first_vect_length)
1742 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1743 else
1744 DECL_EXCL (decl)->names [i]
1745 = second_str_cpu_units [i - first_vect_length];
1746 VLA_PTR_ADD (decls, decl);
1747 num_dfa_decls++;
1750 /* Process a PRESENCE_SET.
1752 This gives information about a cpu unit reservation requirements.
1753 We fill a struct unit_rel_decl (presence) with information used
1754 later by `expand_automata'. */
1755 void
1756 gen_presence_set (def)
1757 rtx def;
1759 decl_t decl;
1760 char **first_str_cpu_units;
1761 char **second_str_cpu_units;
1762 int first_vect_length;
1763 int length;
1764 int i;
1766 first_str_cpu_units
1767 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1768 if (first_str_cpu_units == NULL)
1769 fatal ("invalid first string `%s' in presence_set", XSTR (def, 0));
1770 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1772 if (second_str_cpu_units == NULL)
1773 fatal ("invalid second string `%s' in presence_set", XSTR (def, 1));
1774 length += first_vect_length;
1775 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1776 decl->mode = dm_presence;
1777 decl->pos = 0;
1778 DECL_PRESENCE (decl)->names_num = length;
1779 DECL_PRESENCE (decl)->first_list_length = first_vect_length;
1780 for (i = 0; i < length; i++)
1781 if (i < first_vect_length)
1782 DECL_PRESENCE (decl)->names [i] = first_str_cpu_units [i];
1783 else
1784 DECL_PRESENCE (decl)->names [i]
1785 = second_str_cpu_units [i - first_vect_length];
1786 VLA_PTR_ADD (decls, decl);
1787 num_dfa_decls++;
1790 /* Process an ABSENCE_SET.
1792 This gives information about a cpu unit reservation requirements.
1793 We fill a struct unit_rel_decl (absence) with information used
1794 later by `expand_automata'. */
1795 void
1796 gen_absence_set (def)
1797 rtx def;
1799 decl_t decl;
1800 char **first_str_cpu_units;
1801 char **second_str_cpu_units;
1802 int first_vect_length;
1803 int length;
1804 int i;
1806 first_str_cpu_units
1807 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1808 if (first_str_cpu_units == NULL)
1809 fatal ("invalid first string `%s' in absence_set", XSTR (def, 0));
1810 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1812 if (second_str_cpu_units == NULL)
1813 fatal ("invalid second string `%s' in absence_set", XSTR (def, 1));
1814 length += first_vect_length;
1815 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1816 decl->mode = dm_absence;
1817 decl->pos = 0;
1818 DECL_ABSENCE (decl)->names_num = length;
1819 DECL_ABSENCE (decl)->first_list_length = first_vect_length;
1820 for (i = 0; i < length; i++)
1821 if (i < first_vect_length)
1822 DECL_ABSENCE (decl)->names [i] = first_str_cpu_units [i];
1823 else
1824 DECL_ABSENCE (decl)->names [i]
1825 = second_str_cpu_units [i - first_vect_length];
1826 VLA_PTR_ADD (decls, decl);
1827 num_dfa_decls++;
1830 /* Process a DEFINE_AUTOMATON.
1832 This gives information about a finite state automaton used for
1833 recognizing pipeline hazards. We fill a struct automaton_decl
1834 with information used later by `expand_automata'. */
1835 void
1836 gen_automaton (def)
1837 rtx def;
1839 decl_t decl;
1840 char **str_automata;
1841 int vect_length;
1842 int i;
1844 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1845 if (str_automata == NULL)
1846 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1847 for (i = 0; i < vect_length; i++)
1849 decl = create_node (sizeof (struct decl));
1850 decl->mode = dm_automaton;
1851 decl->pos = 0;
1852 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1853 VLA_PTR_ADD (decls, decl);
1854 num_dfa_decls++;
1858 /* Process an AUTOMATA_OPTION.
1860 This gives information how to generate finite state automaton used
1861 for recognizing pipeline hazards. */
1862 void
1863 gen_automata_option (def)
1864 rtx def;
1866 if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1867 no_minimization_flag = 1;
1868 else if (strcmp ((char *) XSTR (def, 0), TIME_OPTION + 1) == 0)
1869 time_flag = 1;
1870 else if (strcmp ((char *) XSTR (def, 0), V_OPTION + 1) == 0)
1871 v_flag = 1;
1872 else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
1873 w_flag = 1;
1874 else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
1875 ndfa_flag = 1;
1876 else
1877 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1880 /* Name in reservation to denote absence reservation. */
1881 #define NOTHING_NAME "nothing"
1883 /* The following string contains original reservation string being
1884 parsed. */
1885 static char *reserv_str;
1887 /* Parse an element in STR. */
1888 static regexp_t
1889 gen_regexp_el (str)
1890 char *str;
1892 regexp_t regexp;
1893 int len;
1895 if (*str == '(')
1897 len = strlen (str);
1898 if (str [len - 1] != ')')
1899 fatal ("garbage after ) in reservation `%s'", reserv_str);
1900 str [len - 1] = '\0';
1901 regexp = gen_regexp_sequence (str + 1);
1903 else if (strcmp (str, NOTHING_NAME) == 0)
1905 regexp = create_node (sizeof (struct decl));
1906 regexp->mode = rm_nothing;
1908 else
1910 regexp = create_node (sizeof (struct decl));
1911 regexp->mode = rm_unit;
1912 REGEXP_UNIT (regexp)->name = str;
1914 return regexp;
1917 /* Parse construction `repeat' in STR. */
1918 static regexp_t
1919 gen_regexp_repeat (str)
1920 char *str;
1922 regexp_t regexp;
1923 regexp_t repeat;
1924 char **repeat_vect;
1925 int els_num;
1926 int i;
1928 repeat_vect = get_str_vect (str, &els_num, '*', 1);
1929 if (repeat_vect == NULL)
1930 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1931 if (els_num > 1)
1933 regexp = gen_regexp_el (repeat_vect [0]);
1934 for (i = 1; i < els_num; i++)
1936 repeat = create_node (sizeof (struct regexp));
1937 repeat->mode = rm_repeat;
1938 REGEXP_REPEAT (repeat)->regexp = regexp;
1939 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1940 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1941 fatal ("repetition `%s' <= 1 in reservation `%s'",
1942 str, reserv_str);
1943 regexp = repeat;
1945 return regexp;
1947 else
1948 return gen_regexp_el (str);
1951 /* Parse reservation STR which possibly contains separator '+'. */
1952 static regexp_t
1953 gen_regexp_allof (str)
1954 char *str;
1956 regexp_t allof;
1957 char **allof_vect;
1958 int els_num;
1959 int i;
1961 allof_vect = get_str_vect (str, &els_num, '+', 1);
1962 if (allof_vect == NULL)
1963 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1964 if (els_num > 1)
1966 allof = create_node (sizeof (struct regexp)
1967 + sizeof (regexp_t) * (els_num - 1));
1968 allof->mode = rm_allof;
1969 REGEXP_ALLOF (allof)->regexps_num = els_num;
1970 for (i = 0; i < els_num; i++)
1971 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1972 return allof;
1974 else
1975 return gen_regexp_repeat (str);
1978 /* Parse reservation STR which possibly contains separator '|'. */
1979 static regexp_t
1980 gen_regexp_oneof (str)
1981 char *str;
1983 regexp_t oneof;
1984 char **oneof_vect;
1985 int els_num;
1986 int i;
1988 oneof_vect = get_str_vect (str, &els_num, '|', 1);
1989 if (oneof_vect == NULL)
1990 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1991 if (els_num > 1)
1993 oneof = create_node (sizeof (struct regexp)
1994 + sizeof (regexp_t) * (els_num - 1));
1995 oneof->mode = rm_oneof;
1996 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1997 for (i = 0; i < els_num; i++)
1998 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1999 return oneof;
2001 else
2002 return gen_regexp_allof (str);
2005 /* Parse reservation STR which possibly contains separator ','. */
2006 static regexp_t
2007 gen_regexp_sequence (str)
2008 char *str;
2010 regexp_t sequence;
2011 char **sequence_vect;
2012 int els_num;
2013 int i;
2015 sequence_vect = get_str_vect (str, &els_num, ',', 1);
2016 if (els_num > 1)
2018 sequence = create_node (sizeof (struct regexp)
2019 + sizeof (regexp_t) * (els_num - 1));
2020 sequence->mode = rm_sequence;
2021 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2022 for (i = 0; i < els_num; i++)
2023 REGEXP_SEQUENCE (sequence)->regexps [i]
2024 = gen_regexp_oneof (sequence_vect [i]);
2025 return sequence;
2027 else
2028 return gen_regexp_oneof (str);
2031 /* Parse construction reservation STR. */
2032 static regexp_t
2033 gen_regexp (str)
2034 char *str;
2036 reserv_str = str;
2037 return gen_regexp_sequence (str);;
2040 /* Process a DEFINE_RESERVATION.
2042 This gives information about a reservation of cpu units. We fill
2043 in a struct reserv_decl with information used later by
2044 `expand_automata'. */
2045 void
2046 gen_reserv (def)
2047 rtx def;
2049 decl_t decl;
2051 decl = create_node (sizeof (struct decl));
2052 decl->mode = dm_reserv;
2053 decl->pos = 0;
2054 DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2055 DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2056 VLA_PTR_ADD (decls, decl);
2057 num_dfa_decls++;
2060 /* Process a DEFINE_INSN_RESERVATION.
2062 This gives information about the reservation of cpu units by an
2063 insn. We fill a struct insn_reserv_decl with information used
2064 later by `expand_automata'. */
2065 void
2066 gen_insn_reserv (def)
2067 rtx def;
2069 decl_t decl;
2071 decl = create_node (sizeof (struct decl));
2072 decl->mode = dm_insn_reserv;
2073 decl->pos = 0;
2074 DECL_INSN_RESERV (decl)->name
2075 = check_name ((char *) XSTR (def, 0), decl->pos);
2076 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2077 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2078 DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2079 VLA_PTR_ADD (decls, decl);
2080 num_dfa_decls++;
2085 /* The function evaluates hash value (0..UINT_MAX) of string. */
2086 static unsigned
2087 string_hash (string)
2088 const char *string;
2090 unsigned result, i;
2092 for (result = i = 0;*string++ != '\0'; i++)
2093 result += ((unsigned char) *string << (i % CHAR_BIT));
2094 return result;
2099 /* This page contains abstract data `table of automaton declarations'.
2100 Elements of the table is nodes representing automaton declarations.
2101 Key of the table elements is name of given automaton. Rememeber
2102 that automaton names have own space. */
2104 /* The function evaluates hash value of an automaton declaration. The
2105 function is used by abstract data `hashtab'. The function returns
2106 hash value (0..UINT_MAX) of given automaton declaration. */
2107 static unsigned
2108 automaton_decl_hash (automaton_decl)
2109 const void *automaton_decl;
2111 const decl_t decl = (decl_t) automaton_decl;
2113 if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
2114 abort ();
2115 return string_hash (DECL_AUTOMATON (decl)->name);
2118 /* The function tests automaton declarations on equality of their
2119 keys. The function is used by abstract data `hashtab'. The
2120 function returns 1 if the declarations have the same key, 0
2121 otherwise. */
2122 static int
2123 automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
2124 const void* automaton_decl_1;
2125 const void* automaton_decl_2;
2127 const decl_t decl1 = (decl_t) automaton_decl_1;
2128 const decl_t decl2 = (decl_t) automaton_decl_2;
2130 if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
2131 || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
2132 abort ();
2133 return strcmp (DECL_AUTOMATON (decl1)->name,
2134 DECL_AUTOMATON (decl2)->name) == 0;
2137 /* The automaton declaration table itself is represented by the
2138 following variable. */
2139 static htab_t automaton_decl_table;
2141 /* The function inserts automaton declaration into the table. The
2142 function does nothing if an automaton declaration with the same key
2143 exists already in the table. The function returns automaton
2144 declaration node in the table with the same key as given automaton
2145 declaration node. */
2146 static decl_t
2147 insert_automaton_decl (automaton_decl)
2148 decl_t automaton_decl;
2150 void **entry_ptr;
2152 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
2153 if (*entry_ptr == NULL)
2154 *entry_ptr = (void *) automaton_decl;
2155 return (decl_t) *entry_ptr;
2158 /* The following variable value is node representing automaton
2159 declaration. The node used for searching automaton declaration
2160 with given name. */
2161 static struct decl work_automaton_decl;
2163 /* The function searches for automaton declaration in the table with
2164 the same key as node representing name of the automaton
2165 declaration. The function returns node found in the table, NULL if
2166 such node does not exist in the table. */
2167 static decl_t
2168 find_automaton_decl (name)
2169 char *name;
2171 void *entry;
2173 work_automaton_decl.mode = dm_automaton;
2174 DECL_AUTOMATON (&work_automaton_decl)->name = name;
2175 entry = htab_find (automaton_decl_table, &work_automaton_decl);
2176 return (decl_t) entry;
2179 /* The function creates empty automaton declaration table and node
2180 representing automaton declaration and used for searching automaton
2181 declaration with given name. The function must be called only once
2182 before any work with the automaton declaration table. */
2183 static void
2184 initiate_automaton_decl_table ()
2186 work_automaton_decl.mode = dm_automaton;
2187 automaton_decl_table = htab_create (10, automaton_decl_hash,
2188 automaton_decl_eq_p, (htab_del) 0);
2191 /* The function deletes the automaton declaration table. Only call of
2192 function `initiate_automaton_decl_table' is possible immediately
2193 after this function call. */
2194 static void
2195 finish_automaton_decl_table ()
2197 htab_delete (automaton_decl_table);
2202 /* This page contains abstract data `table of insn declarations'.
2203 Elements of the table is nodes representing insn declarations. Key
2204 of the table elements is name of given insn (in corresponding
2205 define_insn_reservation). Rememeber that insn names have own
2206 space. */
2208 /* The function evaluates hash value of an insn declaration. The
2209 function is used by abstract data `hashtab'. The function returns
2210 hash value (0..UINT_MAX) of given insn declaration. */
2211 static unsigned
2212 insn_decl_hash (insn_decl)
2213 const void *insn_decl;
2215 const decl_t decl = (decl_t) insn_decl;
2217 if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
2218 abort ();
2219 return string_hash (DECL_INSN_RESERV (decl)->name);
2222 /* The function tests insn declarations on equality of their keys.
2223 The function is used by abstract data `hashtab'. The function
2224 returns 1 if declarations have the same key, 0 otherwise. */
2225 static int
2226 insn_decl_eq_p (insn_decl_1, insn_decl_2)
2227 const void *insn_decl_1;
2228 const void *insn_decl_2;
2230 const decl_t decl1 = (decl_t) insn_decl_1;
2231 const decl_t decl2 = (decl_t) insn_decl_2;
2233 if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
2234 || decl2->mode != dm_insn_reserv
2235 || DECL_INSN_RESERV (decl2)->name == NULL)
2236 abort ();
2237 return strcmp (DECL_INSN_RESERV (decl1)->name,
2238 DECL_INSN_RESERV (decl2)->name) == 0;
2241 /* The insn declaration table itself is represented by the following
2242 variable. The table does not contain insn reservation
2243 declarations. */
2244 static htab_t insn_decl_table;
2246 /* The function inserts insn declaration into the table. The function
2247 does nothing if an insn declaration with the same key exists
2248 already in the table. The function returns insn declaration node
2249 in the table with the same key as given insn declaration node. */
2250 static decl_t
2251 insert_insn_decl (insn_decl)
2252 decl_t insn_decl;
2254 void **entry_ptr;
2256 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2257 if (*entry_ptr == NULL)
2258 *entry_ptr = (void *) insn_decl;
2259 return (decl_t) *entry_ptr;
2262 /* The following variable value is node representing insn reservation
2263 declaration. The node used for searching insn reservation
2264 declaration with given name. */
2265 static struct decl work_insn_decl;
2267 /* The function searches for insn reservation declaration in the table
2268 with the same key as node representing name of the insn reservation
2269 declaration. The function returns node found in the table, NULL if
2270 such node does not exist in the table. */
2271 static decl_t
2272 find_insn_decl (name)
2273 char *name;
2275 void *entry;
2277 work_insn_decl.mode = dm_insn_reserv;
2278 DECL_INSN_RESERV (&work_insn_decl)->name = name;
2279 entry = htab_find (insn_decl_table, &work_insn_decl);
2280 return (decl_t) entry;
2283 /* The function creates empty insn declaration table and node
2284 representing insn declaration and used for searching insn
2285 declaration with given name. The function must be called only once
2286 before any work with the insn declaration table. */
2287 static void
2288 initiate_insn_decl_table ()
2290 work_insn_decl.mode = dm_insn_reserv;
2291 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2292 (htab_del) 0);
2295 /* The function deletes the insn declaration table. Only call of
2296 function `initiate_insn_decl_table' is possible immediately after
2297 this function call. */
2298 static void
2299 finish_insn_decl_table ()
2301 htab_delete (insn_decl_table);
2306 /* This page contains abstract data `table of declarations'. Elements
2307 of the table is nodes representing declarations (of units and
2308 reservations). Key of the table elements is names of given
2309 declarations. */
2311 /* The function evaluates hash value of a declaration. The function
2312 is used by abstract data `hashtab'. The function returns hash
2313 value (0..UINT_MAX) of given declaration. */
2314 static unsigned
2315 decl_hash (decl)
2316 const void *decl;
2318 const decl_t d = (const decl_t) decl;
2320 if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
2321 && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
2322 abort ();
2323 return string_hash (d->mode == dm_unit
2324 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
2327 /* The function tests declarations on equality of their keys. The
2328 function is used by abstract data `hashtab'. The function
2329 returns 1 if the declarations have the same key, 0 otherwise. */
2330 static int
2331 decl_eq_p (decl_1, decl_2)
2332 const void *decl_1;
2333 const void *decl_2;
2335 const decl_t d1 = (const decl_t) decl_1;
2336 const decl_t d2 = (const decl_t) decl_2;
2338 if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
2339 && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
2340 || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
2341 && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
2342 abort ();
2343 return strcmp ((d1->mode == dm_unit
2344 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
2345 (d2->mode == dm_unit
2346 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2349 /* The declaration table itself is represented by the following
2350 variable. */
2351 static htab_t decl_table;
2353 /* The function inserts declaration into the table. The function does
2354 nothing if a declaration with the same key exists already in the
2355 table. The function returns declaration node in the table with the
2356 same key as given declaration node. */
2358 static decl_t
2359 insert_decl (decl)
2360 decl_t decl;
2362 void **entry_ptr;
2364 entry_ptr = htab_find_slot (decl_table, decl, 1);
2365 if (*entry_ptr == NULL)
2366 *entry_ptr = (void *) decl;
2367 return (decl_t) *entry_ptr;
2370 /* The following variable value is node representing declaration. The
2371 node used for searching declaration with given name. */
2372 static struct decl work_decl;
2374 /* The function searches for declaration in the table with the same
2375 key as node representing name of the declaration. The function
2376 returns node found in the table, NULL if such node does not exist
2377 in the table. */
2378 static decl_t
2379 find_decl (name)
2380 char *name;
2382 void *entry;
2384 work_decl.mode = dm_unit;
2385 DECL_UNIT (&work_decl)->name = name;
2386 entry = htab_find (decl_table, &work_decl);
2387 return (decl_t) entry;
2390 /* The function creates empty declaration table and node representing
2391 declaration and used for searching declaration with given name.
2392 The function must be called only once before any work with the
2393 declaration table. */
2394 static void
2395 initiate_decl_table ()
2397 work_decl.mode = dm_unit;
2398 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2401 /* The function deletes the declaration table. Only call of function
2402 `initiate_declaration_table' is possible immediately after this
2403 function call. */
2404 static void
2405 finish_decl_table ()
2407 htab_delete (decl_table);
2412 /* This page contains checker of pipeline hazard description. */
2414 /* Checking NAMES in an exclusion clause vector and returning formed
2415 unit_set_el_list. */
2416 static unit_set_el_t
2417 process_excls (names, num, excl_pos)
2418 char **names;
2419 int num;
2420 pos_t excl_pos ATTRIBUTE_UNUSED;
2422 unit_set_el_t el_list;
2423 unit_set_el_t last_el;
2424 unit_set_el_t new_el;
2425 decl_t decl_in_table;
2426 int i;
2428 el_list = NULL;
2429 last_el = NULL;
2430 for (i = 0; i < num; i++)
2432 decl_in_table = find_decl (names [i]);
2433 if (decl_in_table == NULL)
2434 error ("unit `%s' in exclusion is not declared", names [i]);
2435 else if (decl_in_table->mode != dm_unit)
2436 error ("`%s' in exclusion is not unit", names [i]);
2437 else
2439 new_el = create_node (sizeof (struct unit_set_el));
2440 new_el->unit_decl = DECL_UNIT (decl_in_table);
2441 new_el->next_unit_set_el = NULL;
2442 if (last_el == NULL)
2443 el_list = last_el = new_el;
2444 else
2446 last_el->next_unit_set_el = new_el;
2447 last_el = last_el->next_unit_set_el;
2451 return el_list;
2454 /* The function adds each element from SOURCE_LIST to the exclusion
2455 list of the each element from DEST_LIST. Checking situation "unit
2456 excludes itself". */
2457 static void
2458 add_excls (dest_list, source_list, excl_pos)
2459 unit_set_el_t dest_list;
2460 unit_set_el_t source_list;
2461 pos_t excl_pos ATTRIBUTE_UNUSED;
2463 unit_set_el_t dst;
2464 unit_set_el_t src;
2465 unit_set_el_t curr_el;
2466 unit_set_el_t prev_el;
2467 unit_set_el_t copy;
2469 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2470 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2472 if (dst->unit_decl == src->unit_decl)
2474 error ("unit `%s' excludes itself", src->unit_decl->name);
2475 continue;
2477 if (dst->unit_decl->automaton_name != NULL
2478 && src->unit_decl->automaton_name != NULL
2479 && strcmp (dst->unit_decl->automaton_name,
2480 src->unit_decl->automaton_name) != 0)
2482 error ("units `%s' and `%s' in exclusion set belong to different automata",
2483 src->unit_decl->name, dst->unit_decl->name);
2484 continue;
2486 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2487 curr_el != NULL;
2488 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2489 if (curr_el->unit_decl == src->unit_decl)
2490 break;
2491 if (curr_el == NULL)
2493 /* Element not found - insert. */
2494 copy = copy_node (src, sizeof (*src));
2495 copy->next_unit_set_el = NULL;
2496 if (prev_el == NULL)
2497 dst->unit_decl->excl_list = copy;
2498 else
2499 prev_el->next_unit_set_el = copy;
2504 /* Checking NAMES in an presence clause vector and returning formed
2505 unit_set_el_list. The function is called only after processing all
2506 exclusion sets. */
2507 static unit_set_el_t
2508 process_presence_absence (names, num, req_pos, presence_p)
2509 char **names;
2510 int num;
2511 pos_t req_pos ATTRIBUTE_UNUSED;
2512 int presence_p;
2514 unit_set_el_t el_list;
2515 unit_set_el_t last_el;
2516 unit_set_el_t new_el;
2517 decl_t decl_in_table;
2518 int i;
2520 el_list = NULL;
2521 last_el = NULL;
2522 for (i = 0; i < num; i++)
2524 decl_in_table = find_decl (names [i]);
2525 if (decl_in_table == NULL)
2526 error ((presence_p
2527 ? "unit `%s' in presence set is not declared"
2528 : "unit `%s' in absence set is not declared"), names [i]);
2529 else if (decl_in_table->mode != dm_unit)
2530 error ((presence_p
2531 ? "`%s' in presence set is not unit"
2532 : "`%s' in absence set is not unit"), names [i]);
2533 else
2535 new_el = create_node (sizeof (struct unit_set_el));
2536 new_el->unit_decl = DECL_UNIT (decl_in_table);
2537 new_el->next_unit_set_el = NULL;
2538 if (last_el == NULL)
2539 el_list = last_el = new_el;
2540 else
2542 last_el->next_unit_set_el = new_el;
2543 last_el = last_el->next_unit_set_el;
2547 return el_list;
2550 /* The function adds each element from SOURCE_LIST to presence (if
2551 PRESENCE_P) or absence list of the each element from DEST_LIST.
2552 Checking situations "unit requires own presence", "unit requires
2553 own absence", and "unit excludes and requires presence of ...".
2554 Remember that we process absence sets only after all presence
2555 sets. */
2556 static void
2557 add_presence_absence (dest_list, source_list, req_pos, presence_p)
2558 unit_set_el_t dest_list;
2559 unit_set_el_t source_list;
2560 pos_t req_pos ATTRIBUTE_UNUSED;
2561 int presence_p;
2563 unit_set_el_t dst;
2564 unit_set_el_t src;
2565 unit_set_el_t curr_el;
2566 unit_set_el_t prev_el;
2567 unit_set_el_t copy;
2569 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2570 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2572 if (dst->unit_decl == src->unit_decl)
2574 error ((presence_p
2575 ? "unit `%s' requires own presence"
2576 : "unit `%s' requires own absence"), src->unit_decl->name);
2577 continue;
2579 if (dst->unit_decl->automaton_name != NULL
2580 && src->unit_decl->automaton_name != NULL
2581 && strcmp (dst->unit_decl->automaton_name,
2582 src->unit_decl->automaton_name) != 0)
2584 error ((presence_p
2585 ? "units `%s' and `%s' in presence set belong to different automata"
2586 : "units `%s' and `%s' in absence set belong to different automata"),
2587 src->unit_decl->name, dst->unit_decl->name);
2588 continue;
2590 for (curr_el = (presence_p
2591 ? dst->unit_decl->presence_list
2592 : dst->unit_decl->absence_list), prev_el = NULL;
2593 curr_el != NULL;
2594 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2595 if (curr_el->unit_decl == src->unit_decl)
2596 break;
2597 if (curr_el == NULL)
2599 /* Element not found - insert if there is no error. */
2600 int no_error_flag = 1;
2602 if (presence_p)
2603 for (curr_el = dst->unit_decl->excl_list;
2604 curr_el != NULL;
2605 curr_el = curr_el->next_unit_set_el)
2607 if (src->unit_decl == curr_el->unit_decl)
2609 if (!w_flag)
2611 error
2612 ("unit `%s' excludes and requires presence of `%s'",
2613 dst->unit_decl->name, src->unit_decl->name);
2614 no_error_flag = 0;
2616 else
2617 warning
2618 ("unit `%s' excludes and requires presence of `%s'",
2619 dst->unit_decl->name, src->unit_decl->name);
2622 else
2623 for (curr_el = dst->unit_decl->presence_list;
2624 curr_el != NULL;
2625 curr_el = curr_el->next_unit_set_el)
2627 if (src->unit_decl == curr_el->unit_decl)
2629 if (!w_flag)
2631 error
2632 ("unit `%s' requires absence and presence of `%s'",
2633 dst->unit_decl->name, src->unit_decl->name);
2634 no_error_flag = 0;
2636 else
2637 warning
2638 ("unit `%s' requires absence and presence of `%s'",
2639 dst->unit_decl->name, src->unit_decl->name);
2642 if (no_error_flag)
2644 copy = copy_node (src, sizeof (*src));
2645 copy->next_unit_set_el = NULL;
2646 if (prev_el == NULL)
2648 if (presence_p)
2649 dst->unit_decl->presence_list = copy;
2650 else
2651 dst->unit_decl->absence_list = copy;
2653 else
2654 prev_el->next_unit_set_el = copy;
2660 /* The function searches for bypass with given IN_INSN_RESERV in given
2661 BYPASS_LIST. */
2662 static struct bypass_decl *
2663 find_bypass (bypass_list, in_insn_reserv)
2664 struct bypass_decl *bypass_list;
2665 struct insn_reserv_decl *in_insn_reserv;
2667 struct bypass_decl *bypass;
2669 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2670 if (bypass->in_insn_reserv == in_insn_reserv)
2671 break;
2672 return bypass;
2675 /* The function processes pipeline description declarations, checks
2676 their correctness, and forms exclusion/presence/absence sets. */
2677 static void
2678 process_decls ()
2680 decl_t decl;
2681 decl_t automaton_decl;
2682 decl_t decl_in_table;
2683 decl_t out_insn_reserv;
2684 decl_t in_insn_reserv;
2685 struct bypass_decl *bypass;
2686 int automaton_presence;
2687 int i;
2689 /* Checking repeated automata declarations. */
2690 automaton_presence = 0;
2691 for (i = 0; i < description->decls_num; i++)
2693 decl = description->decls [i];
2694 if (decl->mode == dm_automaton)
2696 automaton_presence = 1;
2697 decl_in_table = insert_automaton_decl (decl);
2698 if (decl_in_table != decl)
2700 if (!w_flag)
2701 error ("repeated declaration of automaton `%s'",
2702 DECL_AUTOMATON (decl)->name);
2703 else
2704 warning ("repeated declaration of automaton `%s'",
2705 DECL_AUTOMATON (decl)->name);
2709 /* Checking undeclared automata, repeated declarations (except for
2710 automata) and correctness of their attributes (insn latency times
2711 etc.). */
2712 for (i = 0; i < description->decls_num; i++)
2714 decl = description->decls [i];
2715 if (decl->mode == dm_insn_reserv)
2717 DECL_INSN_RESERV (decl)->condexp
2718 = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
2719 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2720 error ("define_insn_reservation `%s' has negative latency time",
2721 DECL_INSN_RESERV (decl)->name);
2722 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2723 description->insns_num++;
2724 decl_in_table = insert_insn_decl (decl);
2725 if (decl_in_table != decl)
2726 error ("`%s' is already used as insn reservation name",
2727 DECL_INSN_RESERV (decl)->name);
2729 else if (decl->mode == dm_bypass)
2731 if (DECL_BYPASS (decl)->latency < 0)
2732 error ("define_bypass `%s - %s' has negative latency time",
2733 DECL_BYPASS (decl)->out_insn_name,
2734 DECL_BYPASS (decl)->in_insn_name);
2736 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2738 if (decl->mode == dm_unit)
2740 DECL_UNIT (decl)->automaton_decl = NULL;
2741 if (DECL_UNIT (decl)->automaton_name != NULL)
2743 automaton_decl
2744 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2745 if (automaton_decl == NULL)
2746 error ("automaton `%s' is not declared",
2747 DECL_UNIT (decl)->automaton_name);
2748 else
2750 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2751 DECL_UNIT (decl)->automaton_decl
2752 = DECL_AUTOMATON (automaton_decl);
2755 else if (automaton_presence)
2756 error ("define_unit `%s' without automaton when one defined",
2757 DECL_UNIT (decl)->name);
2758 DECL_UNIT (decl)->unit_num = description->units_num;
2759 description->units_num++;
2760 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2762 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2763 continue;
2765 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2767 else
2769 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2771 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2772 continue;
2774 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2776 if (decl_in_table == NULL)
2777 decl_in_table = insert_decl (decl);
2778 else
2780 if (decl->mode == dm_unit)
2781 error ("repeated declaration of unit `%s'",
2782 DECL_UNIT (decl)->name);
2783 else
2784 error ("repeated declaration of reservation `%s'",
2785 DECL_RESERV (decl)->name);
2789 /* Check bypasses and form list of bypasses for each (output)
2790 insn. */
2791 for (i = 0; i < description->decls_num; i++)
2793 decl = description->decls [i];
2794 if (decl->mode == dm_bypass)
2796 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2797 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2798 if (out_insn_reserv == NULL)
2799 error ("there is no insn reservation `%s'",
2800 DECL_BYPASS (decl)->out_insn_name);
2801 else if (in_insn_reserv == NULL)
2802 error ("there is no insn reservation `%s'",
2803 DECL_BYPASS (decl)->in_insn_name);
2804 else
2806 DECL_BYPASS (decl)->out_insn_reserv
2807 = DECL_INSN_RESERV (out_insn_reserv);
2808 DECL_BYPASS (decl)->in_insn_reserv
2809 = DECL_INSN_RESERV (in_insn_reserv);
2810 bypass
2811 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2812 DECL_BYPASS (decl)->in_insn_reserv);
2813 if (bypass != NULL)
2815 if (DECL_BYPASS (decl)->latency == bypass->latency)
2817 if (!w_flag)
2818 error
2819 ("the same bypass `%s - %s' is already defined",
2820 DECL_BYPASS (decl)->out_insn_name,
2821 DECL_BYPASS (decl)->in_insn_name);
2822 else
2823 warning
2824 ("the same bypass `%s - %s' is already defined",
2825 DECL_BYPASS (decl)->out_insn_name,
2826 DECL_BYPASS (decl)->in_insn_name);
2828 else
2829 error ("bypass `%s - %s' is already defined",
2830 DECL_BYPASS (decl)->out_insn_name,
2831 DECL_BYPASS (decl)->in_insn_name);
2833 else
2835 DECL_BYPASS (decl)->next
2836 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2837 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2838 = DECL_BYPASS (decl);
2844 /* Check exclusion set declarations and form exclussion sets. */
2845 for (i = 0; i < description->decls_num; i++)
2847 decl = description->decls [i];
2848 if (decl->mode == dm_excl)
2850 unit_set_el_t unit_set_el_list;
2851 unit_set_el_t unit_set_el_list_2;
2853 unit_set_el_list
2854 = process_excls (DECL_EXCL (decl)->names,
2855 DECL_EXCL (decl)->first_list_length, decl->pos);
2856 unit_set_el_list_2
2857 = process_excls (&DECL_EXCL (decl)->names
2858 [DECL_EXCL (decl)->first_list_length],
2859 DECL_EXCL (decl)->names_num
2860 - DECL_EXCL (decl)->first_list_length,
2861 decl->pos);
2862 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2863 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2867 /* Check presence set declarations and form presence sets. */
2868 for (i = 0; i < description->decls_num; i++)
2870 decl = description->decls [i];
2871 if (decl->mode == dm_presence)
2873 unit_set_el_t unit_set_el_list;
2874 unit_set_el_t unit_set_el_list_2;
2876 unit_set_el_list
2877 = process_presence_absence
2878 (DECL_PRESENCE (decl)->names,
2879 DECL_PRESENCE (decl)->first_list_length, decl->pos, 1);
2880 unit_set_el_list_2
2881 = process_presence_absence
2882 (&DECL_PRESENCE (decl)->names
2883 [DECL_PRESENCE (decl)->first_list_length],
2884 DECL_PRESENCE (decl)->names_num
2885 - DECL_PRESENCE (decl)->first_list_length,
2886 decl->pos, 1);
2887 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2888 decl->pos, 1);
2892 /* Check absence set declarations and form absence sets. */
2893 for (i = 0; i < description->decls_num; i++)
2895 decl = description->decls [i];
2896 if (decl->mode == dm_absence)
2898 unit_set_el_t unit_set_el_list;
2899 unit_set_el_t unit_set_el_list_2;
2901 unit_set_el_list
2902 = process_presence_absence
2903 (DECL_ABSENCE (decl)->names,
2904 DECL_ABSENCE (decl)->first_list_length, decl->pos, 0);
2905 unit_set_el_list_2
2906 = process_presence_absence
2907 (&DECL_ABSENCE (decl)->names
2908 [DECL_ABSENCE (decl)->first_list_length],
2909 DECL_ABSENCE (decl)->names_num
2910 - DECL_ABSENCE (decl)->first_list_length,
2911 decl->pos, 0);
2912 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2913 decl->pos, 0);
2918 /* The following function checks that declared automaton is used. If
2919 the automaton is not used, the function fixes error/warning. The
2920 following function must be called only after `process_decls'. */
2921 static void
2922 check_automaton_usage ()
2924 decl_t decl;
2925 int i;
2927 for (i = 0; i < description->decls_num; i++)
2929 decl = description->decls [i];
2930 if (decl->mode == dm_automaton
2931 && !DECL_AUTOMATON (decl)->automaton_is_used)
2933 if (!w_flag)
2934 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2935 else
2936 warning ("automaton `%s' is not used",
2937 DECL_AUTOMATON (decl)->name);
2942 /* The following recursive function processes all regexp in order to
2943 fix usage of units or reservations and to fix errors of undeclared
2944 name. The function may change unit_regexp onto reserv_regexp.
2945 Remember that reserv_regexp does not exist before the function
2946 call. */
2947 static regexp_t
2948 process_regexp (regexp)
2949 regexp_t regexp;
2951 decl_t decl_in_table;
2952 regexp_t new_regexp;
2953 int i;
2955 if (regexp->mode == rm_unit)
2957 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2958 if (decl_in_table == NULL)
2959 error ("undeclared unit or reservation `%s'",
2960 REGEXP_UNIT (regexp)->name);
2961 else if (decl_in_table->mode == dm_unit)
2963 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2964 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2966 else if (decl_in_table->mode == dm_reserv)
2968 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2969 new_regexp = create_node (sizeof (struct regexp));
2970 new_regexp->mode = rm_reserv;
2971 new_regexp->pos = regexp->pos;
2972 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2973 REGEXP_RESERV (new_regexp)->reserv_decl
2974 = DECL_RESERV (decl_in_table);
2975 regexp = new_regexp;
2977 else
2978 abort ();
2980 else if (regexp->mode == rm_sequence)
2981 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2982 REGEXP_SEQUENCE (regexp)->regexps [i]
2983 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2984 else if (regexp->mode == rm_allof)
2985 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2986 REGEXP_ALLOF (regexp)->regexps [i]
2987 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2988 else if (regexp->mode == rm_oneof)
2989 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2990 REGEXP_ONEOF (regexp)->regexps [i]
2991 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2992 else if (regexp->mode == rm_repeat)
2993 REGEXP_REPEAT (regexp)->regexp
2994 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2995 else if (regexp->mode != rm_nothing)
2996 abort ();
2997 return regexp;
3000 /* The following function processes regexp of define_reservation and
3001 define_insn_reservation with the aid of function
3002 `process_regexp'. */
3003 static void
3004 process_regexp_decls ()
3006 decl_t decl;
3007 int i;
3009 for (i = 0; i < description->decls_num; i++)
3011 decl = description->decls [i];
3012 if (decl->mode == dm_reserv)
3013 DECL_RESERV (decl)->regexp
3014 = process_regexp (DECL_RESERV (decl)->regexp);
3015 else if (decl->mode == dm_insn_reserv)
3016 DECL_INSN_RESERV (decl)->regexp
3017 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3021 /* The following function checks that declared unit is used. If the
3022 unit is not used, the function fixes errors/warnings. The
3023 following function must be called only after `process_decls',
3024 `process_regexp_decls'. */
3025 static void
3026 check_usage ()
3028 decl_t decl;
3029 int i;
3031 for (i = 0; i < description->decls_num; i++)
3033 decl = description->decls [i];
3034 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3036 if (!w_flag)
3037 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3038 else
3039 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3041 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3043 if (!w_flag)
3044 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3045 else
3046 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3051 /* The following variable value is number of reservation being
3052 processed on loop recognition. */
3053 static int curr_loop_pass_num;
3055 /* The following recursive function returns nonzero value if REGEXP
3056 contains given decl or reservations in given regexp refers for
3057 given decl. */
3058 static int
3059 loop_in_regexp (regexp, start_decl)
3060 regexp_t regexp;
3061 decl_t start_decl;
3063 int i;
3065 if (regexp == NULL)
3066 return 0;
3067 if (regexp->mode == rm_unit)
3068 return 0;
3069 else if (regexp->mode == rm_reserv)
3071 if (start_decl->mode == dm_reserv
3072 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3073 return 1;
3074 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3075 == curr_loop_pass_num)
3076 /* declaration has been processed. */
3077 return 0;
3078 else
3080 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3081 = curr_loop_pass_num;
3082 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3083 start_decl);
3086 else if (regexp->mode == rm_sequence)
3088 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3089 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3090 return 1;
3091 return 0;
3093 else if (regexp->mode == rm_allof)
3095 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3096 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3097 return 1;
3098 return 0;
3100 else if (regexp->mode == rm_oneof)
3102 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3103 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3104 return 1;
3105 return 0;
3107 else if (regexp->mode == rm_repeat)
3108 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3109 else
3111 if (regexp->mode != rm_nothing)
3112 abort ();
3113 return 0;
3117 /* The following function fixes errors "cycle in definition ...". The
3118 function uses function `loop_in_regexp' for that. */
3119 static void
3120 check_loops_in_regexps ()
3122 decl_t decl;
3123 int i;
3125 for (i = 0; i < description->decls_num; i++)
3127 decl = description->decls [i];
3128 if (decl->mode == dm_reserv)
3129 DECL_RESERV (decl)->loop_pass_num = 0;
3131 for (i = 0; i < description->decls_num; i++)
3133 decl = description->decls [i];
3134 curr_loop_pass_num = i;
3136 if (decl->mode == dm_reserv)
3138 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
3139 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3141 if (DECL_RESERV (decl)->regexp == NULL)
3142 abort ();
3143 error ("cycle in definition of reservation `%s'",
3144 DECL_RESERV (decl)->name);
3150 /* The function recursively processes IR of reservation and defines
3151 max and min cycle for reservation of unit and for result in the
3152 reservation. */
3153 static int
3154 process_regexp_cycles (regexp, start_cycle)
3155 regexp_t regexp;
3156 int start_cycle;
3158 int i;
3160 if (regexp->mode == rm_unit)
3162 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < start_cycle)
3163 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = start_cycle;
3164 return start_cycle;
3166 else if (regexp->mode == rm_reserv)
3167 return process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3168 start_cycle);
3169 else if (regexp->mode == rm_repeat)
3171 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3172 start_cycle = process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3173 start_cycle) + 1;
3174 return start_cycle;
3176 else if (regexp->mode == rm_sequence)
3178 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3179 start_cycle
3180 = process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3181 start_cycle) + 1;
3182 return start_cycle;
3184 else if (regexp->mode == rm_allof)
3186 int finish_cycle = 0;
3187 int cycle;
3189 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3191 cycle = process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3192 start_cycle);
3193 if (finish_cycle < cycle)
3194 finish_cycle = cycle;
3196 return finish_cycle;
3198 else if (regexp->mode == rm_oneof)
3200 int finish_cycle = 0;
3201 int cycle;
3203 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3205 cycle = process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3206 start_cycle);
3207 if (finish_cycle < cycle)
3208 finish_cycle = cycle;
3210 return finish_cycle;
3212 else
3214 if (regexp->mode != rm_nothing)
3215 abort ();
3216 return start_cycle;
3220 /* The following function is called only for correct program. The
3221 function defines max reservation of insns in cycles. */
3222 static void
3223 evaluate_max_reserv_cycles ()
3225 int max_insn_cycles_num;
3226 decl_t decl;
3227 int i;
3229 description->max_insn_reserv_cycles = 0;
3230 for (i = 0; i < description->decls_num; i++)
3232 decl = description->decls [i];
3233 if (decl->mode == dm_insn_reserv)
3235 max_insn_cycles_num
3236 = process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0);
3237 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3238 description->max_insn_reserv_cycles = max_insn_cycles_num;
3241 description->max_insn_reserv_cycles++;
3244 /* The following function calls functions for checking all
3245 description. */
3246 static void
3247 check_all_description ()
3249 process_decls ();
3250 check_automaton_usage ();
3251 process_regexp_decls ();
3252 check_usage ();
3253 check_loops_in_regexps ();
3254 if (!have_error)
3255 evaluate_max_reserv_cycles ();
3260 /* The page contains abstract data `ticker'. This data is used to
3261 report time of different phases of building automata. It is
3262 possibly to write a description for which automata will be built
3263 during several minutes even on fast machine. */
3265 /* The following function creates ticker and makes it active. */
3266 static ticker_t
3267 create_ticker ()
3269 ticker_t ticker;
3271 ticker.modified_creation_time = get_run_time ();
3272 ticker.incremented_off_time = 0;
3273 return ticker;
3276 /* The following function switches off given ticker. */
3277 static void
3278 ticker_off (ticker)
3279 ticker_t *ticker;
3281 if (ticker->incremented_off_time == 0)
3282 ticker->incremented_off_time = get_run_time () + 1;
3285 /* The following function switches on given ticker. */
3286 static void
3287 ticker_on (ticker)
3288 ticker_t *ticker;
3290 if (ticker->incremented_off_time != 0)
3292 ticker->modified_creation_time
3293 += get_run_time () - ticker->incremented_off_time + 1;
3294 ticker->incremented_off_time = 0;
3298 /* The following function returns current time in milliseconds since
3299 the moment when given ticker was created. */
3300 static int
3301 active_time (ticker)
3302 ticker_t ticker;
3304 if (ticker.incremented_off_time != 0)
3305 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3306 else
3307 return get_run_time () - ticker.modified_creation_time;
3310 /* The following function returns string representation of active time
3311 of given ticker. The result is string representation of seconds
3312 with accuracy of 1/100 second. Only result of the last call of the
3313 function exists. Therefore the following code is not correct
3315 printf ("parser time: %s\ngeneration time: %s\n",
3316 active_time_string (parser_ticker),
3317 active_time_string (generation_ticker));
3319 Correct code has to be the following
3321 printf ("parser time: %s\n", active_time_string (parser_ticker));
3322 printf ("generation time: %s\n",
3323 active_time_string (generation_ticker));
3326 static void
3327 print_active_time (f, ticker)
3328 FILE *f;
3329 ticker_t ticker;
3331 int msecs;
3333 msecs = active_time (ticker);
3334 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3339 /* The following variable value is number of automaton which are
3340 really being created. This value is defined on the base of
3341 argument of option `-split'. If the variable has zero value the
3342 number of automata is defined by the constructions `%automaton'.
3343 This case occures when option `-split' is absent or has zero
3344 argument. If constructions `define_automaton' is absent only one
3345 automaton is created. */
3346 static int automata_num;
3348 /* The following variable values are times of
3349 o transformation of regular expressions
3350 o building NDFA (DFA if !ndfa_flag)
3351 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3352 o DFA minimization
3353 o building insn equivalence classes
3354 o all previous ones
3355 o code output */
3356 static ticker_t transform_time;
3357 static ticker_t NDFA_time;
3358 static ticker_t NDFA_to_DFA_time;
3359 static ticker_t minimize_time;
3360 static ticker_t equiv_time;
3361 static ticker_t automaton_generation_time;
3362 static ticker_t output_time;
3364 /* The following variable values are times of
3365 all checking
3366 all generation
3367 all pipeline hazard translator work */
3368 static ticker_t check_time;
3369 static ticker_t generation_time;
3370 static ticker_t all_time;
3374 /* Pseudo insn decl which denotes advancing cycle. */
3375 static decl_t advance_cycle_insn_decl;
3376 static void
3377 add_advance_cycle_insn_decl ()
3379 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3380 advance_cycle_insn_decl->mode = dm_insn_reserv;
3381 advance_cycle_insn_decl->pos = no_pos;
3382 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3383 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
3384 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3385 = description->insns_num;
3386 description->decls [description->decls_num] = advance_cycle_insn_decl;
3387 description->decls_num++;
3388 description->insns_num++;
3389 num_dfa_decls++;
3393 /* Abstract data `alternative states' which reperesents
3394 nondeterministic nature of the description (see comments for
3395 structures alt_state and state). */
3397 /* List of free states. */
3398 static alt_state_t first_free_alt_state;
3400 #ifndef NDEBUG
3401 /* The following variables is maximal number of allocated nodes
3402 alt_state. */
3403 static int allocated_alt_states_num = 0;
3404 #endif
3406 /* The following function returns free node alt_state. It may be new
3407 allocated node or node freed eralier. */
3408 static alt_state_t
3409 get_free_alt_state ()
3411 alt_state_t result;
3413 if (first_free_alt_state != NULL)
3415 result = first_free_alt_state;
3416 first_free_alt_state = first_free_alt_state->next_alt_state;
3418 else
3420 #ifndef NDEBUG
3421 allocated_alt_states_num++;
3422 #endif
3423 result = create_node (sizeof (struct alt_state));
3425 result->state = NULL;
3426 result->next_alt_state = NULL;
3427 result->next_sorted_alt_state = NULL;
3428 return result;
3431 /* The function frees node ALT_STATE. */
3432 static void
3433 free_alt_state (alt_state)
3434 alt_state_t alt_state;
3436 if (alt_state == NULL)
3437 return;
3438 alt_state->next_alt_state = first_free_alt_state;
3439 first_free_alt_state = alt_state;
3442 /* The function frees list started with node ALT_STATE_LIST. */
3443 static void
3444 free_alt_states (alt_states_list)
3445 alt_state_t alt_states_list;
3447 alt_state_t curr_alt_state;
3448 alt_state_t next_alt_state;
3450 for (curr_alt_state = alt_states_list;
3451 curr_alt_state != NULL;
3452 curr_alt_state = next_alt_state)
3454 next_alt_state = curr_alt_state->next_alt_state;
3455 free_alt_state (curr_alt_state);
3459 /* The function compares unique numbers of alt states. */
3460 static int
3461 alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
3462 const void *alt_state_ptr_1;
3463 const void *alt_state_ptr_2;
3465 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3466 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3467 return 0;
3468 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3469 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3470 return -1;
3471 else
3472 return 1;
3475 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3476 states from the list. The comparison key is alt state unique
3477 number. */
3478 static alt_state_t
3479 uniq_sort_alt_states (alt_states_list)
3480 alt_state_t alt_states_list;
3482 alt_state_t curr_alt_state;
3483 vla_ptr_t alt_states;
3484 size_t i;
3485 size_t prev_unique_state_ind;
3486 alt_state_t result;
3487 alt_state_t *result_ptr;
3489 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3490 for (curr_alt_state = alt_states_list;
3491 curr_alt_state != NULL;
3492 curr_alt_state = curr_alt_state->next_alt_state)
3493 VLA_PTR_ADD (alt_states, curr_alt_state);
3494 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3495 sizeof (alt_state_t), alt_state_cmp);
3496 if (VLA_PTR_LENGTH (alt_states) == 0)
3497 result = NULL;
3498 else
3500 result_ptr = VLA_PTR_BEGIN (alt_states);
3501 prev_unique_state_ind = 0;
3502 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3503 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3505 prev_unique_state_ind++;
3506 result_ptr [prev_unique_state_ind] = result_ptr [i];
3508 #if 0
3509 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3510 free_alt_state (result_ptr [i]);
3511 #endif
3512 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3513 result_ptr = VLA_PTR_BEGIN (alt_states);
3514 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3515 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3516 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3517 result = *result_ptr;
3519 VLA_PTR_DELETE (alt_states);
3520 return result;
3523 /* The function checks equality of alt state lists. Remember that the
3524 lists must be already sorted by the previous function. */
3525 static int
3526 alt_states_eq (alt_states_1, alt_states_2)
3527 alt_state_t alt_states_1;
3528 alt_state_t alt_states_2;
3530 while (alt_states_1 != NULL && alt_states_2 != NULL
3531 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3533 alt_states_1 = alt_states_1->next_sorted_alt_state;
3534 alt_states_2 = alt_states_2->next_sorted_alt_state;
3536 return alt_states_1 == alt_states_2;
3539 /* Initialization of the abstract data. */
3540 static void
3541 initiate_alt_states ()
3543 first_free_alt_state = NULL;
3546 /* Finishing work with the abstract data. */
3547 static void
3548 finish_alt_states ()
3554 /* The page contains macros for work with bits strings. We could use
3555 standard gcc bitmap or sbitmap but it would result in difficulties
3556 of building canadian cross. */
3558 /* Set bit number bitno in the bit string. The macro is not side
3559 effect proof. */
3560 #define SET_BIT(bitstring, bitno) \
3561 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3563 /* Test if bit number bitno in the bitstring is set. The macro is not
3564 side effect proof. */
3565 #define TEST_BIT(bitstring, bitno) \
3566 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3570 /* This page contains abstract data `state'. */
3572 /* Maximal length of reservations in cycles (>= 1). */
3573 static int max_cycles_num;
3575 /* Number of set elements (see type set_el_t) needed for
3576 representation of one cycle reservation. It is depended on units
3577 number. */
3578 static int els_in_cycle_reserv;
3580 /* Number of set elements (see type set_el_t) needed for
3581 representation of maximal length reservation. Deterministic
3582 reservation is stored as set (bit string) of length equal to the
3583 variable value * number of bits in set_el_t. */
3584 static int els_in_reservs;
3586 /* VLA for representation of array of pointers to unit
3587 declarations. */
3588 static vla_ptr_t units_container;
3590 /* The start address of the array. */
3591 static unit_decl_t *units_array;
3593 /* Empty reservation of maximal length. */
3594 static reserv_sets_t empty_reserv;
3596 /* The state table itself is represented by the following variable. */
3597 static htab_t state_table;
3599 /* VLA for representation of array of pointers to free nodes
3600 `state'. */
3601 static vla_ptr_t free_states;
3603 static int curr_unique_state_num;
3605 #ifndef NDEBUG
3606 /* The following variables is maximal number of allocated nodes
3607 `state'. */
3608 static int allocated_states_num = 0;
3609 #endif
3611 /* Allocate new reservation set. */
3612 static reserv_sets_t
3613 alloc_empty_reserv_sets ()
3615 reserv_sets_t result;
3617 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3618 result = (reserv_sets_t) obstack_base (&irp);
3619 obstack_finish (&irp);
3620 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3621 return result;
3624 /* Hash value of reservation set. */
3625 static unsigned
3626 reserv_sets_hash_value (reservs)
3627 reserv_sets_t reservs;
3629 set_el_t hash_value;
3630 unsigned result;
3631 int reservs_num, i;
3632 set_el_t *reserv_ptr;
3634 hash_value = 0;
3635 reservs_num = els_in_reservs;
3636 reserv_ptr = reservs;
3637 i = 0;
3638 while (reservs_num != 0)
3640 reservs_num--;
3641 hash_value += ((*reserv_ptr >> i)
3642 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3643 i++;
3644 if (i == sizeof (set_el_t) * CHAR_BIT)
3645 i = 0;
3646 reserv_ptr++;
3648 if (sizeof (set_el_t) <= sizeof (unsigned))
3649 return hash_value;
3650 result = 0;
3651 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3653 result += (unsigned) hash_value;
3654 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3656 return result;
3659 /* Comparison of given reservation sets. */
3660 static int
3661 reserv_sets_cmp (reservs_1, reservs_2)
3662 reserv_sets_t reservs_1;
3663 reserv_sets_t reservs_2;
3665 int reservs_num;
3666 set_el_t *reserv_ptr_1;
3667 set_el_t *reserv_ptr_2;
3669 if (reservs_1 == NULL || reservs_2 == NULL)
3670 abort ();
3671 reservs_num = els_in_reservs;
3672 reserv_ptr_1 = reservs_1;
3673 reserv_ptr_2 = reservs_2;
3674 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3676 reservs_num--;
3677 reserv_ptr_1++;
3678 reserv_ptr_2++;
3680 if (reservs_num == 0)
3681 return 0;
3682 else if (*reserv_ptr_1 < *reserv_ptr_2)
3683 return -1;
3684 else
3685 return 1;
3688 /* The function checks equality of the reservation sets. */
3689 static int
3690 reserv_sets_eq (reservs_1, reservs_2)
3691 reserv_sets_t reservs_1;
3692 reserv_sets_t reservs_2;
3694 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3697 /* Set up in the reservation set that unit with UNIT_NUM is used on
3698 CYCLE_NUM. */
3699 static void
3700 set_unit_reserv (reservs, cycle_num, unit_num)
3701 reserv_sets_t reservs;
3702 int cycle_num;
3703 int unit_num;
3705 if (cycle_num >= max_cycles_num)
3706 abort ();
3707 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3708 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3711 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3712 used on CYCLE_NUM. */
3713 static int
3714 test_unit_reserv (reservs, cycle_num, unit_num)
3715 reserv_sets_t reservs;
3716 int cycle_num;
3717 int unit_num;
3719 if (cycle_num >= max_cycles_num)
3720 abort ();
3721 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3722 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3725 /* The function checks that the reservation set represents no one unit
3726 reservation. */
3727 static int
3728 it_is_empty_reserv_sets (operand)
3729 reserv_sets_t operand;
3731 set_el_t *reserv_ptr;
3732 int reservs_num;
3734 if (operand == NULL)
3735 abort ();
3736 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3737 reservs_num != 0;
3738 reserv_ptr++, reservs_num--)
3739 if (*reserv_ptr != 0)
3740 return 0;
3741 return 1;
3744 /* The function checks that the reservation sets are intersected,
3745 i.e. there is a unit reservation on a cycle in both reservation
3746 sets. */
3747 static int
3748 reserv_sets_are_intersected (operand_1, operand_2)
3749 reserv_sets_t operand_1;
3750 reserv_sets_t operand_2;
3752 set_el_t *el_ptr_1;
3753 set_el_t *el_ptr_2;
3754 set_el_t *cycle_ptr_1;
3755 set_el_t *cycle_ptr_2;
3756 int nonzero_p;
3758 if (operand_1 == NULL || operand_2 == NULL)
3759 abort ();
3760 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3761 el_ptr_1 < operand_1 + els_in_reservs;
3762 el_ptr_1++, el_ptr_2++)
3763 if (*el_ptr_1 & *el_ptr_2)
3764 return 1;
3765 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3766 cycle_ptr_1 < operand_1 + els_in_reservs;
3767 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3769 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3770 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3771 el_ptr_1++, el_ptr_2++)
3772 if (*el_ptr_1 & *el_ptr_2)
3773 return 1;
3774 nonzero_p = 0;
3775 for (el_ptr_1 = cycle_ptr_1,
3776 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 1);
3777 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3778 el_ptr_1++, el_ptr_2++)
3779 if (*el_ptr_1 & *el_ptr_2)
3780 break;
3781 else if (*el_ptr_2 != 0)
3782 nonzero_p = 1;
3783 if (nonzero_p && el_ptr_1 >= cycle_ptr_1 + els_in_cycle_reserv)
3784 return 1;
3785 for (el_ptr_1 = cycle_ptr_1,
3786 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 0);
3787 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3788 el_ptr_1++, el_ptr_2++)
3789 /* It looks like code for exclusion but exclusion set is
3790 made as symmetric relation preliminary. */
3791 if (*el_ptr_1 & *el_ptr_2)
3792 return 1;
3794 return 0;
3797 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3798 cpu cycle. The remaining bits of OPERAND (representing the last
3799 cycle unit reservations) are not chenged. */
3800 static void
3801 reserv_sets_shift (result, operand)
3802 reserv_sets_t result;
3803 reserv_sets_t operand;
3805 int i;
3807 if (result == NULL || operand == NULL || result == operand)
3808 abort ();
3809 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3810 result [i - els_in_cycle_reserv] = operand [i];
3813 /* OR of the reservation sets. */
3814 static void
3815 reserv_sets_or (result, operand_1, operand_2)
3816 reserv_sets_t result;
3817 reserv_sets_t operand_1;
3818 reserv_sets_t operand_2;
3820 set_el_t *el_ptr_1;
3821 set_el_t *el_ptr_2;
3822 set_el_t *result_set_el_ptr;
3824 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3825 abort ();
3826 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3827 el_ptr_1 < operand_1 + els_in_reservs;
3828 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3829 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3832 /* AND of the reservation sets. */
3833 static void
3834 reserv_sets_and (result, operand_1, operand_2)
3835 reserv_sets_t result;
3836 reserv_sets_t operand_1;
3837 reserv_sets_t operand_2;
3839 set_el_t *el_ptr_1;
3840 set_el_t *el_ptr_2;
3841 set_el_t *result_set_el_ptr;
3843 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3844 abort ();
3845 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3846 el_ptr_1 < operand_1 + els_in_reservs;
3847 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3848 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3851 /* The function outputs string representation of units reservation on
3852 cycle START_CYCLE in the reservation set. The function uses repeat
3853 construction if REPETITION_NUM > 1. */
3854 static void
3855 output_cycle_reservs (f, reservs, start_cycle, repetition_num)
3856 FILE *f;
3857 reserv_sets_t reservs;
3858 int start_cycle;
3859 int repetition_num;
3861 int unit_num;
3862 int reserved_units_num;
3864 reserved_units_num = 0;
3865 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3866 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3867 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3868 reserved_units_num++;
3869 if (repetition_num <= 0)
3870 abort ();
3871 if (repetition_num != 1 && reserved_units_num > 1)
3872 fprintf (f, "(");
3873 reserved_units_num = 0;
3874 for (unit_num = 0;
3875 unit_num < description->units_num;
3876 unit_num++)
3877 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3878 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3880 if (reserved_units_num != 0)
3881 fprintf (f, "+");
3882 reserved_units_num++;
3883 fprintf (f, "%s", units_array [unit_num]->name);
3885 if (reserved_units_num == 0)
3886 fprintf (f, NOTHING_NAME);
3887 if (repetition_num <= 0)
3888 abort ();
3889 if (reserved_units_num > 1)
3890 fprintf (f, ")");
3891 if (repetition_num != 1)
3892 fprintf (f, "*%d", repetition_num);
3895 /* The function outputs string representation of units reservation in
3896 the reservation set. */
3897 static void
3898 output_reserv_sets (f, reservs)
3899 FILE *f;
3900 reserv_sets_t reservs;
3902 int start_cycle = 0;
3903 int cycle;
3904 int repetition_num;
3906 repetition_num = 0;
3907 for (cycle = 0; cycle < max_cycles_num; cycle++)
3908 if (repetition_num == 0)
3910 repetition_num++;
3911 start_cycle = cycle;
3913 else if (memcmp
3914 ((char *) reservs + start_cycle * els_in_cycle_reserv
3915 * sizeof (set_el_t),
3916 (char *) reservs + cycle * els_in_cycle_reserv
3917 * sizeof (set_el_t),
3918 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3919 repetition_num++;
3920 else
3922 if (start_cycle != 0)
3923 fprintf (f, ", ");
3924 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3925 repetition_num = 1;
3926 start_cycle = cycle;
3928 if (start_cycle < max_cycles_num)
3930 if (start_cycle != 0)
3931 fprintf (f, ", ");
3932 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3936 /* The following function returns free node state for AUTOMATON. It
3937 may be new allocated node or node freed eralier. The function also
3938 allocates reservation set if WITH_RESERVS has nonzero value. */
3939 static state_t
3940 get_free_state (with_reservs, automaton)
3941 int with_reservs;
3942 automaton_t automaton;
3944 state_t result;
3946 if (max_cycles_num <= 0 || automaton == NULL)
3947 abort ();
3948 if (VLA_PTR_LENGTH (free_states) != 0)
3950 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
3951 VLA_PTR_SHORTEN (free_states, 1);
3952 result->automaton = automaton;
3953 result->first_out_arc = NULL;
3954 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3955 result->it_was_placed_in_stack_for_DFA_forming = 0;
3956 result->component_states = NULL;
3957 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3959 else
3961 #ifndef NDEBUG
3962 allocated_states_num++;
3963 #endif
3964 result = create_node (sizeof (struct state));
3965 result->automaton = automaton;
3966 result->first_out_arc = NULL;
3967 result->unique_num = curr_unique_state_num;
3968 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3969 curr_unique_state_num++;
3971 if (with_reservs)
3973 if (result->reservs == NULL)
3974 result->reservs = alloc_empty_reserv_sets ();
3975 else
3976 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3978 return result;
3981 /* The function frees node STATE. */
3982 static void
3983 free_state (state)
3984 state_t state;
3986 free_alt_states (state->component_states);
3987 VLA_PTR_ADD (free_states, state);
3990 /* Hash value of STATE. If STATE represents deterministic state it is
3991 simply hash value of the corresponding reservation set. Otherwise
3992 it is formed from hash values of the component deterministic
3993 states. One more key is order number of state automaton. */
3994 static unsigned
3995 state_hash (state)
3996 const void *state;
3998 unsigned int hash_value;
3999 alt_state_t alt_state;
4001 if (((state_t) state)->component_states == NULL)
4002 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
4003 else
4005 hash_value = 0;
4006 for (alt_state = ((state_t) state)->component_states;
4007 alt_state != NULL;
4008 alt_state = alt_state->next_sorted_alt_state)
4009 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4010 | (hash_value << CHAR_BIT))
4011 + alt_state->state->unique_num);
4013 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4014 | (hash_value << CHAR_BIT))
4015 + ((state_t) state)->automaton->automaton_order_num);
4016 return hash_value;
4019 /* Return nonzero value if the states are the same. */
4020 static int
4021 state_eq_p (state_1, state_2)
4022 const void *state_1;
4023 const void *state_2;
4025 alt_state_t alt_state_1;
4026 alt_state_t alt_state_2;
4028 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
4029 return 0;
4030 else if (((state_t) state_1)->component_states == NULL
4031 && ((state_t) state_2)->component_states == NULL)
4032 return reserv_sets_eq (((state_t) state_1)->reservs,
4033 ((state_t) state_2)->reservs);
4034 else if (((state_t) state_1)->component_states != NULL
4035 && ((state_t) state_2)->component_states != NULL)
4037 for (alt_state_1 = ((state_t) state_1)->component_states,
4038 alt_state_2 = ((state_t) state_2)->component_states;
4039 alt_state_1 != NULL && alt_state_2 != NULL;
4040 alt_state_1 = alt_state_1->next_sorted_alt_state,
4041 alt_state_2 = alt_state_2->next_sorted_alt_state)
4042 /* All state in the list must be already in the hash table.
4043 Also the lists must be sorted. */
4044 if (alt_state_1->state != alt_state_2->state)
4045 return 0;
4046 return alt_state_1 == alt_state_2;
4048 else
4049 return 0;
4052 /* Insert STATE into the state table. */
4053 static state_t
4054 insert_state (state)
4055 state_t state;
4057 void **entry_ptr;
4059 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
4060 if (*entry_ptr == NULL)
4061 *entry_ptr = (void *) state;
4062 return (state_t) *entry_ptr;
4065 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4066 deterministic STATE. */
4067 static void
4068 set_state_reserv (state, cycle_num, unit_num)
4069 state_t state;
4070 int cycle_num;
4071 int unit_num;
4073 set_unit_reserv (state->reservs, cycle_num, unit_num);
4076 /* Return nonzero value if the deterministic states contains a
4077 reservation of the same cpu unit on the same cpu cycle. */
4078 static int
4079 intersected_state_reservs_p (state1, state2)
4080 state_t state1;
4081 state_t state2;
4083 if (state1->automaton != state2->automaton)
4084 abort ();
4085 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
4088 /* Return deterministic state (inserted into the table) which
4089 representing the automaton state whic is union of reservations of
4090 deterministic states. */
4091 static state_t
4092 states_union (state1, state2)
4093 state_t state1;
4094 state_t state2;
4096 state_t result;
4097 state_t state_in_table;
4099 if (state1->automaton != state2->automaton)
4100 abort ();
4101 result = get_free_state (1, state1->automaton);
4102 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
4103 state_in_table = insert_state (result);
4104 if (result != state_in_table)
4106 free_state (result);
4107 result = state_in_table;
4109 return result;
4112 /* Return deterministic state (inserted into the table) which
4113 represent the automaton state is obtained from deterministic STATE
4114 by advancing cpu cycle. */
4115 static state_t
4116 state_shift (state)
4117 state_t state;
4119 state_t result;
4120 state_t state_in_table;
4122 result = get_free_state (1, state->automaton);
4123 reserv_sets_shift (result->reservs, state->reservs);
4124 state_in_table = insert_state (result);
4125 if (result != state_in_table)
4127 free_state (result);
4128 result = state_in_table;
4130 return result;
4133 /* Initialization of the abstract data. */
4134 static void
4135 initiate_states ()
4137 decl_t decl;
4138 int i;
4140 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
4141 units_array
4142 = (description->decls_num && description->units_num
4143 ? VLA_PTR_BEGIN (units_container) : NULL);
4144 for (i = 0; i < description->decls_num; i++)
4146 decl = description->decls [i];
4147 if (decl->mode == dm_unit)
4148 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
4150 max_cycles_num = description->max_insn_reserv_cycles;
4151 els_in_cycle_reserv
4152 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
4153 / (sizeof (set_el_t) * CHAR_BIT));
4154 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
4155 curr_unique_state_num = 0;
4156 initiate_alt_states ();
4157 VLA_PTR_CREATE (free_states, 1500, "free states");
4158 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
4159 empty_reserv = alloc_empty_reserv_sets ();
4162 /* Finisging work with the abstract data. */
4163 static void
4164 finish_states ()
4166 VLA_PTR_DELETE (units_container);
4167 htab_delete (state_table);
4168 VLA_PTR_DELETE (free_states);
4169 finish_alt_states ();
4174 /* Abstract data `arcs'. */
4176 /* List of free arcs. */
4177 static arc_t first_free_arc;
4179 #ifndef NDEBUG
4180 /* The following variables is maximal number of allocated nodes
4181 `arc'. */
4182 static int allocated_arcs_num = 0;
4183 #endif
4185 /* The function frees node ARC. */
4186 static void
4187 free_arc (arc)
4188 arc_t arc;
4190 arc->next_out_arc = first_free_arc;
4191 first_free_arc = arc;
4194 /* The function removes and frees ARC staring from FROM_STATE. */
4195 static void
4196 remove_arc (from_state, arc)
4197 state_t from_state;
4198 arc_t arc;
4200 arc_t prev_arc;
4201 arc_t curr_arc;
4203 if (arc == NULL)
4204 abort ();
4205 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
4206 curr_arc != NULL;
4207 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4208 if (curr_arc == arc)
4209 break;
4210 if (curr_arc == NULL)
4211 abort ();
4212 if (prev_arc == NULL)
4213 from_state->first_out_arc = arc->next_out_arc;
4214 else
4215 prev_arc->next_out_arc = arc->next_out_arc;
4216 free_arc (arc);
4219 /* The functions returns arc with given characteristics (or NULL if
4220 the arc does not exist). */
4221 static arc_t
4222 find_arc (from_state, to_state, insn)
4223 state_t from_state;
4224 state_t to_state;
4225 ainsn_t insn;
4227 arc_t arc;
4229 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4230 if (arc->to_state == to_state && arc->insn == insn)
4231 return arc;
4232 return NULL;
4235 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4236 and with given STATE_ALTS. The function returns added arc (or
4237 already existing arc). */
4238 static arc_t
4239 add_arc (from_state, to_state, ainsn, state_alts)
4240 state_t from_state;
4241 state_t to_state;
4242 ainsn_t ainsn;
4243 int state_alts;
4245 arc_t new_arc;
4247 new_arc = find_arc (from_state, to_state, ainsn);
4248 if (new_arc != NULL)
4249 return new_arc;
4250 if (first_free_arc == NULL)
4252 #ifndef NDEBUG
4253 allocated_arcs_num++;
4254 #endif
4255 new_arc = create_node (sizeof (struct arc));
4256 new_arc->to_state = NULL;
4257 new_arc->insn = NULL;
4258 new_arc->next_out_arc = NULL;
4260 else
4262 new_arc = first_free_arc;
4263 first_free_arc = first_free_arc->next_out_arc;
4265 new_arc->to_state = to_state;
4266 new_arc->insn = ainsn;
4267 ainsn->arc_exists_p = 1;
4268 new_arc->next_out_arc = from_state->first_out_arc;
4269 from_state->first_out_arc = new_arc;
4270 new_arc->next_arc_marked_by_insn = NULL;
4271 new_arc->state_alts = state_alts;
4272 return new_arc;
4275 /* The function returns the first arc starting from STATE. */
4276 static arc_t
4277 first_out_arc (state)
4278 state_t state;
4280 return state->first_out_arc;
4283 /* The function returns next out arc after ARC. */
4284 static arc_t
4285 next_out_arc (arc)
4286 arc_t arc;
4288 return arc->next_out_arc;
4291 /* Initialization of the abstract data. */
4292 static void
4293 initiate_arcs ()
4295 first_free_arc = NULL;
4298 /* Finishing work with the abstract data. */
4299 static void
4300 finish_arcs ()
4306 /* Abstract data `automata lists'. */
4308 /* List of free states. */
4309 static automata_list_el_t first_free_automata_list_el;
4311 /* The list being formed. */
4312 static automata_list_el_t current_automata_list;
4314 /* Hash table of automata lists. */
4315 static htab_t automata_list_table;
4317 /* The following function returns free automata list el. It may be
4318 new allocated node or node freed earlier. */
4319 static automata_list_el_t
4320 get_free_automata_list_el ()
4322 automata_list_el_t result;
4324 if (first_free_automata_list_el != NULL)
4326 result = first_free_automata_list_el;
4327 first_free_automata_list_el
4328 = first_free_automata_list_el->next_automata_list_el;
4330 else
4331 result = create_node (sizeof (struct automata_list_el));
4332 result->automaton = NULL;
4333 result->next_automata_list_el = NULL;
4334 return result;
4337 /* The function frees node AUTOMATA_LIST_EL. */
4338 static void
4339 free_automata_list_el (automata_list_el)
4340 automata_list_el_t automata_list_el;
4342 if (automata_list_el == NULL)
4343 return;
4344 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4345 first_free_automata_list_el = automata_list_el;
4348 /* The function frees list AUTOMATA_LIST. */
4349 static void
4350 free_automata_list (automata_list)
4351 automata_list_el_t automata_list;
4353 automata_list_el_t curr_automata_list_el;
4354 automata_list_el_t next_automata_list_el;
4356 for (curr_automata_list_el = automata_list;
4357 curr_automata_list_el != NULL;
4358 curr_automata_list_el = next_automata_list_el)
4360 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4361 free_automata_list_el (curr_automata_list_el);
4365 /* Hash value of AUTOMATA_LIST. */
4366 static unsigned
4367 automata_list_hash (automata_list)
4368 const void *automata_list;
4370 unsigned int hash_value;
4371 automata_list_el_t curr_automata_list_el;
4373 hash_value = 0;
4374 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4375 curr_automata_list_el != NULL;
4376 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4377 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4378 | (hash_value << CHAR_BIT))
4379 + curr_automata_list_el->automaton->automaton_order_num);
4380 return hash_value;
4383 /* Return nonzero value if the automata_lists are the same. */
4384 static int
4385 automata_list_eq_p (automata_list_1, automata_list_2)
4386 const void *automata_list_1;
4387 const void *automata_list_2;
4389 automata_list_el_t automata_list_el_1;
4390 automata_list_el_t automata_list_el_2;
4392 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4393 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4394 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4395 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4396 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4397 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4398 return 0;
4399 return automata_list_el_1 == automata_list_el_2;
4402 /* Initialization of the abstract data. */
4403 static void
4404 initiate_automata_lists ()
4406 first_free_automata_list_el = NULL;
4407 automata_list_table = htab_create (1500, automata_list_hash,
4408 automata_list_eq_p, (htab_del) 0);
4411 /* The following function starts new automata list and makes it the
4412 current one. */
4413 static void
4414 automata_list_start ()
4416 current_automata_list = NULL;
4419 /* The following function adds AUTOMATON to the current list. */
4420 static void
4421 automata_list_add (automaton)
4422 automaton_t automaton;
4424 automata_list_el_t el;
4426 el = get_free_automata_list_el ();
4427 el->automaton = automaton;
4428 el->next_automata_list_el = current_automata_list;
4429 current_automata_list = el;
4432 /* The following function finishes forming the current list, inserts
4433 it into the table and returns it. */
4434 static automata_list_el_t
4435 automata_list_finish ()
4437 void **entry_ptr;
4439 if (current_automata_list == NULL)
4440 return NULL;
4441 entry_ptr = htab_find_slot (automata_list_table,
4442 (void *) current_automata_list, 1);
4443 if (*entry_ptr == NULL)
4444 *entry_ptr = (void *) current_automata_list;
4445 else
4446 free_automata_list (current_automata_list);
4447 current_automata_list = NULL;
4448 return (automata_list_el_t) *entry_ptr;
4451 /* Finishing work with the abstract data. */
4452 static void
4453 finish_automata_lists ()
4455 htab_delete (automata_list_table);
4460 /* The page contains abstract data for work with exclusion sets (see
4461 exclusion_set in file rtl.def). */
4463 /* The following variable refers to an exclusion set returned by
4464 get_excl_set. This is bit string of length equal to cpu units
4465 number. If exclusion set for given unit contains 1 for a unit,
4466 then simultaneous reservation of the units is prohibited. */
4467 static reserv_sets_t excl_set;
4469 /* The array contains exclusion sets for each unit. */
4470 static reserv_sets_t *unit_excl_set_table;
4472 /* The following function forms the array containing exclusion sets
4473 for each unit. */
4474 static void
4475 initiate_excl_sets ()
4477 decl_t decl;
4478 reserv_sets_t unit_excl_set;
4479 unit_set_el_t el;
4480 int i;
4482 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4483 excl_set = (reserv_sets_t) obstack_base (&irp);
4484 obstack_finish (&irp);
4485 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4486 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4487 obstack_finish (&irp);
4488 /* Evaluate unit exclusion sets. */
4489 for (i = 0; i < description->decls_num; i++)
4491 decl = description->decls [i];
4492 if (decl->mode == dm_unit)
4494 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4495 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4496 obstack_finish (&irp);
4497 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4498 for (el = DECL_UNIT (decl)->excl_list;
4499 el != NULL;
4500 el = el->next_unit_set_el)
4501 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4502 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4507 /* The function sets up and return EXCL_SET which is union of
4508 exclusion sets for each unit in IN_SET. */
4509 static reserv_sets_t
4510 get_excl_set (in_set)
4511 reserv_sets_t in_set;
4513 int excl_char_num;
4514 int chars_num;
4515 int i;
4516 int start_unit_num;
4517 int unit_num;
4519 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4520 memset (excl_set, 0, chars_num);
4521 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4522 if (((unsigned char *) in_set) [excl_char_num])
4523 for (i = CHAR_BIT - 1; i >= 0; i--)
4524 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4526 start_unit_num = excl_char_num * CHAR_BIT + i;
4527 if (start_unit_num >= description->units_num)
4528 return excl_set;
4529 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4531 excl_set [unit_num]
4532 |= unit_excl_set_table [start_unit_num] [unit_num];
4535 return excl_set;
4540 /* The page contains abstract data for work with presence/absence sets
4541 (see presence_set/absence_set in file rtl.def). */
4543 /* The following variables refer to correspondingly an presence and an
4544 absence set returned by get_presence_absence_set. This is bit
4545 string of length equal to cpu units number. */
4546 static reserv_sets_t presence_set, absence_set;
4548 /* The following arrays contain correspondingly presence and absence
4549 sets for each unit. */
4550 static reserv_sets_t *unit_presence_set_table, *unit_absence_set_table;
4552 /* The following function forms the array containing presence and
4553 absence sets for each unit */
4554 static void
4555 initiate_presence_absence_sets ()
4557 decl_t decl;
4558 reserv_sets_t unit_set;
4559 unit_set_el_t el;
4560 int i;
4562 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4563 presence_set = (reserv_sets_t) obstack_base (&irp);
4564 obstack_finish (&irp);
4565 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4566 unit_presence_set_table = (reserv_sets_t *) obstack_base (&irp);
4567 obstack_finish (&irp);
4568 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4569 absence_set = (reserv_sets_t) obstack_base (&irp);
4570 obstack_finish (&irp);
4571 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4572 unit_absence_set_table = (reserv_sets_t *) obstack_base (&irp);
4573 obstack_finish (&irp);
4574 /* Evaluate unit presence/absence sets. */
4575 for (i = 0; i < description->decls_num; i++)
4577 decl = description->decls [i];
4578 if (decl->mode == dm_unit)
4580 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4581 unit_set = (reserv_sets_t) obstack_base (&irp);
4582 obstack_finish (&irp);
4583 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4584 for (el = DECL_UNIT (decl)->presence_list;
4585 el != NULL;
4586 el = el->next_unit_set_el)
4587 SET_BIT (unit_set, el->unit_decl->unit_num);
4588 unit_presence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4590 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4591 unit_set = (reserv_sets_t) obstack_base (&irp);
4592 obstack_finish (&irp);
4593 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4594 for (el = DECL_UNIT (decl)->absence_list;
4595 el != NULL;
4596 el = el->next_unit_set_el)
4597 SET_BIT (unit_set, el->unit_decl->unit_num);
4598 unit_absence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4603 /* The function sets up and return PRESENCE_SET (if PRESENCE_P) or
4604 ABSENCE_SET which is union of corresponding sets for each unit in
4605 IN_SET. */
4606 static reserv_sets_t
4607 get_presence_absence_set (in_set, presence_p)
4608 reserv_sets_t in_set;
4609 int presence_p;
4611 int char_num;
4612 int chars_num;
4613 int i;
4614 int start_unit_num;
4615 int unit_num;
4617 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4618 if (presence_p)
4619 memset (presence_set, 0, chars_num);
4620 else
4621 memset (absence_set, 0, chars_num);
4622 for (char_num = 0; char_num < chars_num; char_num++)
4623 if (((unsigned char *) in_set) [char_num])
4624 for (i = CHAR_BIT - 1; i >= 0; i--)
4625 if ((((unsigned char *) in_set) [char_num] >> i) & 1)
4627 start_unit_num = char_num * CHAR_BIT + i;
4628 if (start_unit_num >= description->units_num)
4629 return (presence_p ? presence_set : absence_set);
4630 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4631 if (presence_p)
4632 presence_set [unit_num]
4633 |= unit_presence_set_table [start_unit_num] [unit_num];
4634 else
4635 absence_set [unit_num]
4636 |= unit_absence_set_table [start_unit_num] [unit_num];
4638 return (presence_p ? presence_set : absence_set);
4643 /* This page contains code for transformation of original reservations
4644 described in .md file. The main goal of transformations is
4645 simplifying reservation and lifting up all `|' on the top of IR
4646 reservation representation. */
4649 /* The following function makes copy of IR representation of
4650 reservation. The function also substitutes all reservations
4651 defined by define_reservation by corresponding value during making
4652 the copy. */
4653 static regexp_t
4654 copy_insn_regexp (regexp)
4655 regexp_t regexp;
4657 regexp_t result;
4658 int i;
4660 if (regexp->mode == rm_reserv)
4661 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4662 else if (regexp->mode == rm_unit)
4663 result = copy_node (regexp, sizeof (struct regexp));
4664 else if (regexp->mode == rm_repeat)
4666 result = copy_node (regexp, sizeof (struct regexp));
4667 REGEXP_REPEAT (result)->regexp
4668 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4670 else if (regexp->mode == rm_sequence)
4672 result = copy_node (regexp,
4673 sizeof (struct regexp) + sizeof (regexp_t)
4674 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4675 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4676 REGEXP_SEQUENCE (result)->regexps [i]
4677 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4679 else if (regexp->mode == rm_allof)
4681 result = copy_node (regexp,
4682 sizeof (struct regexp) + sizeof (regexp_t)
4683 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4684 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4685 REGEXP_ALLOF (result)->regexps [i]
4686 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4688 else if (regexp->mode == rm_oneof)
4690 result = copy_node (regexp,
4691 sizeof (struct regexp) + sizeof (regexp_t)
4692 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4693 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4694 REGEXP_ONEOF (result)->regexps [i]
4695 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4697 else
4699 if (regexp->mode != rm_nothing)
4700 abort ();
4701 result = copy_node (regexp, sizeof (struct regexp));
4703 return result;
4706 /* The following variable is set up 1 if a transformation has been
4707 applied. */
4708 static int regexp_transformed_p;
4710 /* The function makes transformation
4711 A*N -> A, A, ... */
4712 static regexp_t
4713 transform_1 (regexp)
4714 regexp_t regexp;
4716 int i;
4717 int repeat_num;
4718 regexp_t operand;
4719 pos_t pos;
4721 if (regexp->mode == rm_repeat)
4723 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4724 if (repeat_num <= 1)
4725 abort ();
4726 operand = REGEXP_REPEAT (regexp)->regexp;
4727 pos = regexp->mode;
4728 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4729 * (repeat_num - 1));
4730 regexp->mode = rm_sequence;
4731 regexp->pos = pos;
4732 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4733 for (i = 0; i < repeat_num; i++)
4734 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4735 regexp_transformed_p = 1;
4737 return regexp;
4740 /* The function makes transformations
4741 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4742 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4743 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4744 static regexp_t
4745 transform_2 (regexp)
4746 regexp_t regexp;
4748 if (regexp->mode == rm_sequence)
4750 regexp_t sequence = NULL;
4751 regexp_t result;
4752 int sequence_index = 0;
4753 int i, j;
4755 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4756 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4758 sequence_index = i;
4759 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4760 break;
4762 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4764 if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
4765 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4766 abort ();
4767 result = create_node (sizeof (struct regexp)
4768 + sizeof (regexp_t)
4769 * (REGEXP_SEQUENCE (regexp)->regexps_num
4770 + REGEXP_SEQUENCE (sequence)->regexps_num
4771 - 2));
4772 result->mode = rm_sequence;
4773 result->pos = regexp->pos;
4774 REGEXP_SEQUENCE (result)->regexps_num
4775 = (REGEXP_SEQUENCE (regexp)->regexps_num
4776 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4777 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4778 if (i < sequence_index)
4779 REGEXP_SEQUENCE (result)->regexps [i]
4780 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4781 else if (i > sequence_index)
4782 REGEXP_SEQUENCE (result)->regexps
4783 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4784 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4785 else
4786 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4787 REGEXP_SEQUENCE (result)->regexps [i + j]
4788 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4789 regexp_transformed_p = 1;
4790 regexp = result;
4793 else if (regexp->mode == rm_allof)
4795 regexp_t allof = NULL;
4796 regexp_t result;
4797 int allof_index = 0;
4798 int i, j;
4800 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4801 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4803 allof_index = i;
4804 allof = REGEXP_ALLOF (regexp)->regexps [i];
4805 break;
4807 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4809 if (REGEXP_ALLOF (allof)->regexps_num <= 1
4810 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4811 abort ();
4812 result = create_node (sizeof (struct regexp)
4813 + sizeof (regexp_t)
4814 * (REGEXP_ALLOF (regexp)->regexps_num
4815 + REGEXP_ALLOF (allof)->regexps_num - 2));
4816 result->mode = rm_allof;
4817 result->pos = regexp->pos;
4818 REGEXP_ALLOF (result)->regexps_num
4819 = (REGEXP_ALLOF (regexp)->regexps_num
4820 + REGEXP_ALLOF (allof)->regexps_num - 1);
4821 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4822 if (i < allof_index)
4823 REGEXP_ALLOF (result)->regexps [i]
4824 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4825 else if (i > allof_index)
4826 REGEXP_ALLOF (result)->regexps
4827 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4828 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4829 else
4830 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4831 REGEXP_ALLOF (result)->regexps [i + j]
4832 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4833 regexp_transformed_p = 1;
4834 regexp = result;
4837 else if (regexp->mode == rm_oneof)
4839 regexp_t oneof = NULL;
4840 regexp_t result;
4841 int oneof_index = 0;
4842 int i, j;
4844 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4845 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4847 oneof_index = i;
4848 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4849 break;
4851 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4853 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4854 || REGEXP_ONEOF (regexp)->regexps_num <= 1)
4855 abort ();
4856 result = create_node (sizeof (struct regexp)
4857 + sizeof (regexp_t)
4858 * (REGEXP_ONEOF (regexp)->regexps_num
4859 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4860 result->mode = rm_oneof;
4861 result->pos = regexp->pos;
4862 REGEXP_ONEOF (result)->regexps_num
4863 = (REGEXP_ONEOF (regexp)->regexps_num
4864 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4865 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4866 if (i < oneof_index)
4867 REGEXP_ONEOF (result)->regexps [i]
4868 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4869 else if (i > oneof_index)
4870 REGEXP_ONEOF (result)->regexps
4871 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4872 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4873 else
4874 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4875 REGEXP_ONEOF (result)->regexps [i + j]
4876 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4877 regexp_transformed_p = 1;
4878 regexp = result;
4881 return regexp;
4884 /* The function makes transformations
4885 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4886 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4887 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4888 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4889 static regexp_t
4890 transform_3 (regexp)
4891 regexp_t regexp;
4893 if (regexp->mode == rm_sequence)
4895 regexp_t oneof = NULL;
4896 int oneof_index = 0;
4897 regexp_t result;
4898 regexp_t sequence;
4899 int i, j;
4901 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4902 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4904 oneof_index = i;
4905 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4906 break;
4908 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4910 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4911 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4912 abort ();
4913 result = create_node (sizeof (struct regexp)
4914 + sizeof (regexp_t)
4915 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4916 result->mode = rm_oneof;
4917 result->pos = regexp->pos;
4918 REGEXP_ONEOF (result)->regexps_num
4919 = REGEXP_ONEOF (oneof)->regexps_num;
4920 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4922 sequence
4923 = create_node (sizeof (struct regexp)
4924 + sizeof (regexp_t)
4925 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4926 sequence->mode = rm_sequence;
4927 sequence->pos = regexp->pos;
4928 REGEXP_SEQUENCE (sequence)->regexps_num
4929 = REGEXP_SEQUENCE (regexp)->regexps_num;
4930 REGEXP_ONEOF (result)->regexps [i] = sequence;
4931 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4932 if (j != oneof_index)
4933 REGEXP_SEQUENCE (sequence)->regexps [j]
4934 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4935 else
4936 REGEXP_SEQUENCE (sequence)->regexps [j]
4937 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4939 regexp_transformed_p = 1;
4940 regexp = result;
4943 else if (regexp->mode == rm_allof)
4945 regexp_t oneof = NULL, seq;
4946 int oneof_index = 0, max_seq_length, allof_length;
4947 regexp_t result;
4948 regexp_t allof = NULL, allof_op = NULL;
4949 int i, j;
4951 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4952 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4954 oneof_index = i;
4955 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4956 break;
4958 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4960 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4961 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4962 abort ();
4963 result = create_node (sizeof (struct regexp)
4964 + sizeof (regexp_t)
4965 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4966 result->mode = rm_oneof;
4967 result->pos = regexp->pos;
4968 REGEXP_ONEOF (result)->regexps_num
4969 = REGEXP_ONEOF (oneof)->regexps_num;
4970 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4972 allof
4973 = create_node (sizeof (struct regexp)
4974 + sizeof (regexp_t)
4975 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4976 allof->mode = rm_allof;
4977 allof->pos = regexp->pos;
4978 REGEXP_ALLOF (allof)->regexps_num
4979 = REGEXP_ALLOF (regexp)->regexps_num;
4980 REGEXP_ONEOF (result)->regexps [i] = allof;
4981 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4982 if (j != oneof_index)
4983 REGEXP_ALLOF (allof)->regexps [j]
4984 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4985 else
4986 REGEXP_ALLOF (allof)->regexps [j]
4987 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4989 regexp_transformed_p = 1;
4990 regexp = result;
4992 max_seq_length = 0;
4993 if (regexp->mode == rm_allof)
4994 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4995 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
4997 seq = REGEXP_ALLOF (regexp)->regexps [i];
4998 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4999 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
5001 else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit)
5003 max_seq_length = 0;
5004 break;
5006 if (max_seq_length != 0)
5008 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5009 abort ();
5010 result = create_node (sizeof (struct regexp)
5011 + sizeof (regexp_t) * (max_seq_length - 1));
5012 result->mode = rm_sequence;
5013 result->pos = regexp->pos;
5014 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5015 for (i = 0; i < max_seq_length; i++)
5017 allof_length = 0;
5018 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5019 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5020 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5021 ->regexps [j])->regexps_num)))
5023 allof_op
5024 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5025 ->regexps [i]);
5026 allof_length++;
5028 else if (i == 0
5029 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5030 == rm_unit))
5032 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5033 allof_length++;
5035 if (allof_length == 1)
5036 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5037 else
5039 allof = create_node (sizeof (struct regexp)
5040 + sizeof (regexp_t)
5041 * (allof_length - 1));
5042 allof->mode = rm_allof;
5043 allof->pos = regexp->pos;
5044 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5045 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5046 allof_length = 0;
5047 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5048 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5049 && (i <
5050 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5051 ->regexps [j])->regexps_num)))
5053 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5054 ->regexps [j])
5055 ->regexps [i]);
5056 REGEXP_ALLOF (allof)->regexps [allof_length]
5057 = allof_op;
5058 allof_length++;
5060 else if (i == 0
5061 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5062 == rm_unit))
5064 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5065 REGEXP_ALLOF (allof)->regexps [allof_length]
5066 = allof_op;
5067 allof_length++;
5071 regexp_transformed_p = 1;
5072 regexp = result;
5075 return regexp;
5078 /* The function traverses IR of reservation and applies transformations
5079 implemented by FUNC. */
5080 static regexp_t
5081 regexp_transform_func (regexp, func)
5082 regexp_t regexp;
5083 regexp_t (*func) PARAMS ((regexp_t regexp));
5085 int i;
5087 if (regexp->mode == rm_sequence)
5088 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5089 REGEXP_SEQUENCE (regexp)->regexps [i]
5090 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5091 else if (regexp->mode == rm_allof)
5092 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5093 REGEXP_ALLOF (regexp)->regexps [i]
5094 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5095 else if (regexp->mode == rm_oneof)
5096 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5097 REGEXP_ONEOF (regexp)->regexps [i]
5098 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5099 else if (regexp->mode == rm_repeat)
5100 REGEXP_REPEAT (regexp)->regexp
5101 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5102 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5103 abort ();
5104 return (*func) (regexp);
5107 /* The function applies all transformations for IR representation of
5108 reservation REGEXP. */
5109 static regexp_t
5110 transform_regexp (regexp)
5111 regexp_t regexp;
5113 regexp = regexp_transform_func (regexp, transform_1);
5116 regexp_transformed_p = 0;
5117 regexp = regexp_transform_func (regexp, transform_2);
5118 regexp = regexp_transform_func (regexp, transform_3);
5120 while (regexp_transformed_p);
5121 return regexp;
5124 /* The function applys all transformations for reservations of all
5125 insn declarations. */
5126 static void
5127 transform_insn_regexps ()
5129 decl_t decl;
5130 int i;
5132 transform_time = create_ticker ();
5133 add_advance_cycle_insn_decl ();
5134 fprintf (stderr, "Reservation transformation...");
5135 fflush (stderr);
5136 for (i = 0; i < description->decls_num; i++)
5138 decl = description->decls [i];
5139 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5140 DECL_INSN_RESERV (decl)->transformed_regexp
5141 = transform_regexp (copy_insn_regexp
5142 (DECL_INSN_RESERV (decl)->regexp));
5144 fprintf (stderr, "done\n");
5145 ticker_off (&transform_time);
5146 fflush (stderr);
5151 /* The following variable is an array indexed by cycle. Each element
5152 contains cyclic list of units which should be in the same cycle. */
5153 static unit_decl_t *the_same_automaton_lists;
5155 /* The function processes all alternative reservations on CYCLE in
5156 given REGEXP to check the UNIT is not reserved on the all
5157 alternatives. If it is true, the unit should be in the same
5158 automaton with other analogous units reserved on CYCLE in given
5159 REGEXP. */
5160 static void
5161 process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
5162 regexp_t unit;
5163 regexp_t regexp;
5164 int cycle;
5166 int i, k;
5167 regexp_t seq, allof;
5168 unit_decl_t unit_decl, last;
5170 if (regexp == NULL || regexp->mode != rm_oneof)
5171 abort ();
5172 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5173 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5175 seq = REGEXP_ONEOF (regexp)->regexps [i];
5176 if (seq->mode == rm_sequence)
5178 if (cycle >= REGEXP_SEQUENCE (seq)->regexps_num)
5179 break;
5180 allof = REGEXP_SEQUENCE (seq)->regexps [cycle];
5181 if (allof->mode == rm_allof)
5183 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5184 if (REGEXP_ALLOF (allof)->regexps [k]->mode == rm_unit
5185 && (REGEXP_UNIT (REGEXP_ALLOF (allof)->regexps [k])
5186 ->unit_decl == unit_decl))
5187 break;
5188 if (k >= REGEXP_ALLOF (allof)->regexps_num)
5189 break;
5191 else if (allof->mode == rm_unit
5192 && REGEXP_UNIT (allof)->unit_decl != unit_decl)
5193 break;
5195 else if (cycle != 0)
5196 break;
5197 else if (seq->mode == rm_allof)
5199 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5200 if (REGEXP_ALLOF (seq)->regexps [k]->mode == rm_unit
5201 && (REGEXP_UNIT (REGEXP_ALLOF (seq)->regexps [k])->unit_decl
5202 == unit_decl))
5203 break;
5204 if (k >= REGEXP_ALLOF (seq)->regexps_num)
5205 break;
5207 else if (seq->mode == rm_unit
5208 && REGEXP_UNIT (seq)->unit_decl != unit_decl)
5209 break;
5211 if (i >= 0)
5213 if (the_same_automaton_lists [cycle] == NULL)
5214 the_same_automaton_lists [cycle] = unit_decl;
5215 else
5217 for (last = the_same_automaton_lists [cycle];;)
5219 if (last == unit_decl)
5220 return;
5221 if (last->the_same_automaton_unit
5222 == the_same_automaton_lists [cycle])
5223 break;
5224 last = last->the_same_automaton_unit;
5226 last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
5227 unit_decl->the_same_automaton_unit
5228 = the_same_automaton_lists [cycle];
5233 /* The function processes given REGEXP to find units which should be
5234 in the same automaton. */
5235 static void
5236 form_the_same_automaton_unit_lists_from_regexp (regexp)
5237 regexp_t regexp;
5239 int i, j, k;
5240 regexp_t seq, allof, unit;
5242 if (regexp == NULL || regexp->mode != rm_oneof)
5243 return;
5244 for (i = 0; i < description->max_insn_reserv_cycles; i++)
5245 the_same_automaton_lists [i] = NULL;
5246 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5248 seq = REGEXP_ONEOF (regexp)->regexps [i];
5249 if (seq->mode == rm_sequence)
5250 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5252 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5253 if (allof->mode == rm_allof)
5254 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5256 unit = REGEXP_ALLOF (allof)->regexps [k];
5257 if (unit->mode == rm_unit)
5258 process_unit_to_form_the_same_automaton_unit_lists
5259 (unit, regexp, j);
5260 else if (unit->mode != rm_nothing)
5261 abort ();
5263 else if (allof->mode == rm_unit)
5264 process_unit_to_form_the_same_automaton_unit_lists
5265 (allof, regexp, j);
5266 else if (allof->mode != rm_nothing)
5267 abort ();
5269 else if (seq->mode == rm_allof)
5270 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5272 unit = REGEXP_ALLOF (seq)->regexps [k];
5273 if (unit->mode == rm_unit)
5274 process_unit_to_form_the_same_automaton_unit_lists
5275 (unit, regexp, 0);
5276 else if (unit->mode != rm_nothing)
5277 abort ();
5279 else if (seq->mode == rm_unit)
5280 process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
5281 else if (seq->mode != rm_nothing)
5282 abort ();
5286 /* The function initializes data to search for units which should be
5287 in the same automaton and call function
5288 `form_the_same_automaton_unit_lists_from_regexp' for each insn
5289 reservation regexp. */
5290 static void
5291 form_the_same_automaton_unit_lists ()
5293 decl_t decl;
5294 int i;
5296 the_same_automaton_lists
5297 = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
5298 * sizeof (unit_decl_t));
5299 for (i = 0; i < description->decls_num; i++)
5301 decl = description->decls [i];
5302 if (decl->mode == dm_unit)
5304 DECL_UNIT (decl)->the_same_automaton_message_reported_p = FALSE;
5305 DECL_UNIT (decl)->the_same_automaton_unit = DECL_UNIT (decl);
5308 for (i = 0; i < description->decls_num; i++)
5310 decl = description->decls [i];
5311 if (decl->mode == dm_insn_reserv)
5312 form_the_same_automaton_unit_lists_from_regexp
5313 (DECL_INSN_RESERV (decl)->transformed_regexp);
5315 free (the_same_automaton_lists);
5318 /* The function finds units which should be in the same automaton and,
5319 if they are not, reports about it. */
5320 static void
5321 check_unit_distributions_to_automata ()
5323 decl_t decl;
5324 unit_decl_t start_unit_decl, unit_decl;
5325 int i;
5327 form_the_same_automaton_unit_lists ();
5328 for (i = 0; i < description->decls_num; i++)
5330 decl = description->decls [i];
5331 if (decl->mode == dm_unit)
5333 start_unit_decl = DECL_UNIT (decl);
5334 if (!start_unit_decl->the_same_automaton_message_reported_p)
5335 for (unit_decl = start_unit_decl->the_same_automaton_unit;
5336 unit_decl != start_unit_decl;
5337 unit_decl = unit_decl->the_same_automaton_unit)
5338 if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
5340 error ("Units `%s' and `%s' should be in the same automaton",
5341 start_unit_decl->name, unit_decl->name);
5342 unit_decl->the_same_automaton_message_reported_p = TRUE;
5350 /* The page contains code for building alt_states (see comments for
5351 IR) describing all possible insns reservations of an automaton. */
5353 /* Current state being formed for which the current alt_state
5354 refers. */
5355 static state_t state_being_formed;
5357 /* Current alt_state being formed. */
5358 static alt_state_t alt_state_being_formed;
5360 /* This recursive function processes `,' and units in reservation
5361 REGEXP for forming alt_states of AUTOMATON. It is believed that
5362 CURR_CYCLE is start cycle of all reservation REGEXP. */
5363 static int
5364 process_seq_for_forming_states (regexp, automaton, curr_cycle)
5365 regexp_t regexp;
5366 automaton_t automaton;
5367 int curr_cycle;
5369 int i;
5371 if (regexp == NULL)
5372 return curr_cycle;
5373 else if (regexp->mode == rm_unit)
5375 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5376 == automaton->automaton_order_num)
5377 set_state_reserv (state_being_formed, curr_cycle,
5378 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5379 return curr_cycle;
5381 else if (regexp->mode == rm_sequence)
5383 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5384 curr_cycle
5385 = process_seq_for_forming_states
5386 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5387 return curr_cycle;
5389 else if (regexp->mode == rm_allof)
5391 int finish_cycle = 0;
5392 int cycle;
5394 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5396 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5397 ->regexps [i],
5398 automaton, curr_cycle);
5399 if (finish_cycle < cycle)
5400 finish_cycle = cycle;
5402 return finish_cycle;
5404 else
5406 if (regexp->mode != rm_nothing)
5407 abort ();
5408 return curr_cycle;
5412 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5413 inserts alt_state into the table. */
5414 static void
5415 finish_forming_alt_state (alt_state, automaton)
5416 alt_state_t alt_state;
5417 automaton_t automaton ATTRIBUTE_UNUSED;
5419 state_t state_in_table;
5420 state_t corresponding_state;
5422 corresponding_state = alt_state->state;
5423 state_in_table = insert_state (corresponding_state);
5424 if (state_in_table != corresponding_state)
5426 free_state (corresponding_state);
5427 alt_state->state = state_in_table;
5431 /* The following variable value is current automaton insn for whose
5432 reservation the alt states are created. */
5433 static ainsn_t curr_ainsn;
5435 /* This recursive function processes `|' in reservation REGEXP for
5436 forming alt_states of AUTOMATON. List of the alt states should
5437 have the same order as in the description. */
5438 static void
5439 process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5440 regexp_t regexp;
5441 automaton_t automaton;
5442 int inside_oneof_p;
5444 int i;
5446 if (regexp->mode != rm_oneof)
5448 alt_state_being_formed = get_free_alt_state ();
5449 state_being_formed = get_free_state (1, automaton);
5450 alt_state_being_formed->state = state_being_formed;
5451 /* We inserts in reverse order but we process alternatives also
5452 in reverse order. So we have the same order of alternative
5453 as in the description. */
5454 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5455 curr_ainsn->alt_states = alt_state_being_formed;
5456 (void) process_seq_for_forming_states (regexp, automaton, 0);
5457 finish_forming_alt_state (alt_state_being_formed, automaton);
5459 else
5461 if (inside_oneof_p)
5462 abort ();
5463 /* We processes it in reverse order to get list with the same
5464 order as in the description. See also the previous
5465 commentary. */
5466 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5467 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5468 automaton, 1);
5472 /* Create nodes alt_state for all AUTOMATON insns. */
5473 static void
5474 create_alt_states (automaton)
5475 automaton_t automaton;
5477 struct insn_reserv_decl *reserv_decl;
5479 for (curr_ainsn = automaton->ainsn_list;
5480 curr_ainsn != NULL;
5481 curr_ainsn = curr_ainsn->next_ainsn)
5483 reserv_decl = curr_ainsn->insn_reserv_decl;
5484 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5486 curr_ainsn->alt_states = NULL;
5487 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5488 automaton, 0);
5489 curr_ainsn->sorted_alt_states
5490 = uniq_sort_alt_states (curr_ainsn->alt_states);
5497 /* The page contains major code for building DFA(s) for fast pipeline
5498 hazards recognition. */
5500 /* The function forms list of ainsns of AUTOMATON with the same
5501 reservation. */
5502 static void
5503 form_ainsn_with_same_reservs (automaton)
5504 automaton_t automaton;
5506 ainsn_t curr_ainsn;
5507 size_t i;
5508 vla_ptr_t first_insns;
5509 vla_ptr_t last_insns;
5511 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5512 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5513 for (curr_ainsn = automaton->ainsn_list;
5514 curr_ainsn != NULL;
5515 curr_ainsn = curr_ainsn->next_ainsn)
5516 if (curr_ainsn->insn_reserv_decl
5517 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5519 curr_ainsn->next_same_reservs_insn = NULL;
5520 curr_ainsn->first_insn_with_same_reservs = 1;
5522 else
5524 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5525 if (alt_states_eq
5526 (curr_ainsn->sorted_alt_states,
5527 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5528 break;
5529 curr_ainsn->next_same_reservs_insn = NULL;
5530 if (i < VLA_PTR_LENGTH (first_insns))
5532 curr_ainsn->first_insn_with_same_reservs = 0;
5533 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5534 = curr_ainsn;
5535 VLA_PTR (last_insns, i) = curr_ainsn;
5537 else
5539 VLA_PTR_ADD (first_insns, curr_ainsn);
5540 VLA_PTR_ADD (last_insns, curr_ainsn);
5541 curr_ainsn->first_insn_with_same_reservs = 1;
5544 VLA_PTR_DELETE (first_insns);
5545 VLA_PTR_DELETE (last_insns);
5548 /* The following function creates all states of nondeterministic (if
5549 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5550 static void
5551 make_automaton (automaton)
5552 automaton_t automaton;
5554 ainsn_t ainsn;
5555 struct insn_reserv_decl *insn_reserv_decl;
5556 alt_state_t alt_state;
5557 state_t state;
5558 state_t start_state;
5559 state_t state2;
5560 ainsn_t advance_cycle_ainsn;
5561 arc_t added_arc;
5562 vla_ptr_t state_stack;
5564 VLA_PTR_CREATE (state_stack, 150, "state stack");
5565 /* Create the start state (empty state). */
5566 start_state = insert_state (get_free_state (1, automaton));
5567 automaton->start_state = start_state;
5568 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5569 VLA_PTR_ADD (state_stack, start_state);
5570 while (VLA_PTR_LENGTH (state_stack) != 0)
5572 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5573 VLA_PTR_SHORTEN (state_stack, 1);
5574 advance_cycle_ainsn = NULL;
5575 for (ainsn = automaton->ainsn_list;
5576 ainsn != NULL;
5577 ainsn = ainsn->next_ainsn)
5578 if (ainsn->first_insn_with_same_reservs)
5580 insn_reserv_decl = ainsn->insn_reserv_decl;
5581 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5583 /* We process alt_states in the same order as they are
5584 present in the description. */
5585 added_arc = NULL;
5586 for (alt_state = ainsn->alt_states;
5587 alt_state != NULL;
5588 alt_state = alt_state->next_alt_state)
5590 state2 = alt_state->state;
5591 if (!intersected_state_reservs_p (state, state2))
5593 state2 = states_union (state, state2);
5594 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5596 state2->it_was_placed_in_stack_for_NDFA_forming
5597 = 1;
5598 VLA_PTR_ADD (state_stack, state2);
5600 added_arc = add_arc (state, state2, ainsn, 1);
5601 if (!ndfa_flag)
5602 break;
5605 if (!ndfa_flag && added_arc != NULL)
5607 added_arc->state_alts = 0;
5608 for (alt_state = ainsn->alt_states;
5609 alt_state != NULL;
5610 alt_state = alt_state->next_alt_state)
5612 state2 = alt_state->state;
5613 if (!intersected_state_reservs_p (state, state2))
5614 added_arc->state_alts++;
5618 else
5619 advance_cycle_ainsn = ainsn;
5621 /* Add transition to advance cycle. */
5622 state2 = state_shift (state);
5623 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5625 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5626 VLA_PTR_ADD (state_stack, state2);
5628 if (advance_cycle_ainsn == NULL)
5629 abort ();
5630 add_arc (state, state2, advance_cycle_ainsn, 1);
5632 VLA_PTR_DELETE (state_stack);
5635 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5636 static void
5637 form_arcs_marked_by_insn (state)
5638 state_t state;
5640 decl_t decl;
5641 arc_t arc;
5642 int i;
5644 for (i = 0; i < description->decls_num; i++)
5646 decl = description->decls [i];
5647 if (decl->mode == dm_insn_reserv)
5648 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5650 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5652 if (arc->insn == NULL)
5653 abort ();
5654 arc->next_arc_marked_by_insn
5655 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5656 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5660 /* The function creates composed state (see comments for IR) from
5661 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5662 same insn. If the composed state is not in STATE_STACK yet, it is
5663 popped to STATE_STACK. */
5664 static void
5665 create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5666 state_t original_state;
5667 arc_t arcs_marked_by_insn;
5668 vla_ptr_t *state_stack;
5670 state_t state;
5671 alt_state_t curr_alt_state;
5672 alt_state_t new_alt_state;
5673 arc_t curr_arc;
5674 arc_t next_arc;
5675 state_t state_in_table;
5676 state_t temp_state;
5677 alt_state_t canonical_alt_states_list;
5678 int alts_number;
5680 if (arcs_marked_by_insn == NULL)
5681 return;
5682 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5683 state = arcs_marked_by_insn->to_state;
5684 else
5686 if (!ndfa_flag)
5687 abort ();
5688 /* Create composed state. */
5689 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5690 curr_alt_state = NULL;
5691 for (curr_arc = arcs_marked_by_insn;
5692 curr_arc != NULL;
5693 curr_arc = curr_arc->next_arc_marked_by_insn)
5695 new_alt_state = get_free_alt_state ();
5696 new_alt_state->next_alt_state = curr_alt_state;
5697 new_alt_state->state = curr_arc->to_state;
5698 if (curr_arc->to_state->component_states != NULL)
5699 abort ();
5700 curr_alt_state = new_alt_state;
5702 /* There are not identical sets in the alt state list. */
5703 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5704 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5706 temp_state = state;
5707 state = canonical_alt_states_list->state;
5708 free_state (temp_state);
5710 else
5712 state->component_states = canonical_alt_states_list;
5713 state_in_table = insert_state (state);
5714 if (state_in_table != state)
5716 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5717 abort ();
5718 free_state (state);
5719 state = state_in_table;
5721 else
5723 if (state->it_was_placed_in_stack_for_DFA_forming)
5724 abort ();
5725 for (curr_alt_state = state->component_states;
5726 curr_alt_state != NULL;
5727 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5728 for (curr_arc = first_out_arc (curr_alt_state->state);
5729 curr_arc != NULL;
5730 curr_arc = next_out_arc (curr_arc))
5731 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5733 arcs_marked_by_insn->to_state = state;
5734 for (alts_number = 0,
5735 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5736 curr_arc != NULL;
5737 curr_arc = next_arc)
5739 next_arc = curr_arc->next_arc_marked_by_insn;
5740 remove_arc (original_state, curr_arc);
5741 alts_number++;
5743 arcs_marked_by_insn->state_alts = alts_number;
5746 if (!state->it_was_placed_in_stack_for_DFA_forming)
5748 state->it_was_placed_in_stack_for_DFA_forming = 1;
5749 VLA_PTR_ADD (*state_stack, state);
5753 /* The function transformes nondeterminstic AUTOMATON into
5754 deterministic. */
5755 static void
5756 NDFA_to_DFA (automaton)
5757 automaton_t automaton;
5759 state_t start_state;
5760 state_t state;
5761 decl_t decl;
5762 vla_ptr_t state_stack;
5763 int i;
5765 VLA_PTR_CREATE (state_stack, 150, "state stack");
5766 /* Create the start state (empty state). */
5767 start_state = automaton->start_state;
5768 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5769 VLA_PTR_ADD (state_stack, start_state);
5770 while (VLA_PTR_LENGTH (state_stack) != 0)
5772 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5773 VLA_PTR_SHORTEN (state_stack, 1);
5774 form_arcs_marked_by_insn (state);
5775 for (i = 0; i < description->decls_num; i++)
5777 decl = description->decls [i];
5778 if (decl->mode == dm_insn_reserv)
5779 create_composed_state
5780 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5781 &state_stack);
5784 VLA_PTR_DELETE (state_stack);
5787 /* The following variable value is current number (1, 2, ...) of passing
5788 graph of states. */
5789 static int curr_state_graph_pass_num;
5791 /* This recursive function passes all states achieved from START_STATE
5792 and applies APPLIED_FUNC to them. */
5793 static void
5794 pass_state_graph (start_state, applied_func)
5795 state_t start_state;
5796 void (*applied_func) PARAMS ((state_t state));
5798 arc_t arc;
5800 if (start_state->pass_num == curr_state_graph_pass_num)
5801 return;
5802 start_state->pass_num = curr_state_graph_pass_num;
5803 (*applied_func) (start_state);
5804 for (arc = first_out_arc (start_state);
5805 arc != NULL;
5806 arc = next_out_arc (arc))
5807 pass_state_graph (arc->to_state, applied_func);
5810 /* This recursive function passes all states of AUTOMATON and applies
5811 APPLIED_FUNC to them. */
5812 static void
5813 pass_states (automaton, applied_func)
5814 automaton_t automaton;
5815 void (*applied_func) PARAMS ((state_t state));
5817 curr_state_graph_pass_num++;
5818 pass_state_graph (automaton->start_state, applied_func);
5821 /* The function initializes code for passing of all states. */
5822 static void
5823 initiate_pass_states ()
5825 curr_state_graph_pass_num = 0;
5828 /* The following vla is used for storing pointers to all achieved
5829 states. */
5830 static vla_ptr_t all_achieved_states;
5832 /* This function is called by function pass_states to add an achieved
5833 STATE. */
5834 static void
5835 add_achieved_state (state)
5836 state_t state;
5838 VLA_PTR_ADD (all_achieved_states, state);
5841 /* The function sets up equivalence numbers of insns which mark all
5842 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5843 nonzero value) or by equiv_class_num_2 of the destination state.
5844 The function returns number of out arcs of STATE. */
5845 static int
5846 set_out_arc_insns_equiv_num (state, odd_iteration_flag)
5847 state_t state;
5848 int odd_iteration_flag;
5850 int state_out_arcs_num;
5851 arc_t arc;
5853 state_out_arcs_num = 0;
5854 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5856 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
5857 || arc->insn->insn_reserv_decl->state_alts != 0)
5858 abort ();
5859 state_out_arcs_num++;
5860 arc->insn->insn_reserv_decl->equiv_class_num
5861 = (odd_iteration_flag
5862 ? arc->to_state->equiv_class_num_1
5863 : arc->to_state->equiv_class_num_2);
5864 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
5865 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
5866 || arc->insn->insn_reserv_decl->state_alts <= 0)
5867 abort ();
5869 return state_out_arcs_num;
5872 /* The function clears equivalence numbers and alt_states in all insns
5873 which mark all out arcs of STATE. */
5874 static void
5875 clear_arc_insns_equiv_num (state)
5876 state_t state;
5878 arc_t arc;
5880 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5882 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5883 arc->insn->insn_reserv_decl->state_alts = 0;
5887 /* The function copies pointers to equivalent states from vla FROM
5888 into vla TO. */
5889 static void
5890 copy_equiv_class (to, from)
5891 vla_ptr_t *to;
5892 const vla_ptr_t *from;
5894 state_t *class_ptr;
5896 VLA_PTR_NULLIFY (*to);
5897 for (class_ptr = VLA_PTR_BEGIN (*from);
5898 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
5899 class_ptr++)
5900 VLA_PTR_ADD (*to, *class_ptr);
5903 /* The function returns nonzero value if STATE is not equivalent to
5904 another state from the same current partition on equivalence
5905 classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of
5906 output arcs. Iteration of making equivalence partition is defined
5907 by ODD_ITERATION_FLAG. */
5908 static int
5909 state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag)
5910 state_t state;
5911 int original_state_out_arcs_num;
5912 int odd_iteration_flag;
5914 arc_t arc;
5915 int state_out_arcs_num;
5917 state_out_arcs_num = 0;
5918 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5920 state_out_arcs_num++;
5921 if ((odd_iteration_flag
5922 ? arc->to_state->equiv_class_num_1
5923 : arc->to_state->equiv_class_num_2)
5924 != arc->insn->insn_reserv_decl->equiv_class_num
5925 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
5926 return 1;
5928 return state_out_arcs_num != original_state_out_arcs_num;
5931 /* The function makes initial partition of STATES on equivalent
5932 classes. */
5933 static state_t
5934 init_equiv_class (states, states_num)
5935 state_t *states;
5936 int states_num;
5938 state_t *state_ptr;
5939 state_t result_equiv_class;
5941 result_equiv_class = NULL;
5942 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
5944 (*state_ptr)->equiv_class_num_1 = 1;
5945 (*state_ptr)->next_equiv_class_state = result_equiv_class;
5946 result_equiv_class = *state_ptr;
5948 return result_equiv_class;
5951 /* The function processes equivalence class given by its pointer
5952 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
5953 are not equvalent states, the function partitions the class
5954 removing nonequivalent states and placing them in
5955 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5956 assigns it to the state equivalence number. If the class has been
5957 partitioned, the function returns nonzero value. */
5958 static int
5959 partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5960 next_iteration_classes, new_equiv_class_num_ptr)
5961 state_t *equiv_class_ptr;
5962 int odd_iteration_flag;
5963 vla_ptr_t *next_iteration_classes;
5964 int *new_equiv_class_num_ptr;
5966 state_t new_equiv_class;
5967 int partition_p;
5968 state_t first_state;
5969 state_t curr_state;
5970 state_t prev_state;
5971 state_t next_state;
5972 int out_arcs_num;
5974 partition_p = 0;
5975 if (*equiv_class_ptr == NULL)
5976 abort ();
5977 for (first_state = *equiv_class_ptr;
5978 first_state != NULL;
5979 first_state = new_equiv_class)
5981 new_equiv_class = NULL;
5982 if (first_state->next_equiv_class_state != NULL)
5984 /* There are more one states in the class equivalence. */
5985 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
5986 odd_iteration_flag);
5987 for (prev_state = first_state,
5988 curr_state = first_state->next_equiv_class_state;
5989 curr_state != NULL;
5990 curr_state = next_state)
5992 next_state = curr_state->next_equiv_class_state;
5993 if (state_is_differed (curr_state, out_arcs_num,
5994 odd_iteration_flag))
5996 /* Remove curr state from the class equivalence. */
5997 prev_state->next_equiv_class_state = next_state;
5998 /* Add curr state to the new class equivalence. */
5999 curr_state->next_equiv_class_state = new_equiv_class;
6000 if (new_equiv_class == NULL)
6001 (*new_equiv_class_num_ptr)++;
6002 if (odd_iteration_flag)
6003 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6004 else
6005 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6006 new_equiv_class = curr_state;
6007 partition_p = 1;
6009 else
6010 prev_state = curr_state;
6012 clear_arc_insns_equiv_num (first_state);
6014 if (new_equiv_class != NULL)
6015 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
6017 return partition_p;
6020 /* The function finds equivalent states of AUTOMATON. */
6021 static void
6022 evaluate_equiv_classes (automaton, equiv_classes)
6023 automaton_t automaton;
6024 vla_ptr_t *equiv_classes;
6026 state_t new_equiv_class;
6027 int new_equiv_class_num;
6028 int odd_iteration_flag;
6029 int finish_flag;
6030 vla_ptr_t next_iteration_classes;
6031 state_t *equiv_class_ptr;
6032 state_t *state_ptr;
6034 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6035 pass_states (automaton, add_achieved_state);
6036 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6037 VLA_PTR_LENGTH (all_achieved_states));
6038 odd_iteration_flag = 0;
6039 new_equiv_class_num = 1;
6040 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6041 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6044 odd_iteration_flag = !odd_iteration_flag;
6045 finish_flag = 1;
6046 copy_equiv_class (equiv_classes, &next_iteration_classes);
6047 /* Transfer equiv numbers for the next iteration. */
6048 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6049 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6050 state_ptr++)
6051 if (odd_iteration_flag)
6052 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6053 else
6054 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6055 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6056 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6057 equiv_class_ptr++)
6058 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6059 &next_iteration_classes,
6060 &new_equiv_class_num))
6061 finish_flag = 0;
6063 while (!finish_flag);
6064 VLA_PTR_DELETE (next_iteration_classes);
6065 VLA_PTR_DELETE (all_achieved_states);
6068 /* The function merges equivalent states of AUTOMATON. */
6069 static void
6070 merge_states (automaton, equiv_classes)
6071 automaton_t automaton;
6072 vla_ptr_t *equiv_classes;
6074 state_t *equiv_class_ptr;
6075 state_t curr_state;
6076 state_t new_state;
6077 state_t first_class_state;
6078 alt_state_t alt_states;
6079 alt_state_t new_alt_state;
6080 arc_t curr_arc;
6081 arc_t next_arc;
6083 /* Create states corresponding to equivalence classes containing two
6084 or more states. */
6085 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6086 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6087 equiv_class_ptr++)
6088 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6090 /* There are more one states in the class equivalence. */
6091 /* Create new compound state. */
6092 new_state = get_free_state (0, automaton);
6093 alt_states = NULL;
6094 first_class_state = *equiv_class_ptr;
6095 for (curr_state = first_class_state;
6096 curr_state != NULL;
6097 curr_state = curr_state->next_equiv_class_state)
6099 curr_state->equiv_class_state = new_state;
6100 new_alt_state = get_free_alt_state ();
6101 new_alt_state->state = curr_state;
6102 new_alt_state->next_sorted_alt_state = alt_states;
6103 alt_states = new_alt_state;
6105 new_state->component_states = alt_states;
6107 else
6108 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6109 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6110 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6111 equiv_class_ptr++)
6112 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6114 first_class_state = *equiv_class_ptr;
6115 /* Create new arcs output from the state corresponding to
6116 equiv class. */
6117 for (curr_arc = first_out_arc (first_class_state);
6118 curr_arc != NULL;
6119 curr_arc = next_out_arc (curr_arc))
6120 add_arc (first_class_state->equiv_class_state,
6121 curr_arc->to_state->equiv_class_state,
6122 curr_arc->insn, curr_arc->state_alts);
6123 /* Delete output arcs from states of given class equivalence. */
6124 for (curr_state = first_class_state;
6125 curr_state != NULL;
6126 curr_state = curr_state->next_equiv_class_state)
6128 if (automaton->start_state == curr_state)
6129 automaton->start_state = curr_state->equiv_class_state;
6130 /* Delete the state and its output arcs. */
6131 for (curr_arc = first_out_arc (curr_state);
6132 curr_arc != NULL;
6133 curr_arc = next_arc)
6135 next_arc = next_out_arc (curr_arc);
6136 free_arc (curr_arc);
6140 else
6142 /* Change `to_state' of arcs output from the state of given
6143 equivalence class. */
6144 for (curr_arc = first_out_arc (*equiv_class_ptr);
6145 curr_arc != NULL;
6146 curr_arc = next_out_arc (curr_arc))
6147 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6151 /* The function sets up new_cycle_p for states if there is arc to the
6152 state marked by advance_cycle_insn_decl. */
6153 static void
6154 set_new_cycle_flags (state)
6155 state_t state;
6157 arc_t arc;
6159 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6160 if (arc->insn->insn_reserv_decl
6161 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6162 arc->to_state->new_cycle_p = 1;
6165 /* The top level function for minimization of deterministic
6166 AUTOMATON. */
6167 static void
6168 minimize_DFA (automaton)
6169 automaton_t automaton;
6171 vla_ptr_t equiv_classes;
6173 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6174 evaluate_equiv_classes (automaton, &equiv_classes);
6175 merge_states (automaton, &equiv_classes);
6176 pass_states (automaton, set_new_cycle_flags);
6177 VLA_PTR_DELETE (equiv_classes);
6180 /* Values of two variables are counted number of states and arcs in an
6181 automaton. */
6182 static int curr_counted_states_num;
6183 static int curr_counted_arcs_num;
6185 /* The function is called by function `pass_states' to count states
6186 and arcs of an automaton. */
6187 static void
6188 incr_states_and_arcs_nums (state)
6189 state_t state;
6191 arc_t arc;
6193 curr_counted_states_num++;
6194 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6195 curr_counted_arcs_num++;
6198 /* The function counts states and arcs of AUTOMATON. */
6199 static void
6200 count_states_and_arcs (automaton, states_num, arcs_num)
6201 automaton_t automaton;
6202 int *states_num;
6203 int *arcs_num;
6205 curr_counted_states_num = 0;
6206 curr_counted_arcs_num = 0;
6207 pass_states (automaton, incr_states_and_arcs_nums);
6208 *states_num = curr_counted_states_num;
6209 *arcs_num = curr_counted_arcs_num;
6212 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6213 recognition after checking and simplifying IR of the
6214 description. */
6215 static void
6216 build_automaton (automaton)
6217 automaton_t automaton;
6219 int states_num;
6220 int arcs_num;
6222 ticker_on (&NDFA_time);
6223 make_automaton (automaton);
6224 ticker_off (&NDFA_time);
6225 count_states_and_arcs (automaton, &states_num, &arcs_num);
6226 automaton->NDFA_states_num = states_num;
6227 automaton->NDFA_arcs_num = arcs_num;
6228 ticker_on (&NDFA_to_DFA_time);
6229 NDFA_to_DFA (automaton);
6230 ticker_off (&NDFA_to_DFA_time);
6231 count_states_and_arcs (automaton, &states_num, &arcs_num);
6232 automaton->DFA_states_num = states_num;
6233 automaton->DFA_arcs_num = arcs_num;
6234 if (!no_minimization_flag)
6236 ticker_on (&minimize_time);
6237 minimize_DFA (automaton);
6238 ticker_off (&minimize_time);
6239 count_states_and_arcs (automaton, &states_num, &arcs_num);
6240 automaton->minimal_DFA_states_num = states_num;
6241 automaton->minimal_DFA_arcs_num = arcs_num;
6247 /* The page contains code for enumeration of all states of an automaton. */
6249 /* Variable used for enumeration of all states of an automaton. Its
6250 value is current number of automaton states. */
6251 static int curr_state_order_num;
6253 /* The function is called by function `pass_states' for enumerating
6254 states. */
6255 static void
6256 set_order_state_num (state)
6257 state_t state;
6259 state->order_state_num = curr_state_order_num;
6260 curr_state_order_num++;
6263 /* The function enumerates all states of AUTOMATON. */
6264 static void
6265 enumerate_states (automaton)
6266 automaton_t automaton;
6268 curr_state_order_num = 0;
6269 pass_states (automaton, set_order_state_num);
6270 automaton->achieved_states_num = curr_state_order_num;
6275 /* The page contains code for finding equivalent automaton insns
6276 (ainsns). */
6278 /* The function inserts AINSN into cyclic list
6279 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6280 static ainsn_t
6281 insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6282 ainsn_t ainsn;
6283 ainsn_t cyclic_equiv_class_insn_list;
6285 if (cyclic_equiv_class_insn_list == NULL)
6286 ainsn->next_equiv_class_insn = ainsn;
6287 else
6289 ainsn->next_equiv_class_insn
6290 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6291 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6293 return ainsn;
6296 /* The function deletes equiv_class_insn into cyclic list of
6297 equivalent ainsns. */
6298 static void
6299 delete_ainsn_from_equiv_class (equiv_class_insn)
6300 ainsn_t equiv_class_insn;
6302 ainsn_t curr_equiv_class_insn;
6303 ainsn_t prev_equiv_class_insn;
6305 prev_equiv_class_insn = equiv_class_insn;
6306 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6307 curr_equiv_class_insn != equiv_class_insn;
6308 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6309 prev_equiv_class_insn = curr_equiv_class_insn;
6310 if (prev_equiv_class_insn != equiv_class_insn)
6311 prev_equiv_class_insn->next_equiv_class_insn
6312 = equiv_class_insn->next_equiv_class_insn;
6315 /* The function processes AINSN of a state in order to find equivalent
6316 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6317 state. */
6318 static void
6319 process_insn_equiv_class (ainsn, insn_arcs_array)
6320 ainsn_t ainsn;
6321 arc_t *insn_arcs_array;
6323 ainsn_t next_insn;
6324 ainsn_t curr_insn;
6325 ainsn_t cyclic_insn_list;
6326 arc_t arc;
6328 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6329 abort ();
6330 curr_insn = ainsn;
6331 /* New class of ainsns which are not equivalent to given ainsn. */
6332 cyclic_insn_list = NULL;
6335 next_insn = curr_insn->next_equiv_class_insn;
6336 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6337 if (arc == NULL
6338 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6339 != arc->to_state))
6341 delete_ainsn_from_equiv_class (curr_insn);
6342 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6343 cyclic_insn_list);
6345 curr_insn = next_insn;
6347 while (curr_insn != ainsn);
6350 /* The function processes STATE in order to find equivalent ainsns. */
6351 static void
6352 process_state_for_insn_equiv_partition (state)
6353 state_t state;
6355 arc_t arc;
6356 arc_t *insn_arcs_array;
6357 int i;
6358 vla_ptr_t insn_arcs_vect;
6360 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6361 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6362 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6363 /* Process insns of the arcs. */
6364 for (i = 0; i < description->insns_num; i++)
6365 insn_arcs_array [i] = NULL;
6366 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6367 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6368 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6369 process_insn_equiv_class (arc->insn, insn_arcs_array);
6370 VLA_PTR_DELETE (insn_arcs_vect);
6373 /* The function searches for equivalent ainsns of AUTOMATON. */
6374 static void
6375 set_insn_equiv_classes (automaton)
6376 automaton_t automaton;
6378 ainsn_t ainsn;
6379 ainsn_t first_insn;
6380 ainsn_t curr_insn;
6381 ainsn_t cyclic_insn_list;
6382 ainsn_t insn_with_same_reservs;
6383 int equiv_classes_num;
6385 /* All insns are included in one equivalence class. */
6386 cyclic_insn_list = NULL;
6387 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6388 if (ainsn->first_insn_with_same_reservs)
6389 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6390 cyclic_insn_list);
6391 /* Process insns in order to make equivalence partition. */
6392 pass_states (automaton, process_state_for_insn_equiv_partition);
6393 /* Enumerate equiv classes. */
6394 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6395 /* Set undefined value. */
6396 ainsn->insn_equiv_class_num = -1;
6397 equiv_classes_num = 0;
6398 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6399 if (ainsn->insn_equiv_class_num < 0)
6401 first_insn = ainsn;
6402 if (!first_insn->first_insn_with_same_reservs)
6403 abort ();
6404 first_insn->first_ainsn_with_given_equialence_num = 1;
6405 curr_insn = first_insn;
6408 for (insn_with_same_reservs = curr_insn;
6409 insn_with_same_reservs != NULL;
6410 insn_with_same_reservs
6411 = insn_with_same_reservs->next_same_reservs_insn)
6412 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6413 curr_insn = curr_insn->next_equiv_class_insn;
6415 while (curr_insn != first_insn);
6416 equiv_classes_num++;
6418 automaton->insn_equiv_classes_num = equiv_classes_num;
6423 /* This page contains code for creating DFA(s) and calls functions
6424 building them. */
6427 /* The following value is used to prevent floating point overflow for
6428 estimating an automaton bound. The value should be less DBL_MAX on
6429 the host machine. We use here approximate minimum of maximal
6430 double floating point value required by ANSI C standard. It
6431 will work for non ANSI sun compiler too. */
6433 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6435 /* The function estimate size of the single DFA used by PHR (pipeline
6436 hazards recognizer). */
6437 static double
6438 estimate_one_automaton_bound ()
6440 decl_t decl;
6441 double one_automaton_estimation_bound;
6442 double root_value;
6443 int i;
6445 one_automaton_estimation_bound = 1.0;
6446 for (i = 0; i < description->decls_num; i++)
6448 decl = description->decls [i];
6449 if (decl->mode == dm_unit)
6451 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num + 1.0)
6452 / automata_num);
6453 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6454 > one_automaton_estimation_bound)
6455 one_automaton_estimation_bound *= root_value;
6458 return one_automaton_estimation_bound;
6461 /* The function compares unit declarations acoording to their maximal
6462 cycle in reservations. */
6463 static int
6464 compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6465 const void *unit_decl_1;
6466 const void *unit_decl_2;
6468 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6469 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6470 return 1;
6471 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6472 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6473 return 0;
6474 else
6475 return -1;
6478 /* The function makes heuristic assigning automata to units. Actually
6479 efficacy of the algorithm has been checked yet??? */
6480 static void
6481 units_to_automata_heuristic_distr ()
6483 double estimation_bound;
6484 decl_t decl;
6485 decl_t *unit_decl_ptr;
6486 int automaton_num;
6487 int rest_units_num;
6488 double bound_value;
6489 vla_ptr_t unit_decls;
6490 int i;
6492 if (description->units_num == 0)
6493 return;
6494 estimation_bound = estimate_one_automaton_bound ();
6495 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6496 for (i = 0; i < description->decls_num; i++)
6498 decl = description->decls [i];
6499 if (decl->mode == dm_unit)
6500 VLA_PTR_ADD (unit_decls, decl);
6502 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6503 sizeof (decl_t), compare_max_occ_cycle_nums);
6504 automaton_num = 0;
6505 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6506 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6507 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6508 for (unit_decl_ptr++;
6509 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6510 unit_decl_ptr++)
6512 rest_units_num
6513 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6514 if (automata_num - automaton_num - 1 > rest_units_num)
6515 abort ();
6516 if (automaton_num < automata_num - 1
6517 && ((automata_num - automaton_num - 1 == rest_units_num)
6518 || (bound_value
6519 > (estimation_bound
6520 / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6522 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6523 automaton_num++;
6525 else
6526 bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6527 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6529 if (automaton_num != automata_num - 1)
6530 abort ();
6531 VLA_PTR_DELETE (unit_decls);
6534 /* The functions creates automaton insns for each automata. Automaton
6535 insn is simply insn for given automaton which makes reservation
6536 only of units of the automaton. */
6537 static ainsn_t
6538 create_ainsns ()
6540 decl_t decl;
6541 ainsn_t first_ainsn;
6542 ainsn_t curr_ainsn;
6543 ainsn_t prev_ainsn;
6544 int i;
6546 first_ainsn = NULL;
6547 prev_ainsn = NULL;
6548 for (i = 0; i < description->decls_num; i++)
6550 decl = description->decls [i];
6551 if (decl->mode == dm_insn_reserv)
6553 curr_ainsn = create_node (sizeof (struct ainsn));
6554 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6555 curr_ainsn->important_p = FALSE;
6556 curr_ainsn->next_ainsn = NULL;
6557 if (prev_ainsn == NULL)
6558 first_ainsn = curr_ainsn;
6559 else
6560 prev_ainsn->next_ainsn = curr_ainsn;
6561 prev_ainsn = curr_ainsn;
6564 return first_ainsn;
6567 /* The function assigns automata to units according to constructions
6568 `define_automaton' in the description. */
6569 static void
6570 units_to_automata_distr ()
6572 decl_t decl;
6573 int i;
6575 for (i = 0; i < description->decls_num; i++)
6577 decl = description->decls [i];
6578 if (decl->mode == dm_unit)
6580 if (DECL_UNIT (decl)->automaton_decl == NULL
6581 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6582 == NULL))
6583 /* Distribute to the first automaton. */
6584 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6585 else
6586 DECL_UNIT (decl)->corresponding_automaton_num
6587 = (DECL_UNIT (decl)->automaton_decl
6588 ->corresponding_automaton->automaton_order_num);
6593 /* The function creates DFA(s) for fast pipeline hazards recognition
6594 after checking and simplifying IR of the description. */
6595 static void
6596 create_automata ()
6598 automaton_t curr_automaton;
6599 automaton_t prev_automaton;
6600 decl_t decl;
6601 int curr_automaton_num;
6602 int i;
6604 if (automata_num != 0)
6606 units_to_automata_heuristic_distr ();
6607 for (prev_automaton = NULL, curr_automaton_num = 0;
6608 curr_automaton_num < automata_num;
6609 curr_automaton_num++, prev_automaton = curr_automaton)
6611 curr_automaton = create_node (sizeof (struct automaton));
6612 curr_automaton->ainsn_list = create_ainsns ();
6613 curr_automaton->corresponding_automaton_decl = NULL;
6614 curr_automaton->next_automaton = NULL;
6615 curr_automaton->automaton_order_num = curr_automaton_num;
6616 if (prev_automaton == NULL)
6617 description->first_automaton = curr_automaton;
6618 else
6619 prev_automaton->next_automaton = curr_automaton;
6622 else
6624 curr_automaton_num = 0;
6625 prev_automaton = NULL;
6626 for (i = 0; i < description->decls_num; i++)
6628 decl = description->decls [i];
6629 if (decl->mode == dm_automaton
6630 && DECL_AUTOMATON (decl)->automaton_is_used)
6632 curr_automaton = create_node (sizeof (struct automaton));
6633 curr_automaton->ainsn_list = create_ainsns ();
6634 curr_automaton->corresponding_automaton_decl
6635 = DECL_AUTOMATON (decl);
6636 curr_automaton->next_automaton = NULL;
6637 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6638 curr_automaton->automaton_order_num = curr_automaton_num;
6639 if (prev_automaton == NULL)
6640 description->first_automaton = curr_automaton;
6641 else
6642 prev_automaton->next_automaton = curr_automaton;
6643 curr_automaton_num++;
6644 prev_automaton = curr_automaton;
6647 if (curr_automaton_num == 0)
6649 curr_automaton = create_node (sizeof (struct automaton));
6650 curr_automaton->ainsn_list = create_ainsns ();
6651 curr_automaton->corresponding_automaton_decl = NULL;
6652 curr_automaton->next_automaton = NULL;
6653 description->first_automaton = curr_automaton;
6655 units_to_automata_distr ();
6657 NDFA_time = create_ticker ();
6658 ticker_off (&NDFA_time);
6659 NDFA_to_DFA_time = create_ticker ();
6660 ticker_off (&NDFA_to_DFA_time);
6661 minimize_time = create_ticker ();
6662 ticker_off (&minimize_time);
6663 equiv_time = create_ticker ();
6664 ticker_off (&equiv_time);
6665 for (curr_automaton = description->first_automaton;
6666 curr_automaton != NULL;
6667 curr_automaton = curr_automaton->next_automaton)
6669 if (curr_automaton->corresponding_automaton_decl == NULL)
6670 fprintf (stderr, "Create anonymous automaton ...");
6671 else
6672 fprintf (stderr, "Create automaton `%s'...",
6673 curr_automaton->corresponding_automaton_decl->name);
6674 create_alt_states (curr_automaton);
6675 form_ainsn_with_same_reservs (curr_automaton);
6676 build_automaton (curr_automaton);
6677 enumerate_states (curr_automaton);
6678 ticker_on (&equiv_time);
6679 set_insn_equiv_classes (curr_automaton);
6680 ticker_off (&equiv_time);
6681 fprintf (stderr, "done\n");
6687 /* This page contains code for forming string representation of
6688 regexp. The representation is formed on IR obstack. So you should
6689 not work with IR obstack between regexp_representation and
6690 finish_regexp_representation calls. */
6692 /* This recursive function forms string representation of regexp
6693 (without tailing '\0'). */
6694 static void
6695 form_regexp (regexp)
6696 regexp_t regexp;
6698 int i;
6700 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6702 const char *name = (regexp->mode == rm_unit
6703 ? REGEXP_UNIT (regexp)->name
6704 : REGEXP_RESERV (regexp)->name);
6706 obstack_grow (&irp, name, strlen (name));
6708 else if (regexp->mode == rm_sequence)
6709 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6711 if (i != 0)
6712 obstack_1grow (&irp, ',');
6713 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6715 else if (regexp->mode == rm_allof)
6717 obstack_1grow (&irp, '(');
6718 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6720 if (i != 0)
6721 obstack_1grow (&irp, '+');
6722 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6723 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6724 obstack_1grow (&irp, '(');
6725 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6726 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6727 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6728 obstack_1grow (&irp, ')');
6730 obstack_1grow (&irp, ')');
6732 else if (regexp->mode == rm_oneof)
6733 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6735 if (i != 0)
6736 obstack_1grow (&irp, '|');
6737 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6738 obstack_1grow (&irp, '(');
6739 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6740 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6741 obstack_1grow (&irp, ')');
6743 else if (regexp->mode == rm_repeat)
6745 char digits [30];
6747 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6748 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6749 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6750 obstack_1grow (&irp, '(');
6751 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6752 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6753 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6754 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6755 obstack_1grow (&irp, ')');
6756 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6757 obstack_grow (&irp, digits, strlen (digits));
6759 else if (regexp->mode == rm_nothing)
6760 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6761 else
6762 abort ();
6765 /* The function returns string representation of REGEXP on IR
6766 obstack. */
6767 static const char *
6768 regexp_representation (regexp)
6769 regexp_t regexp;
6771 form_regexp (regexp);
6772 obstack_1grow (&irp, '\0');
6773 return obstack_base (&irp);
6776 /* The function frees memory allocated for last formed string
6777 representation of regexp. */
6778 static void
6779 finish_regexp_representation ()
6781 int length = obstack_object_size (&irp);
6783 obstack_blank_fast (&irp, -length);
6788 /* This page contains code for output PHR (pipeline hazards recognizer). */
6790 /* The function outputs minimal C type which is sufficient for
6791 representation numbers in range min_range_value and
6792 max_range_value. Because host machine and build machine may be
6793 different, we use here minimal values required by ANSI C standard
6794 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6795 approximation. */
6797 static void
6798 output_range_type (f, min_range_value, max_range_value)
6799 FILE *f;
6800 long int min_range_value;
6801 long int max_range_value;
6803 if (min_range_value >= 0 && max_range_value <= 255)
6804 fprintf (f, "unsigned char");
6805 else if (min_range_value >= -127 && max_range_value <= 127)
6806 fprintf (f, "signed char");
6807 else if (min_range_value >= 0 && max_range_value <= 65535)
6808 fprintf (f, "unsigned short");
6809 else if (min_range_value >= -32767 && max_range_value <= 32767)
6810 fprintf (f, "short");
6811 else
6812 fprintf (f, "int");
6815 /* The following macro value is used as value of member
6816 `longest_path_length' of state when we are processing path and the
6817 state on the path. */
6819 #define ON_THE_PATH -2
6821 /* The following recursive function searches for the length of the
6822 longest path starting from STATE which does not contain cycles and
6823 `cycle advance' arcs. */
6825 static int
6826 longest_path_length (state)
6827 state_t state;
6829 arc_t arc;
6830 int length, result;
6832 if (state->longest_path_length == ON_THE_PATH)
6833 /* We don't expect the path cycle here. Our graph may contain
6834 only cycles with one state on the path not containing `cycle
6835 advance' arcs -- see comment below. */
6836 abort ();
6837 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6838 /* We alreday visited the state. */
6839 return state->longest_path_length;
6841 result = 0;
6842 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6843 /* Ignore cycles containing one state and `cycle advance' arcs. */
6844 if (arc->to_state != state
6845 && (arc->insn->insn_reserv_decl
6846 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6848 length = longest_path_length (arc->to_state);
6849 if (length > result)
6850 result = length;
6852 state->longest_path_length = result + 1;
6853 return result;
6856 /* The following variable value is value of the corresponding global
6857 variable in the automaton based pipeline interface. */
6859 static int max_dfa_issue_rate;
6861 /* The following function processes the longest path length staring
6862 from STATE to find MAX_DFA_ISSUE_RATE. */
6864 static void
6865 process_state_longest_path_length (state)
6866 state_t state;
6868 int value;
6870 value = longest_path_length (state);
6871 if (value > max_dfa_issue_rate)
6872 max_dfa_issue_rate = value;
6875 /* The following macro value is name of the corresponding global
6876 variable in the automaton based pipeline interface. */
6878 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
6880 /* The following function calculates value of the the corresponding
6881 global variable and outputs its declaration. */
6883 static void
6884 output_dfa_max_issue_rate ()
6886 automaton_t automaton;
6888 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
6889 abort ();
6890 max_dfa_issue_rate = 0;
6891 for (automaton = description->first_automaton;
6892 automaton != NULL;
6893 automaton = automaton->next_automaton)
6894 pass_states (automaton, process_state_longest_path_length);
6895 fprintf (output_file, "\nint %s = %d;\n",
6896 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
6899 /* The function outputs all initialization values of VECT with length
6900 vect_length. */
6901 static void
6902 output_vect (vect, vect_length)
6903 vect_el_t *vect;
6904 int vect_length;
6906 int els_on_line;
6908 els_on_line = 1;
6909 if (vect_length == 0)
6910 fprintf (output_file,
6911 "0 /* This is dummy el because the vect is empty */");
6912 else
6916 fprintf (output_file, "%5ld", (long) *vect);
6917 vect_length--;
6918 if (els_on_line == 10)
6920 els_on_line = 0;
6921 fprintf (output_file, ",\n");
6923 else if (vect_length != 0)
6924 fprintf (output_file, ", ");
6925 els_on_line++;
6926 vect++;
6928 while (vect_length != 0);
6932 /* The following is name of the structure which represents DFA(s) for
6933 PHR. */
6934 #define CHIP_NAME "DFA_chip"
6936 /* The following is name of member which represents state of a DFA for
6937 PHR. */
6938 static void
6939 output_chip_member_name (f, automaton)
6940 FILE *f;
6941 automaton_t automaton;
6943 if (automaton->corresponding_automaton_decl == NULL)
6944 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6945 else
6946 fprintf (f, "%s_automaton_state",
6947 automaton->corresponding_automaton_decl->name);
6950 /* The following is name of temporary variable which stores state of a
6951 DFA for PHR. */
6952 static void
6953 output_temp_chip_member_name (f, automaton)
6954 FILE *f;
6955 automaton_t automaton;
6957 fprintf (f, "_");
6958 output_chip_member_name (f, automaton);
6961 /* This is name of macro value which is code of pseudo_insn
6962 representing advancing cpu cycle. Its value is used as internal
6963 code unknown insn. */
6964 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6966 /* Output name of translate vector for given automaton. */
6967 static void
6968 output_translate_vect_name (f, automaton)
6969 FILE *f;
6970 automaton_t automaton;
6972 if (automaton->corresponding_automaton_decl == NULL)
6973 fprintf (f, "translate_%d", automaton->automaton_order_num);
6974 else
6975 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6978 /* Output name for simple transition table representation. */
6979 static void
6980 output_trans_full_vect_name (f, automaton)
6981 FILE *f;
6982 automaton_t automaton;
6984 if (automaton->corresponding_automaton_decl == NULL)
6985 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6986 else
6987 fprintf (f, "%s_transitions",
6988 automaton->corresponding_automaton_decl->name);
6991 /* Output name of comb vector of the transition table for given
6992 automaton. */
6993 static void
6994 output_trans_comb_vect_name (f, automaton)
6995 FILE *f;
6996 automaton_t automaton;
6998 if (automaton->corresponding_automaton_decl == NULL)
6999 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7000 else
7001 fprintf (f, "%s_transitions",
7002 automaton->corresponding_automaton_decl->name);
7005 /* Output name of check vector of the transition table for given
7006 automaton. */
7007 static void
7008 output_trans_check_vect_name (f, automaton)
7009 FILE *f;
7010 automaton_t automaton;
7012 if (automaton->corresponding_automaton_decl == NULL)
7013 fprintf (f, "check_%d", automaton->automaton_order_num);
7014 else
7015 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7018 /* Output name of base vector of the transition table for given
7019 automaton. */
7020 static void
7021 output_trans_base_vect_name (f, automaton)
7022 FILE *f;
7023 automaton_t automaton;
7025 if (automaton->corresponding_automaton_decl == NULL)
7026 fprintf (f, "base_%d", automaton->automaton_order_num);
7027 else
7028 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7031 /* Output name for simple alternatives number representation. */
7032 static void
7033 output_state_alts_full_vect_name (f, automaton)
7034 FILE *f;
7035 automaton_t automaton;
7037 if (automaton->corresponding_automaton_decl == NULL)
7038 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7039 else
7040 fprintf (f, "%s_state_alts",
7041 automaton->corresponding_automaton_decl->name);
7044 /* Output name of comb vector of the alternatives number table for given
7045 automaton. */
7046 static void
7047 output_state_alts_comb_vect_name (f, automaton)
7048 FILE *f;
7049 automaton_t automaton;
7051 if (automaton->corresponding_automaton_decl == NULL)
7052 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7053 else
7054 fprintf (f, "%s_state_alts",
7055 automaton->corresponding_automaton_decl->name);
7058 /* Output name of check vector of the alternatives number table for given
7059 automaton. */
7060 static void
7061 output_state_alts_check_vect_name (f, automaton)
7062 FILE *f;
7063 automaton_t automaton;
7065 if (automaton->corresponding_automaton_decl == NULL)
7066 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7067 else
7068 fprintf (f, "%s_check_state_alts",
7069 automaton->corresponding_automaton_decl->name);
7072 /* Output name of base vector of the alternatives number table for given
7073 automaton. */
7074 static void
7075 output_state_alts_base_vect_name (f, automaton)
7076 FILE *f;
7077 automaton_t automaton;
7079 if (automaton->corresponding_automaton_decl == NULL)
7080 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7081 else
7082 fprintf (f, "%s_base_state_alts",
7083 automaton->corresponding_automaton_decl->name);
7086 /* Output name of simple min issue delay table representation. */
7087 static void
7088 output_min_issue_delay_vect_name (f, automaton)
7089 FILE *f;
7090 automaton_t automaton;
7092 if (automaton->corresponding_automaton_decl == NULL)
7093 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7094 else
7095 fprintf (f, "%s_min_issue_delay",
7096 automaton->corresponding_automaton_decl->name);
7099 /* Output name of deadlock vector for given automaton. */
7100 static void
7101 output_dead_lock_vect_name (f, automaton)
7102 FILE *f;
7103 automaton_t automaton;
7105 if (automaton->corresponding_automaton_decl == NULL)
7106 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7107 else
7108 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7111 /* Output name of reserved units table for AUTOMATON into file F. */
7112 static void
7113 output_reserved_units_table_name (f, automaton)
7114 FILE *f;
7115 automaton_t automaton;
7117 if (automaton->corresponding_automaton_decl == NULL)
7118 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7119 else
7120 fprintf (f, "%s_reserved_units",
7121 automaton->corresponding_automaton_decl->name);
7124 /* Name of the PHR interface macro. */
7125 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7127 /* Name of the PHR interface macro. */
7128 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7130 /* Names of an internal functions: */
7131 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7133 /* This is external type of DFA(s) state. */
7134 #define STATE_TYPE_NAME "state_t"
7136 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7138 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7140 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7142 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7144 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7146 /* Name of cache of insn dfa codes. */
7147 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7149 /* Name of length of cache of insn dfa codes. */
7150 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7152 /* Names of the PHR interface functions: */
7153 #define SIZE_FUNC_NAME "state_size"
7155 #define TRANSITION_FUNC_NAME "state_transition"
7157 #define STATE_ALTS_FUNC_NAME "state_alts"
7159 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7161 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7163 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7165 #define RESET_FUNC_NAME "state_reset"
7167 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7169 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7171 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7173 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7175 #define DFA_START_FUNC_NAME "dfa_start"
7177 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7179 /* Names of parameters of the PHR interface functions. */
7180 #define STATE_NAME "state"
7182 #define INSN_PARAMETER_NAME "insn"
7184 #define INSN2_PARAMETER_NAME "insn2"
7186 #define CHIP_PARAMETER_NAME "chip"
7188 #define FILE_PARAMETER_NAME "f"
7190 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7192 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7194 /* Names of the variables whose values are internal insn code of rtx
7195 insn. */
7196 #define INTERNAL_INSN_CODE_NAME "insn_code"
7198 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7200 /* Names of temporary variables in some functions. */
7201 #define TEMPORARY_VARIABLE_NAME "temp"
7203 #define I_VARIABLE_NAME "i"
7205 /* Name of result variable in some functions. */
7206 #define RESULT_VARIABLE_NAME "res"
7208 /* Name of function (attribute) to translate insn into number of insn
7209 alternatives reservation. */
7210 #define INSN_ALTS_FUNC_NAME "insn_alts"
7212 /* Name of function (attribute) to translate insn into internal insn
7213 code. */
7214 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7216 /* Name of function (attribute) to translate insn into internal insn
7217 code with caching. */
7218 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7220 /* Name of function (attribute) to translate insn into internal insn
7221 code. */
7222 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7224 /* Name of function (attribute) to translate insn into internal insn
7225 code. */
7226 #define BYPASS_P_FUNC_NAME "bypass_p"
7228 /* Output C type which is used for representation of codes of states
7229 of AUTOMATON. */
7230 static void
7231 output_state_member_type (f, automaton)
7232 FILE *f;
7233 automaton_t automaton;
7235 output_range_type (f, 0, automaton->achieved_states_num);
7238 /* Output definition of the structure representing current DFA(s)
7239 state(s). */
7240 static void
7241 output_chip_definitions ()
7243 automaton_t automaton;
7245 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7246 for (automaton = description->first_automaton;
7247 automaton != NULL;
7248 automaton = automaton->next_automaton)
7250 fprintf (output_file, " ");
7251 output_state_member_type (output_file, automaton);
7252 fprintf (output_file, " ");
7253 output_chip_member_name (output_file, automaton);
7254 fprintf (output_file, ";\n");
7256 fprintf (output_file, "};\n\n");
7257 #if 0
7258 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7259 #endif
7263 /* The function outputs translate vector of internal insn code into
7264 insn equivalence class number. The equivalence class number is
7265 used to access to table and vectors reprewsenting DFA(s). */
7266 static void
7267 output_translate_vect (automaton)
7268 automaton_t automaton;
7270 ainsn_t ainsn;
7271 int insn_value;
7272 vla_hwint_t translate_vect;
7274 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7275 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7276 for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
7277 /* Undefined value */
7278 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7279 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7280 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7281 = ainsn->insn_equiv_class_num;
7282 fprintf (output_file,
7283 "/* Vector translating external insn codes to internal ones.*/\n");
7284 fprintf (output_file, "static const ");
7285 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7286 fprintf (output_file, " ");
7287 output_translate_vect_name (output_file, automaton);
7288 fprintf (output_file, "[] = {\n");
7289 output_vect (VLA_HWINT_BEGIN (translate_vect),
7290 VLA_HWINT_LENGTH (translate_vect));
7291 fprintf (output_file, "};\n\n");
7292 VLA_HWINT_DELETE (translate_vect);
7295 /* The value in a table state x ainsn -> something which represents
7296 undefined value. */
7297 static int undefined_vect_el_value;
7299 /* The following function returns nonzero value if the best
7300 representation of the table is comb vector. */
7301 static int
7302 comb_vect_p (tab)
7303 state_ainsn_table_t tab;
7305 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7306 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7309 /* The following function creates new table for AUTOMATON. */
7310 static state_ainsn_table_t
7311 create_state_ainsn_table (automaton)
7312 automaton_t automaton;
7314 state_ainsn_table_t tab;
7315 int full_vect_length;
7316 int i;
7318 tab = create_node (sizeof (struct state_ainsn_table));
7319 tab->automaton = automaton;
7320 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7321 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7322 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7323 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7324 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7325 full_vect_length = (automaton->insn_equiv_classes_num
7326 * automaton->achieved_states_num);
7327 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7328 for (i = 0; i < full_vect_length; i++)
7329 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7330 tab->min_base_vect_el_value = 0;
7331 tab->max_base_vect_el_value = 0;
7332 tab->min_comb_vect_el_value = 0;
7333 tab->max_comb_vect_el_value = 0;
7334 return tab;
7337 /* The following function outputs the best C representation of the
7338 table TAB of given TABLE_NAME. */
7339 static void
7340 output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7341 output_comb_vect_name_func,
7342 output_check_vect_name_func,
7343 output_base_vect_name_func)
7344 state_ainsn_table_t tab;
7345 char *table_name;
7346 void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7347 void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7348 void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7349 void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7351 if (!comb_vect_p (tab))
7353 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7354 fprintf (output_file, "static const ");
7355 output_range_type (output_file, tab->min_comb_vect_el_value,
7356 tab->max_comb_vect_el_value);
7357 fprintf (output_file, " ");
7358 (*output_full_vect_name_func) (output_file, tab->automaton);
7359 fprintf (output_file, "[] = {\n");
7360 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7361 VLA_HWINT_LENGTH (tab->full_vect));
7362 fprintf (output_file, "};\n\n");
7364 else
7366 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7367 fprintf (output_file, "static const ");
7368 output_range_type (output_file, tab->min_comb_vect_el_value,
7369 tab->max_comb_vect_el_value);
7370 fprintf (output_file, " ");
7371 (*output_comb_vect_name_func) (output_file, tab->automaton);
7372 fprintf (output_file, "[] = {\n");
7373 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7374 VLA_HWINT_LENGTH (tab->comb_vect));
7375 fprintf (output_file, "};\n\n");
7376 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7377 fprintf (output_file, "static const ");
7378 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7379 fprintf (output_file, " ");
7380 (*output_check_vect_name_func) (output_file, tab->automaton);
7381 fprintf (output_file, "[] = {\n");
7382 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7383 VLA_HWINT_LENGTH (tab->check_vect));
7384 fprintf (output_file, "};\n\n");
7385 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7386 fprintf (output_file, "static const ");
7387 output_range_type (output_file, tab->min_base_vect_el_value,
7388 tab->max_base_vect_el_value);
7389 fprintf (output_file, " ");
7390 (*output_base_vect_name_func) (output_file, tab->automaton);
7391 fprintf (output_file, "[] = {\n");
7392 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7393 VLA_HWINT_LENGTH (tab->base_vect));
7394 fprintf (output_file, "};\n\n");
7398 /* The following function adds vector with length VECT_LENGTH and
7399 elements pointed by VECT to table TAB as its line with number
7400 VECT_NUM. */
7401 static void
7402 add_vect (tab, vect_num, vect, vect_length)
7403 state_ainsn_table_t tab;
7404 int vect_num;
7405 vect_el_t *vect;
7406 int vect_length;
7408 int real_vect_length;
7409 vect_el_t *comb_vect_start;
7410 vect_el_t *check_vect_start;
7411 int comb_vect_index;
7412 int comb_vect_els_num;
7413 int vect_index;
7414 int first_unempty_vect_index;
7415 int additional_els_num;
7416 int no_state_value;
7417 vect_el_t vect_el;
7418 int i;
7420 if (vect_length == 0)
7421 abort ();
7422 real_vect_length = tab->automaton->insn_equiv_classes_num;
7423 if (vect [vect_length - 1] == undefined_vect_el_value)
7424 abort ();
7425 /* Form full vector in the table: */
7426 for (i = 0; i < vect_length; i++)
7427 VLA_HWINT (tab->full_vect,
7428 i + tab->automaton->insn_equiv_classes_num * vect_num)
7429 = vect [i];
7430 /* Form comb vector in the table: */
7431 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7432 abort ();
7433 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7434 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7435 for (first_unempty_vect_index = 0;
7436 first_unempty_vect_index < vect_length;
7437 first_unempty_vect_index++)
7438 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7439 break;
7440 /* Search for the place in comb vect for the inserted vect. */
7441 for (comb_vect_index = 0;
7442 comb_vect_index < comb_vect_els_num;
7443 comb_vect_index++)
7445 for (vect_index = first_unempty_vect_index;
7446 vect_index < vect_length
7447 && vect_index + comb_vect_index < comb_vect_els_num;
7448 vect_index++)
7449 if (vect [vect_index] != undefined_vect_el_value
7450 && (comb_vect_start [vect_index + comb_vect_index]
7451 != undefined_vect_el_value))
7452 break;
7453 if (vect_index >= vect_length
7454 || vect_index + comb_vect_index >= comb_vect_els_num)
7455 break;
7457 /* Slot was found. */
7458 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7459 if (additional_els_num < 0)
7460 additional_els_num = 0;
7461 /* Expand comb and check vectors. */
7462 vect_el = undefined_vect_el_value;
7463 no_state_value = tab->automaton->achieved_states_num;
7464 while (additional_els_num > 0)
7466 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7467 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7468 additional_els_num--;
7470 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7471 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7472 if (VLA_HWINT_LENGTH (tab->comb_vect)
7473 < (size_t) (comb_vect_index + real_vect_length))
7474 abort ();
7475 /* Fill comb and check vectors. */
7476 for (vect_index = 0; vect_index < vect_length; vect_index++)
7477 if (vect [vect_index] != undefined_vect_el_value)
7479 if (comb_vect_start [comb_vect_index + vect_index]
7480 != undefined_vect_el_value)
7481 abort ();
7482 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7483 if (vect [vect_index] < 0)
7484 abort ();
7485 if (tab->max_comb_vect_el_value < vect [vect_index])
7486 tab->max_comb_vect_el_value = vect [vect_index];
7487 if (tab->min_comb_vect_el_value > vect [vect_index])
7488 tab->min_comb_vect_el_value = vect [vect_index];
7489 check_vect_start [comb_vect_index + vect_index] = vect_num;
7491 if (tab->max_base_vect_el_value < comb_vect_index)
7492 tab->max_base_vect_el_value = comb_vect_index;
7493 if (tab->min_base_vect_el_value > comb_vect_index)
7494 tab->min_base_vect_el_value = comb_vect_index;
7495 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7498 /* Return number of out arcs of STATE. */
7499 static int
7500 out_state_arcs_num (state)
7501 state_t state;
7503 int result;
7504 arc_t arc;
7506 result = 0;
7507 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7509 if (arc->insn == NULL)
7510 abort ();
7511 if (arc->insn->first_ainsn_with_given_equialence_num)
7512 result++;
7514 return result;
7517 /* Compare number of possible transitions from the states. */
7518 static int
7519 compare_transition_els_num (state_ptr_1, state_ptr_2)
7520 const void *state_ptr_1;
7521 const void *state_ptr_2;
7523 int transition_els_num_1;
7524 int transition_els_num_2;
7526 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7527 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7528 if (transition_els_num_1 < transition_els_num_2)
7529 return 1;
7530 else if (transition_els_num_1 == transition_els_num_2)
7531 return 0;
7532 else
7533 return -1;
7536 /* The function adds element EL_VALUE to vector VECT for a table state
7537 x AINSN. */
7538 static void
7539 add_vect_el (vect, ainsn, el_value)
7540 vla_hwint_t *vect;
7541 ainsn_t ainsn;
7542 int el_value;
7544 int equiv_class_num;
7545 int vect_index;
7547 if (ainsn == NULL)
7548 abort ();
7549 equiv_class_num = ainsn->insn_equiv_class_num;
7550 for (vect_index = VLA_HWINT_LENGTH (*vect);
7551 vect_index <= equiv_class_num;
7552 vect_index++)
7553 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7554 VLA_HWINT (*vect, equiv_class_num) = el_value;
7557 /* This is for forming vector of states of an automaton. */
7558 static vla_ptr_t output_states_vect;
7560 /* The function is called by function pass_states. The function adds
7561 STATE to `output_states_vect'. */
7562 static void
7563 add_states_vect_el (state)
7564 state_t state;
7566 VLA_PTR_ADD (output_states_vect, state);
7569 /* Form and output vectors (comb, check, base or full vector)
7570 representing transition table of AUTOMATON. */
7571 static void
7572 output_trans_table (automaton)
7573 automaton_t automaton;
7575 state_t *state_ptr;
7576 arc_t arc;
7577 vla_hwint_t transition_vect;
7579 undefined_vect_el_value = automaton->achieved_states_num;
7580 automaton->trans_table = create_state_ainsn_table (automaton);
7581 /* Create vect of pointers to states ordered by num of transitions
7582 from the state (state with the maximum num is the first). */
7583 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7584 pass_states (automaton, add_states_vect_el);
7585 qsort (VLA_PTR_BEGIN (output_states_vect),
7586 VLA_PTR_LENGTH (output_states_vect),
7587 sizeof (state_t), compare_transition_els_num);
7588 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7589 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7590 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7591 state_ptr++)
7593 VLA_HWINT_NULLIFY (transition_vect);
7594 for (arc = first_out_arc (*state_ptr);
7595 arc != NULL;
7596 arc = next_out_arc (arc))
7598 if (arc->insn == NULL)
7599 abort ();
7600 if (arc->insn->first_ainsn_with_given_equialence_num)
7601 add_vect_el (&transition_vect, arc->insn,
7602 arc->to_state->order_state_num);
7604 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7605 VLA_HWINT_BEGIN (transition_vect),
7606 VLA_HWINT_LENGTH (transition_vect));
7608 output_state_ainsn_table
7609 (automaton->trans_table, (char *) "state transitions",
7610 output_trans_full_vect_name, output_trans_comb_vect_name,
7611 output_trans_check_vect_name, output_trans_base_vect_name);
7612 VLA_PTR_DELETE (output_states_vect);
7613 VLA_HWINT_DELETE (transition_vect);
7616 /* Form and output vectors (comb, check, base or simple vect)
7617 representing alts number table of AUTOMATON. The table is state x
7618 ainsn -> number of possible alternative reservations by the
7619 ainsn. */
7620 static void
7621 output_state_alts_table (automaton)
7622 automaton_t automaton;
7624 state_t *state_ptr;
7625 arc_t arc;
7626 vla_hwint_t state_alts_vect;
7628 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7629 automaton->state_alts_table = create_state_ainsn_table (automaton);
7630 /* Create vect of pointers to states ordered by num of transitions
7631 from the state (state with the maximum num is the first). */
7632 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7633 pass_states (automaton, add_states_vect_el);
7634 qsort (VLA_PTR_BEGIN (output_states_vect),
7635 VLA_PTR_LENGTH (output_states_vect),
7636 sizeof (state_t), compare_transition_els_num);
7637 /* Create base, comb, and check vectors. */
7638 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7639 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7640 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7641 state_ptr++)
7643 VLA_HWINT_NULLIFY (state_alts_vect);
7644 for (arc = first_out_arc (*state_ptr);
7645 arc != NULL;
7646 arc = next_out_arc (arc))
7648 if (arc->insn == NULL)
7649 abort ();
7650 if (arc->insn->first_ainsn_with_given_equialence_num)
7651 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7653 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7654 VLA_HWINT_BEGIN (state_alts_vect),
7655 VLA_HWINT_LENGTH (state_alts_vect));
7657 output_state_ainsn_table
7658 (automaton->state_alts_table, (char *) "state insn alternatives",
7659 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7660 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7661 VLA_PTR_DELETE (output_states_vect);
7662 VLA_HWINT_DELETE (state_alts_vect);
7665 /* The current number of passing states to find minimal issue delay
7666 value for an ainsn and state. */
7667 static int curr_state_pass_num;
7670 /* This recursive function passes states to find minimal issue delay
7671 value for AINSN. The state being visited is STATE. The function
7672 returns minimal issue delay value for AINSN in STATE or -1 if we
7673 enter into a loop. */
7674 static int
7675 min_issue_delay_pass_states (state, ainsn)
7676 state_t state;
7677 ainsn_t ainsn;
7679 arc_t arc;
7680 int min_insn_issue_delay, insn_issue_delay;
7682 if (state->state_pass_num == curr_state_pass_num
7683 || state->min_insn_issue_delay != -1)
7684 /* We've entered into a loop or already have the correct value for
7685 given state and ainsn. */
7686 return state->min_insn_issue_delay;
7687 state->state_pass_num = curr_state_pass_num;
7688 min_insn_issue_delay = -1;
7689 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7690 if (arc->insn == ainsn)
7692 min_insn_issue_delay = 0;
7693 break;
7695 else
7697 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7698 if (insn_issue_delay != -1)
7700 if (arc->insn->insn_reserv_decl
7701 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7702 insn_issue_delay++;
7703 if (min_insn_issue_delay == -1
7704 || min_insn_issue_delay > insn_issue_delay)
7706 min_insn_issue_delay = insn_issue_delay;
7707 if (insn_issue_delay == 0)
7708 break;
7712 return min_insn_issue_delay;
7715 /* The function searches minimal issue delay value for AINSN in STATE.
7716 The function can return negative value if we can not issue AINSN. We
7717 will report about it later. */
7718 static int
7719 min_issue_delay (state, ainsn)
7720 state_t state;
7721 ainsn_t ainsn;
7723 curr_state_pass_num++;
7724 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7725 return state->min_insn_issue_delay;
7728 /* The function initiates code for finding minimal issue delay values.
7729 It should be called only once. */
7730 static void
7731 initiate_min_issue_delay_pass_states ()
7733 curr_state_pass_num = 0;
7736 /* Form and output vectors representing minimal issue delay table of
7737 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7738 the ainsn. */
7739 static void
7740 output_min_issue_delay_table (automaton)
7741 automaton_t automaton;
7743 vla_hwint_t min_issue_delay_vect;
7744 vla_hwint_t compressed_min_issue_delay_vect;
7745 vect_el_t min_delay;
7746 ainsn_t ainsn;
7747 state_t *state_ptr;
7748 int i;
7750 /* Create vect of pointers to states ordered by num of transitions
7751 from the state (state with the maximum num is the first). */
7752 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7753 pass_states (automaton, add_states_vect_el);
7754 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7755 VLA_HWINT_EXPAND (min_issue_delay_vect,
7756 VLA_HWINT_LENGTH (output_states_vect)
7757 * automaton->insn_equiv_classes_num);
7758 for (i = 0;
7759 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7760 * automaton->insn_equiv_classes_num);
7761 i++)
7762 VLA_HWINT (min_issue_delay_vect, i) = 0;
7763 automaton->max_min_delay = 0;
7764 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7765 if (ainsn->first_ainsn_with_given_equialence_num)
7767 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7768 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7769 state_ptr++)
7770 (*state_ptr)->min_insn_issue_delay = -1;
7771 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7772 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7773 state_ptr++)
7775 min_delay = min_issue_delay (*state_ptr, ainsn);
7776 if (automaton->max_min_delay < min_delay)
7777 automaton->max_min_delay = min_delay;
7778 VLA_HWINT (min_issue_delay_vect,
7779 (*state_ptr)->order_state_num
7780 * automaton->insn_equiv_classes_num
7781 + ainsn->insn_equiv_class_num) = min_delay;
7784 fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
7785 fprintf (output_file, "static const ");
7786 output_range_type (output_file, 0, automaton->max_min_delay);
7787 fprintf (output_file, " ");
7788 output_min_issue_delay_vect_name (output_file, automaton);
7789 fprintf (output_file, "[] = {\n");
7790 /* Compress the vector */
7791 if (automaton->max_min_delay < 2)
7792 automaton->min_issue_delay_table_compression_factor = 8;
7793 else if (automaton->max_min_delay < 4)
7794 automaton->min_issue_delay_table_compression_factor = 4;
7795 else if (automaton->max_min_delay < 16)
7796 automaton->min_issue_delay_table_compression_factor = 2;
7797 else
7798 automaton->min_issue_delay_table_compression_factor = 1;
7799 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7800 "compressed min issue delay vector");
7801 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7802 (VLA_HWINT_LENGTH (min_issue_delay_vect)
7803 + automaton->min_issue_delay_table_compression_factor
7804 - 1)
7805 / automaton->min_issue_delay_table_compression_factor);
7806 for (i = 0;
7807 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7808 i++)
7809 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7810 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7811 VLA_HWINT (compressed_min_issue_delay_vect,
7812 i / automaton->min_issue_delay_table_compression_factor)
7813 |= (VLA_HWINT (min_issue_delay_vect, i)
7814 << (8 - (i % automaton->min_issue_delay_table_compression_factor
7815 + 1)
7816 * (8 / automaton->min_issue_delay_table_compression_factor)));
7817 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7818 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7819 fprintf (output_file, "};\n\n");
7820 VLA_PTR_DELETE (output_states_vect);
7821 VLA_HWINT_DELETE (min_issue_delay_vect);
7822 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7825 #ifndef NDEBUG
7826 /* Number of states which contains transition only by advancing cpu
7827 cycle. */
7828 static int locked_states_num;
7829 #endif
7831 /* Form and output vector representing the locked states of
7832 AUTOMATON. */
7833 static void
7834 output_dead_lock_vect (automaton)
7835 automaton_t automaton;
7837 state_t *state_ptr;
7838 arc_t arc;
7839 vla_hwint_t dead_lock_vect;
7841 /* Create vect of pointers to states ordered by num of
7842 transitions from the state (state with the maximum num is the
7843 first). */
7844 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7845 pass_states (automaton, add_states_vect_el);
7846 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7847 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7848 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7849 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7850 state_ptr++)
7852 arc = first_out_arc (*state_ptr);
7853 if (arc == NULL)
7854 abort ();
7855 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
7856 = (next_out_arc (arc) == NULL
7857 && (arc->insn->insn_reserv_decl
7858 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
7859 #ifndef NDEBUG
7860 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
7861 locked_states_num++;
7862 #endif
7864 fprintf (output_file, "/* Vector for locked state flags. */\n");
7865 fprintf (output_file, "static const ");
7866 output_range_type (output_file, 0, 1);
7867 fprintf (output_file, " ");
7868 output_dead_lock_vect_name (output_file, automaton);
7869 fprintf (output_file, "[] = {\n");
7870 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
7871 VLA_HWINT_LENGTH (dead_lock_vect));
7872 fprintf (output_file, "};\n\n");
7873 VLA_HWINT_DELETE (dead_lock_vect);
7874 VLA_PTR_DELETE (output_states_vect);
7877 /* Form and output vector representing reserved units of the states of
7878 AUTOMATON. */
7879 static void
7880 output_reserved_units_table (automaton)
7881 automaton_t automaton;
7883 state_t *curr_state_ptr;
7884 vla_hwint_t reserved_units_table;
7885 size_t state_byte_size;
7886 int i;
7888 /* Create vect of pointers to states. */
7889 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7890 pass_states (automaton, add_states_vect_el);
7891 /* Create vector. */
7892 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
7893 state_byte_size = (description->query_units_num + 7) / 8;
7894 VLA_HWINT_EXPAND (reserved_units_table,
7895 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7896 for (i = 0;
7897 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7898 i++)
7899 VLA_HWINT (reserved_units_table, i) = 0;
7900 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
7901 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7902 curr_state_ptr++)
7904 for (i = 0; i < description->units_num; i++)
7905 if (units_array [i]->query_p)
7907 if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i))
7908 VLA_HWINT (reserved_units_table,
7909 (*curr_state_ptr)->order_state_num * state_byte_size
7910 + units_array [i]->query_num / 8)
7911 += (1 << (units_array [i]->query_num % 8));
7914 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7915 fprintf (output_file, "static const ");
7916 output_range_type (output_file, 0, 255);
7917 fprintf (output_file, " ");
7918 output_reserved_units_table_name (output_file, automaton);
7919 fprintf (output_file, "[] = {\n");
7920 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
7921 VLA_HWINT_LENGTH (reserved_units_table));
7922 fprintf (output_file, "};\n\n");
7923 VLA_HWINT_DELETE (reserved_units_table);
7924 VLA_PTR_DELETE (output_states_vect);
7927 /* The function outputs all tables representing DFA(s) used for fast
7928 pipeline hazards recognition. */
7929 static void
7930 output_tables ()
7932 automaton_t automaton;
7934 #ifndef NDEBUG
7935 locked_states_num = 0;
7936 #endif
7937 initiate_min_issue_delay_pass_states ();
7938 for (automaton = description->first_automaton;
7939 automaton != NULL;
7940 automaton = automaton->next_automaton)
7942 output_translate_vect (automaton);
7943 output_trans_table (automaton);
7944 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
7945 output_state_alts_table (automaton);
7946 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7947 AUTOMATON_STATE_ALTS_MACRO_NAME);
7948 output_min_issue_delay_table (automaton);
7949 output_dead_lock_vect (automaton);
7950 if (no_minimization_flag)
7952 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
7953 output_reserved_units_table (automaton);
7954 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7955 CPU_UNITS_QUERY_MACRO_NAME);
7958 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7959 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7962 /* The function outputs definition and value of PHR interface variable
7963 `max_insn_queue_index'. Its value is not less than maximal queue
7964 length needed for the insn scheduler. */
7965 static void
7966 output_max_insn_queue_index_def ()
7968 int i, max, latency;
7969 decl_t decl;
7971 max = description->max_insn_reserv_cycles;
7972 for (i = 0; i < description->decls_num; i++)
7974 decl = description->decls [i];
7975 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7977 latency = DECL_INSN_RESERV (decl)->default_latency;
7978 if (latency > max)
7979 max = latency;
7981 else if (decl->mode == dm_bypass)
7983 latency = DECL_BYPASS (decl)->latency;
7984 if (latency > max)
7985 max = latency;
7988 for (i = 0; (1 << i) <= max; i++)
7990 if (i < 0)
7991 abort ();
7992 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
7996 /* The function outputs switch cases for insn reseravtions using
7997 function *output_automata_list_code. */
7998 static void
7999 output_insn_code_cases (output_automata_list_code)
8000 void (*output_automata_list_code) (automata_list_el_t);
8002 decl_t decl, decl2;
8003 int i, j;
8005 for (i = 0; i < description->decls_num; i++)
8007 decl = description->decls [i];
8008 if (decl->mode == dm_insn_reserv)
8009 DECL_INSN_RESERV (decl)->processed_p = FALSE;
8011 for (i = 0; i < description->decls_num; i++)
8013 decl = description->decls [i];
8014 if (decl->mode == dm_insn_reserv
8015 && !DECL_INSN_RESERV (decl)->processed_p)
8017 for (j = i; j < description->decls_num; j++)
8019 decl2 = description->decls [j];
8020 if (decl2->mode == dm_insn_reserv
8021 && (DECL_INSN_RESERV (decl2)->important_automata_list
8022 == DECL_INSN_RESERV (decl)->important_automata_list))
8024 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8025 fprintf (output_file, " case %d: /* %s */\n",
8026 DECL_INSN_RESERV (decl2)->insn_num,
8027 DECL_INSN_RESERV (decl2)->name);
8030 (*output_automata_list_code)
8031 (DECL_INSN_RESERV (decl)->important_automata_list);
8037 /* The function outputs a code for evaluation of a minimal delay of
8038 issue of insns which have reservations in given AUTOMATA_LIST. */
8039 static void
8040 output_automata_list_min_issue_delay_code (automata_list)
8041 automata_list_el_t automata_list;
8043 automata_list_el_t el;
8044 automaton_t automaton;
8046 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8048 automaton = el->automaton;
8049 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8050 output_min_issue_delay_vect_name (output_file, automaton);
8051 fprintf (output_file,
8052 (automaton->min_issue_delay_table_compression_factor != 1
8053 ? " [(" : " ["));
8054 output_translate_vect_name (output_file, automaton);
8055 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8056 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8057 output_chip_member_name (output_file, automaton);
8058 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8059 if (automaton->min_issue_delay_table_compression_factor == 1)
8060 fprintf (output_file, "];\n");
8061 else
8063 fprintf (output_file, ") / %d];\n",
8064 automaton->min_issue_delay_table_compression_factor);
8065 fprintf (output_file, " %s = (%s >> (8 - (",
8066 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8067 output_translate_vect_name (output_file, automaton);
8068 fprintf
8069 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8070 INTERNAL_INSN_CODE_NAME,
8071 automaton->min_issue_delay_table_compression_factor,
8072 8 / automaton->min_issue_delay_table_compression_factor,
8073 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8074 - 1);
8076 if (el == automata_list)
8077 fprintf (output_file, " %s = %s;\n",
8078 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8079 else
8081 fprintf (output_file, " if (%s > %s)\n",
8082 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8083 fprintf (output_file, " %s = %s;\n",
8084 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8087 fprintf (output_file, " break;\n\n");
8090 /* Output function `internal_min_issue_delay'. */
8091 static void
8092 output_internal_min_issue_delay_func ()
8094 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8095 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
8096 fprintf (output_file,
8097 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8098 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8099 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8100 CHIP_PARAMETER_NAME);
8101 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s;\n",
8102 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8103 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8104 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8105 fprintf (output_file,
8106 "\n default:\n %s = -1;\n break;\n }\n",
8107 RESULT_VARIABLE_NAME);
8108 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8109 fprintf (output_file, "}\n\n");
8112 /* The function outputs a code changing state after issue of insns
8113 which have reservations in given AUTOMATA_LIST. */
8114 static void
8115 output_automata_list_transition_code (automata_list)
8116 automata_list_el_t automata_list;
8118 automata_list_el_t el, next_el;
8120 fprintf (output_file, " {\n");
8121 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8122 for (el = automata_list;; el = next_el)
8124 next_el = el->next_automata_list_el;
8125 if (next_el == NULL)
8126 break;
8127 fprintf (output_file, " ");
8128 output_state_member_type (output_file, el->automaton);
8129 fprintf (output_file, " ");
8130 output_temp_chip_member_name (output_file, el->automaton);
8131 fprintf (output_file, ";\n");
8133 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8134 if (comb_vect_p (el->automaton->trans_table))
8136 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8137 output_trans_base_vect_name (output_file, el->automaton);
8138 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8139 output_chip_member_name (output_file, el->automaton);
8140 fprintf (output_file, "] + ");
8141 output_translate_vect_name (output_file, el->automaton);
8142 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8143 fprintf (output_file, " if (");
8144 output_trans_check_vect_name (output_file, el->automaton);
8145 fprintf (output_file, " [%s] != %s->",
8146 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8147 output_chip_member_name (output_file, el->automaton);
8148 fprintf (output_file, ")\n");
8149 fprintf (output_file, " return %s (%s, %s);\n",
8150 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8151 CHIP_PARAMETER_NAME);
8152 fprintf (output_file, " else\n");
8153 fprintf (output_file, " ");
8154 if (el->next_automata_list_el != NULL)
8155 output_temp_chip_member_name (output_file, el->automaton);
8156 else
8158 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8159 output_chip_member_name (output_file, el->automaton);
8161 fprintf (output_file, " = ");
8162 output_trans_comb_vect_name (output_file, el->automaton);
8163 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8165 else
8167 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8168 output_trans_full_vect_name (output_file, el->automaton);
8169 fprintf (output_file, " [");
8170 output_translate_vect_name (output_file, el->automaton);
8171 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8172 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8173 output_chip_member_name (output_file, el->automaton);
8174 fprintf (output_file, " * %d];\n",
8175 el->automaton->insn_equiv_classes_num);
8176 fprintf (output_file, " if (%s >= %d)\n",
8177 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8178 fprintf (output_file, " return %s (%s, %s);\n",
8179 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8180 CHIP_PARAMETER_NAME);
8181 fprintf (output_file, " else\n ");
8182 if (el->next_automata_list_el != NULL)
8183 output_temp_chip_member_name (output_file, el->automaton);
8184 else
8186 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8187 output_chip_member_name (output_file, el->automaton);
8189 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8191 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8192 for (el = automata_list;; el = next_el)
8194 next_el = el->next_automata_list_el;
8195 if (next_el == NULL)
8196 break;
8197 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8198 output_chip_member_name (output_file, el->automaton);
8199 fprintf (output_file, " = ");
8200 output_temp_chip_member_name (output_file, el->automaton);
8201 fprintf (output_file, ";\n");
8203 fprintf (output_file, " return -1;\n");
8204 fprintf (output_file, " }\n");
8207 /* Output function `internal_state_transition'. */
8208 static void
8209 output_internal_trans_func ()
8211 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8212 INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
8213 fprintf (output_file,
8214 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8215 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8216 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
8217 CHIP_NAME, CHIP_PARAMETER_NAME);
8218 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8219 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8220 output_insn_code_cases (output_automata_list_transition_code);
8221 fprintf (output_file, "\n default:\n return -1;\n }\n");
8222 fprintf (output_file, "}\n\n");
8225 /* Output code
8227 if (insn != 0)
8229 insn_code = dfa_insn_code (insn);
8230 if (insn_code > DFA__ADVANCE_CYCLE)
8231 return code;
8233 else
8234 insn_code = DFA__ADVANCE_CYCLE;
8236 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8237 code denotes CODE. */
8238 static void
8239 output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
8240 const char *insn_name;
8241 const char *insn_code_name;
8242 int code;
8244 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8245 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8246 DFA_INSN_CODE_FUNC_NAME, insn_name);
8247 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8248 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8249 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8250 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8254 /* The function outputs function `dfa_insn_code'. */
8255 static void
8256 output_dfa_insn_code_func ()
8258 fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n");
8259 fprintf (output_file, "static int %s PARAMS ((rtx));\n",
8260 DFA_INSN_CODE_FUNC_NAME);
8261 fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
8262 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
8263 fprintf (output_file, "{\n int %s;\n int %s;\n\n",
8264 INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
8265 fprintf (output_file, " if (INSN_UID (%s) >= %s)\n {\n",
8266 INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8267 fprintf (output_file, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
8268 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8269 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
8270 fprintf (output_file, " %s = xrealloc (%s, %s * sizeof (int));\n",
8271 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8272 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8273 fprintf (output_file,
8274 " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
8275 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8276 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8277 TEMPORARY_VARIABLE_NAME);
8278 fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
8279 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8280 INSN_PARAMETER_NAME);
8281 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8282 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8283 fprintf (output_file, " %s [INSN_UID (%s)] = %s;\n",
8284 DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME,
8285 INTERNAL_INSN_CODE_NAME);
8286 fprintf (output_file, " }\n return %s;\n}\n\n",
8287 INTERNAL_INSN_CODE_NAME);
8290 /* The function outputs PHR interface function `state_transition'. */
8291 static void
8292 output_trans_func ()
8294 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8295 TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8296 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8297 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8298 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8299 INTERNAL_INSN_CODE_NAME, -1);
8300 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8301 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8304 /* The function outputs a code for evaluation of alternative states
8305 number for insns which have reservations in given AUTOMATA_LIST. */
8306 static void
8307 output_automata_list_state_alts_code (automata_list)
8308 automata_list_el_t automata_list;
8310 automata_list_el_t el;
8311 automaton_t automaton;
8313 fprintf (output_file, " {\n");
8314 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8315 if (comb_vect_p (el->automaton->state_alts_table))
8317 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8318 break;
8320 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8322 automaton = el->automaton;
8323 if (comb_vect_p (automaton->state_alts_table))
8325 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8326 output_state_alts_base_vect_name (output_file, automaton);
8327 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8328 output_chip_member_name (output_file, automaton);
8329 fprintf (output_file, "] + ");
8330 output_translate_vect_name (output_file, automaton);
8331 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8332 fprintf (output_file, " if (");
8333 output_state_alts_check_vect_name (output_file, automaton);
8334 fprintf (output_file, " [%s] != %s->",
8335 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8336 output_chip_member_name (output_file, automaton);
8337 fprintf (output_file, ")\n");
8338 fprintf (output_file, " return 0;\n");
8339 fprintf (output_file, " else\n");
8340 fprintf (output_file,
8341 (el == automata_list
8342 ? " %s = " : " %s += "),
8343 RESULT_VARIABLE_NAME);
8344 output_state_alts_comb_vect_name (output_file, automaton);
8345 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8347 else
8349 fprintf (output_file,
8350 (el == automata_list
8351 ? "\n %s = " : " %s += "),
8352 RESULT_VARIABLE_NAME);
8353 output_state_alts_full_vect_name (output_file, automaton);
8354 fprintf (output_file, " [");
8355 output_translate_vect_name (output_file, automaton);
8356 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8357 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8358 output_chip_member_name (output_file, automaton);
8359 fprintf (output_file, " * %d];\n",
8360 automaton->insn_equiv_classes_num);
8363 fprintf (output_file, " break;\n }\n\n");
8366 /* Output function `internal_state_alts'. */
8367 static void
8368 output_internal_state_alts_func ()
8370 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8371 INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8372 fprintf (output_file,
8373 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8374 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8375 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8376 CHIP_PARAMETER_NAME);
8377 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8378 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8379 output_insn_code_cases (output_automata_list_state_alts_code);
8380 fprintf (output_file,
8381 "\n default:\n %s = 0;\n break;\n }\n",
8382 RESULT_VARIABLE_NAME);
8383 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8384 fprintf (output_file, "}\n\n");
8387 /* The function outputs PHR interface function `state_alts'. */
8388 static void
8389 output_state_alts_func ()
8391 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8392 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8393 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8394 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8395 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8396 INTERNAL_INSN_CODE_NAME, 0);
8397 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8398 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8401 /* Output function `min_issue_delay'. */
8402 static void
8403 output_min_issue_delay_func ()
8405 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8406 MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8407 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8408 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8409 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8410 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8411 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8412 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8413 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8414 fprintf (output_file, " }\n else\n %s = %s;\n",
8415 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8416 fprintf (output_file, "\n return %s (%s, %s);\n",
8417 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8418 STATE_NAME);
8419 fprintf (output_file, "}\n\n");
8422 /* Output function `internal_dead_lock'. */
8423 static void
8424 output_internal_dead_lock_func ()
8426 automaton_t automaton;
8428 fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8429 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8430 fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8431 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8432 CHIP_PARAMETER_NAME);
8433 fprintf (output_file, "{\n");
8434 for (automaton = description->first_automaton;
8435 automaton != NULL;
8436 automaton = automaton->next_automaton)
8438 fprintf (output_file, " if (");
8439 output_dead_lock_vect_name (output_file, automaton);
8440 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8441 output_chip_member_name (output_file, automaton);
8442 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8444 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8447 /* The function outputs PHR interface function `state_dead_lock_p'. */
8448 static void
8449 output_dead_lock_func ()
8451 fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8452 DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8453 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8454 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8457 /* Output function `internal_reset'. */
8458 static void
8459 output_internal_reset_func ()
8461 fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8462 INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8463 fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8464 INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8465 CHIP_NAME, CHIP_PARAMETER_NAME);
8466 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8467 CHIP_PARAMETER_NAME, CHIP_NAME);
8470 /* The function outputs PHR interface function `state_size'. */
8471 static void
8472 output_size_func ()
8474 fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8475 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8478 /* The function outputs PHR interface function `state_reset'. */
8479 static void
8480 output_reset_func ()
8482 fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8483 RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8484 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8485 STATE_NAME);
8488 /* Output function `min_insn_conflict_delay'. */
8489 static void
8490 output_min_insn_conflict_delay_func ()
8492 fprintf (output_file,
8493 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8494 MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8495 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8496 STATE_TYPE_NAME, STATE_NAME,
8497 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8498 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8499 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8500 INTERNAL_INSN2_CODE_NAME);
8501 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8502 INTERNAL_INSN_CODE_NAME, 0);
8503 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8504 INTERNAL_INSN2_CODE_NAME, 0);
8505 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8506 CHIP_NAME, STATE_NAME, CHIP_NAME);
8507 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8508 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8509 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8510 fprintf (output_file, " return %s (%s, &%s);\n",
8511 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8512 CHIP_NAME);
8513 fprintf (output_file, "}\n\n");
8516 /* Output function `internal_insn_latency'. */
8517 static void
8518 output_internal_insn_latency_func ()
8520 decl_t decl;
8521 struct bypass_decl *bypass;
8522 int i;
8524 fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8525 INTERNAL_INSN_LATENCY_FUNC_NAME);
8526 fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8527 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8528 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8529 INSN2_PARAMETER_NAME);
8530 fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
8531 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8532 fprintf (output_file,
8533 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
8534 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8535 fprintf (output_file, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8536 for (i = 0; i < description->decls_num; i++)
8538 decl = description->decls [i];
8539 if (decl->mode == dm_insn_reserv)
8541 fprintf (output_file, " case %d:\n",
8542 DECL_INSN_RESERV (decl)->insn_num);
8543 if (DECL_INSN_RESERV (decl)->bypass_list == NULL)
8544 fprintf (output_file, " return (%s != %s ? %d : 0);\n",
8545 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8546 DECL_INSN_RESERV (decl)->default_latency);
8547 else
8549 fprintf (output_file, " switch (%s)\n {\n",
8550 INTERNAL_INSN2_CODE_NAME);
8551 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8552 bypass != NULL;
8553 bypass = bypass->next)
8555 fprintf (output_file, " case %d:\n",
8556 bypass->in_insn_reserv->insn_num);
8557 if (bypass->bypass_guard_name == NULL)
8558 fprintf (output_file, " return %d;\n",
8559 bypass->latency);
8560 else
8561 fprintf (output_file,
8562 " return (%s (%s, %s) ? %d : %d);\n",
8563 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8564 INSN2_PARAMETER_NAME, bypass->latency,
8565 DECL_INSN_RESERV (decl)->default_latency);
8567 fprintf (output_file, " default:\n");
8568 fprintf (output_file,
8569 " return (%s != %s ? %d : 0);\n }\n",
8570 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8571 DECL_INSN_RESERV (decl)->default_latency);
8576 fprintf (output_file, " default:\n return 0;\n }\n}\n\n");
8579 /* The function outputs PHR interface function `insn_latency'. */
8580 static void
8581 output_insn_latency_func ()
8583 fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
8584 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8585 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8586 fprintf (output_file, "{\n int %s, %s;\n",
8587 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8588 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8589 INTERNAL_INSN_CODE_NAME, 0);
8590 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8591 INTERNAL_INSN2_CODE_NAME, 0);
8592 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8593 INTERNAL_INSN_LATENCY_FUNC_NAME,
8594 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8595 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8598 /* The function outputs PHR interface function `print_reservation'. */
8599 static void
8600 output_print_reservation_func ()
8602 decl_t decl;
8603 int i;
8605 fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
8606 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8607 INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
8608 INSN_PARAMETER_NAME);
8609 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8610 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8611 fprintf (output_file, " %s = %s (%s);\n",
8612 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8613 INSN_PARAMETER_NAME);
8614 fprintf (output_file, " if (%s > %s)\n",
8615 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8616 fprintf (output_file, " {\n fprintf (%s, \"%s\");\n",
8617 FILE_PARAMETER_NAME, NOTHING_NAME);
8618 fprintf (output_file, " return;\n }\n");
8619 fprintf (output_file, " }\n else\n");
8620 fprintf (output_file,
8621 " {\n fprintf (%s, \"%s\");\n return;\n }\n",
8622 FILE_PARAMETER_NAME, NOTHING_NAME);
8623 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8624 for (i = 0; i < description->decls_num; i++)
8626 decl = description->decls [i];
8627 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8629 fprintf (output_file,
8630 " case %d:\n", DECL_INSN_RESERV (decl)->insn_num);
8631 fprintf (output_file,
8632 " fprintf (%s, \"%s\");\n break;\n",
8633 FILE_PARAMETER_NAME,
8634 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8635 finish_regexp_representation ();
8638 fprintf (output_file, " default:\n fprintf (%s, \"%s\");\n }\n",
8639 FILE_PARAMETER_NAME, NOTHING_NAME);
8640 fprintf (output_file, "}\n\n");
8643 /* The following function is used to sort unit declaration by their
8644 names. */
8645 static int
8646 units_cmp (unit1, unit2)
8647 const void *unit1, *unit2;
8649 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8650 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8652 return strcmp (u1->name, u2->name);
8655 /* The following macro value is name of struct containing unit name
8656 and unit code. */
8657 #define NAME_CODE_STRUCT_NAME "name_code"
8659 /* The following macro value is name of table of struct name_code. */
8660 #define NAME_CODE_TABLE_NAME "name_code_table"
8662 /* The following macro values are member names for struct name_code. */
8663 #define NAME_MEMBER_NAME "name"
8664 #define CODE_MEMBER_NAME "code"
8666 /* The following macro values are local variable names for function
8667 `get_cpu_unit_code'. */
8668 #define CMP_VARIABLE_NAME "cmp"
8669 #define LOW_VARIABLE_NAME "l"
8670 #define MIDDLE_VARIABLE_NAME "m"
8671 #define HIGH_VARIABLE_NAME "h"
8673 /* The following function outputs function to obtain internal cpu unit
8674 code by the cpu unit name. */
8675 static void
8676 output_get_cpu_unit_code_func ()
8678 int i;
8679 unit_decl_t *units;
8681 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8682 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8683 CPU_UNIT_NAME_PARAMETER_NAME);
8684 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8685 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8686 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8687 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8688 fprintf (output_file, " static struct %s %s [] =\n {\n",
8689 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8690 units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
8691 * description->units_num);
8692 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8693 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8694 for (i = 0; i < description->units_num; i++)
8695 if (units [i]->query_p)
8696 fprintf (output_file, " {\"%s\", %d},\n",
8697 units[i]->name, units[i]->query_num);
8698 fprintf (output_file, " };\n\n");
8699 fprintf (output_file, " /* The following is binary search: */\n");
8700 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8701 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8702 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8703 fprintf (output_file, " while (%s <= %s)\n {\n",
8704 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8705 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8706 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8707 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8708 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8709 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8710 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8711 fprintf (output_file, " %s = %s - 1;\n",
8712 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8713 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8714 fprintf (output_file, " %s = %s + 1;\n",
8715 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8716 fprintf (output_file, " else\n");
8717 fprintf (output_file, " return %s [%s].%s;\n }\n",
8718 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8719 fprintf (output_file, " return -1;\n}\n\n");
8720 free (units);
8723 /* The following function outputs function to check reservation of cpu
8724 unit (its internal code will be passed as the function argument) in
8725 given cpu state. */
8726 static void
8727 output_cpu_unit_reservation_p ()
8729 automaton_t automaton;
8731 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8732 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8733 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8734 CPU_CODE_PARAMETER_NAME);
8735 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8736 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8737 description->query_units_num);
8738 for (automaton = description->first_automaton;
8739 automaton != NULL;
8740 automaton = automaton->next_automaton)
8742 fprintf (output_file, " if ((");
8743 output_reserved_units_table_name (output_file, automaton);
8744 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8745 output_chip_member_name (output_file, automaton);
8746 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8747 (description->query_units_num + 7) / 8,
8748 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8749 fprintf (output_file, " return 1;\n");
8751 fprintf (output_file, " return 0;\n}\n\n");
8754 /* The function outputs PHR interface function `dfa_start'. */
8755 static void
8756 output_dfa_start_func ()
8758 fprintf (output_file,
8759 "void\n%s ()\n{\n int %s;\n\n %s = get_max_uid ();\n",
8760 DFA_START_FUNC_NAME, I_VARIABLE_NAME,
8761 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8762 fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
8763 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8764 fprintf (output_file,
8765 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8766 I_VARIABLE_NAME, I_VARIABLE_NAME,
8767 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8768 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8771 /* The function outputs PHR interface function `dfa_finish'. */
8772 static void
8773 output_dfa_finish_func ()
8775 fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
8776 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8781 /* The page contains code for output description file (readable
8782 representation of original description and generated DFA(s). */
8784 /* The function outputs string representation of IR reservation. */
8785 static void
8786 output_regexp (regexp)
8787 regexp_t regexp;
8789 fprintf (output_description_file, "%s", regexp_representation (regexp));
8790 finish_regexp_representation ();
8793 /* Output names of units in LIST separated by comma. */
8794 static void
8795 output_unit_set_el_list (list)
8796 unit_set_el_t list;
8798 unit_set_el_t el;
8800 for (el = list; el != NULL; el = el->next_unit_set_el)
8802 if (el != list)
8803 fprintf (output_description_file, ",");
8804 fprintf (output_description_file, "%s", el->unit_decl->name);
8808 /* The function outputs string representation of IR define_reservation
8809 and define_insn_reservation. */
8810 static void
8811 output_description ()
8813 decl_t decl;
8814 int i;
8816 for (i = 0; i < description->decls_num; i++)
8818 decl = description->decls [i];
8819 if (decl->mode == dm_unit)
8821 if (DECL_UNIT (decl)->excl_list != NULL)
8823 fprintf (output_description_file, "unit %s exlusion_set: ",
8824 DECL_UNIT (decl)->name);
8825 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8826 fprintf (output_description_file, "\n");
8828 if (DECL_UNIT (decl)->presence_list != NULL)
8830 fprintf (output_description_file, "unit %s presence_set: ",
8831 DECL_UNIT (decl)->name);
8832 output_unit_set_el_list (DECL_UNIT (decl)->presence_list);
8833 fprintf (output_description_file, "\n");
8835 if (DECL_UNIT (decl)->absence_list != NULL)
8837 fprintf (output_description_file, "unit %s absence_set: ",
8838 DECL_UNIT (decl)->name);
8839 output_unit_set_el_list (DECL_UNIT (decl)->absence_list);
8840 fprintf (output_description_file, "\n");
8844 fprintf (output_description_file, "\n");
8845 for (i = 0; i < description->decls_num; i++)
8847 decl = description->decls [i];
8848 if (decl->mode == dm_reserv)
8850 fprintf (output_description_file, "reservation ");
8851 fprintf (output_description_file, DECL_RESERV (decl)->name);
8852 fprintf (output_description_file, ": ");
8853 output_regexp (DECL_RESERV (decl)->regexp);
8854 fprintf (output_description_file, "\n");
8856 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8858 fprintf (output_description_file, "insn reservation %s ",
8859 DECL_INSN_RESERV (decl)->name);
8860 print_rtl (output_description_file,
8861 DECL_INSN_RESERV (decl)->condexp);
8862 fprintf (output_description_file, ": ");
8863 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8864 fprintf (output_description_file, "\n");
8866 else if (decl->mode == dm_bypass)
8867 fprintf (output_description_file, "bypass %d %s %s\n",
8868 DECL_BYPASS (decl)->latency,
8869 DECL_BYPASS (decl)->out_insn_name,
8870 DECL_BYPASS (decl)->in_insn_name);
8872 fprintf (output_description_file, "\n\f\n");
8875 /* The function outputs name of AUTOMATON. */
8876 static void
8877 output_automaton_name (f, automaton)
8878 FILE *f;
8879 automaton_t automaton;
8881 if (automaton->corresponding_automaton_decl == NULL)
8882 fprintf (f, "#%d", automaton->automaton_order_num);
8883 else
8884 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8887 /* Maximal length of line for pretty printing into description
8888 file. */
8889 #define MAX_LINE_LENGTH 70
8891 /* The function outputs units name belonging to AUTOMATON. */
8892 static void
8893 output_automaton_units (automaton)
8894 automaton_t automaton;
8896 decl_t decl;
8897 char *name;
8898 int curr_line_length;
8899 int there_is_an_automaton_unit;
8900 int i;
8902 fprintf (output_description_file, "\n Coresponding units:\n");
8903 fprintf (output_description_file, " ");
8904 curr_line_length = 4;
8905 there_is_an_automaton_unit = 0;
8906 for (i = 0; i < description->decls_num; i++)
8908 decl = description->decls [i];
8909 if (decl->mode == dm_unit
8910 && (DECL_UNIT (decl)->corresponding_automaton_num
8911 == automaton->automaton_order_num))
8913 there_is_an_automaton_unit = 1;
8914 name = DECL_UNIT (decl)->name;
8915 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8917 curr_line_length = strlen (name) + 4;
8918 fprintf (output_description_file, "\n ");
8920 else
8922 curr_line_length += strlen (name) + 1;
8923 fprintf (output_description_file, " ");
8925 fprintf (output_description_file, name);
8928 if (!there_is_an_automaton_unit)
8929 fprintf (output_description_file, "<None>");
8930 fprintf (output_description_file, "\n\n");
8933 /* The following variable is used for forming array of all possible cpu unit
8934 reservations described by the current DFA state. */
8935 static vla_ptr_t state_reservs;
8937 /* The function forms `state_reservs' for STATE. */
8938 static void
8939 add_state_reservs (state)
8940 state_t state;
8942 alt_state_t curr_alt_state;
8943 reserv_sets_t reservs;
8945 if (state->component_states != NULL)
8946 for (curr_alt_state = state->component_states;
8947 curr_alt_state != NULL;
8948 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8949 add_state_reservs (curr_alt_state->state);
8950 else
8952 reservs = state->reservs;
8953 VLA_PTR_ADD (state_reservs, reservs);
8957 /* The function outputs readable represenatation of all out arcs of
8958 STATE. */
8959 static void
8960 output_state_arcs (state)
8961 state_t state;
8963 arc_t arc;
8964 ainsn_t ainsn;
8965 char *insn_name;
8966 int curr_line_length;
8968 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8970 ainsn = arc->insn;
8971 if (!ainsn->first_insn_with_same_reservs)
8972 abort ();
8973 fprintf (output_description_file, " ");
8974 curr_line_length = 7;
8975 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8978 insn_name = ainsn->insn_reserv_decl->name;
8979 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8981 if (ainsn != arc->insn)
8983 fprintf (output_description_file, ",\n ");
8984 curr_line_length = strlen (insn_name) + 6;
8986 else
8987 curr_line_length += strlen (insn_name);
8989 else
8991 curr_line_length += strlen (insn_name);
8992 if (ainsn != arc->insn)
8994 curr_line_length += 2;
8995 fprintf (output_description_file, ", ");
8998 fprintf (output_description_file, insn_name);
8999 ainsn = ainsn->next_same_reservs_insn;
9001 while (ainsn != NULL);
9002 fprintf (output_description_file, " %d (%d)\n",
9003 arc->to_state->order_state_num, arc->state_alts);
9005 fprintf (output_description_file, "\n");
9008 /* The following function is used for sorting possible cpu unit
9009 reservation of a DFA state. */
9010 static int
9011 state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
9012 const void *reservs_ptr_1;
9013 const void *reservs_ptr_2;
9015 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9016 *(reserv_sets_t *) reservs_ptr_2);
9019 /* The following function is used for sorting possible cpu unit
9020 reservation of a DFA state. */
9021 static void
9022 remove_state_duplicate_reservs ()
9024 reserv_sets_t *reservs_ptr;
9025 reserv_sets_t *last_formed_reservs_ptr;
9027 last_formed_reservs_ptr = NULL;
9028 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9029 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9030 reservs_ptr++)
9031 if (last_formed_reservs_ptr == NULL)
9032 last_formed_reservs_ptr = reservs_ptr;
9033 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9035 ++last_formed_reservs_ptr;
9036 *last_formed_reservs_ptr = *reservs_ptr;
9038 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9041 /* The following function output readable representation of DFA(s)
9042 state used for fast recognition of pipeline hazards. State is
9043 described by possible (current and scehduled) cpu unit
9044 reservations. */
9045 static void
9046 output_state (state)
9047 state_t state;
9049 reserv_sets_t *reservs_ptr;
9051 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9052 fprintf (output_description_file, " State #%d", state->order_state_num);
9053 fprintf (output_description_file,
9054 state->new_cycle_p ? " (new cycle)\n" : "\n");
9055 add_state_reservs (state);
9056 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9057 sizeof (reserv_sets_t), state_reservs_cmp);
9058 remove_state_duplicate_reservs ();
9059 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9060 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9061 reservs_ptr++)
9063 fprintf (output_description_file, " ");
9064 output_reserv_sets (output_description_file, *reservs_ptr);
9065 fprintf (output_description_file, "\n");
9067 fprintf (output_description_file, "\n");
9068 output_state_arcs (state);
9069 VLA_PTR_DELETE (state_reservs);
9072 /* The following function output readable representation of
9073 DFAs used for fast recognition of pipeline hazards. */
9074 static void
9075 output_automaton_descriptions ()
9077 automaton_t automaton;
9079 for (automaton = description->first_automaton;
9080 automaton != NULL;
9081 automaton = automaton->next_automaton)
9083 fprintf (output_description_file, "\nAutomaton ");
9084 output_automaton_name (output_description_file, automaton);
9085 fprintf (output_description_file, "\n");
9086 output_automaton_units (automaton);
9087 pass_states (automaton, output_state);
9093 /* The page contains top level function for generation DFA(s) used for
9094 PHR. */
9096 /* The function outputs statistics about work of different phases of
9097 DFA generator. */
9098 static void
9099 output_statistics (f)
9100 FILE *f;
9102 automaton_t automaton;
9103 #ifndef NDEBUG
9104 int transition_comb_vect_els = 0;
9105 int transition_full_vect_els = 0;
9106 int state_alts_comb_vect_els = 0;
9107 int state_alts_full_vect_els = 0;
9108 int min_issue_delay_vect_els = 0;
9109 #endif
9111 for (automaton = description->first_automaton;
9112 automaton != NULL;
9113 automaton = automaton->next_automaton)
9115 fprintf (f, "\nAutomaton ");
9116 output_automaton_name (f, automaton);
9117 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9118 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9119 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9120 automaton->DFA_states_num, automaton->DFA_arcs_num);
9121 if (!no_minimization_flag)
9122 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9123 automaton->minimal_DFA_states_num,
9124 automaton->minimal_DFA_arcs_num);
9125 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9126 description->insns_num, automaton->insn_equiv_classes_num);
9127 #ifndef NDEBUG
9128 fprintf
9129 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9130 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9131 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9132 (comb_vect_p (automaton->trans_table)
9133 ? "use comb vect" : "use simple vect"));
9134 fprintf
9135 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9136 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9137 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9138 (comb_vect_p (automaton->state_alts_table)
9139 ? "use comb vect" : "use simple vect"));
9140 fprintf
9141 (f, "%5ld min delay table els, compression factor %d\n",
9142 (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num,
9143 automaton->min_issue_delay_table_compression_factor);
9144 transition_comb_vect_els
9145 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9146 transition_full_vect_els
9147 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9148 state_alts_comb_vect_els
9149 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9150 state_alts_full_vect_els
9151 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9152 min_issue_delay_vect_els
9153 += automaton->DFA_states_num * automaton->insn_equiv_classes_num;
9154 #endif
9156 #ifndef NDEBUG
9157 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9158 allocated_states_num, allocated_arcs_num);
9159 fprintf (f, "%5d all allocated alternative states\n",
9160 allocated_alt_states_num);
9161 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9162 transition_comb_vect_els, transition_full_vect_els);
9163 fprintf
9164 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9165 state_alts_comb_vect_els, state_alts_full_vect_els);
9166 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9167 fprintf (f, "%5d locked states num\n", locked_states_num);
9168 #endif
9171 /* The function output times of work of different phases of DFA
9172 generator. */
9173 static void
9174 output_time_statistics (f)
9175 FILE *f;
9177 fprintf (f, "\n transformation: ");
9178 print_active_time (f, transform_time);
9179 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9180 print_active_time (f, NDFA_time);
9181 if (ndfa_flag)
9183 fprintf (f, ", NDFA -> DFA: ");
9184 print_active_time (f, NDFA_to_DFA_time);
9186 fprintf (f, "\n DFA minimization: ");
9187 print_active_time (f, minimize_time);
9188 fprintf (f, ", making insn equivalence: ");
9189 print_active_time (f, equiv_time);
9190 fprintf (f, "\n all automaton generation: ");
9191 print_active_time (f, automaton_generation_time);
9192 fprintf (f, ", output: ");
9193 print_active_time (f, output_time);
9194 fprintf (f, "\n");
9197 /* The function generates DFA (deterministic finate state automaton)
9198 for fast recognition of pipeline hazards. No errors during
9199 checking must be fixed before this function call. */
9200 static void
9201 generate ()
9203 automata_num = split_argument;
9204 if (description->units_num < automata_num)
9205 automata_num = description->units_num;
9206 initiate_states ();
9207 initiate_arcs ();
9208 initiate_automata_lists ();
9209 initiate_pass_states ();
9210 initiate_excl_sets ();
9211 initiate_presence_absence_sets ();
9212 automaton_generation_time = create_ticker ();
9213 create_automata ();
9214 ticker_off (&automaton_generation_time);
9219 /* The following function creates insn attribute whose values are
9220 number alternatives in insn reservations. */
9221 static void
9222 make_insn_alts_attr ()
9224 int i, insn_num;
9225 decl_t decl;
9226 rtx condexp;
9228 condexp = rtx_alloc (COND);
9229 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9230 XEXP (condexp, 1) = make_numeric_value (0);
9231 for (i = insn_num = 0; i < description->decls_num; i++)
9233 decl = description->decls [i];
9234 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9236 XVECEXP (condexp, 0, 2 * insn_num)
9237 = DECL_INSN_RESERV (decl)->condexp;
9238 XVECEXP (condexp, 0, 2 * insn_num + 1)
9239 = make_numeric_value
9240 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9241 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9242 ->transformed_regexp)->regexps_num);
9243 insn_num++;
9246 if (description->insns_num != insn_num + 1)
9247 abort ();
9248 make_internal_attr (attr_printf (sizeof ("*")
9249 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9250 "*%s", INSN_ALTS_FUNC_NAME),
9251 condexp, 0);
9256 /* The following function creates attribute which is order number of
9257 insn in pipeline hazard description translator. */
9258 static void
9259 make_internal_dfa_insn_code_attr ()
9261 int i, insn_num;
9262 decl_t decl;
9263 rtx condexp;
9265 condexp = rtx_alloc (COND);
9266 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9267 XEXP (condexp, 1)
9268 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9269 ->insn_num + 1);
9270 for (i = insn_num = 0; i < description->decls_num; i++)
9272 decl = description->decls [i];
9273 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9275 XVECEXP (condexp, 0, 2 * insn_num)
9276 = DECL_INSN_RESERV (decl)->condexp;
9277 XVECEXP (condexp, 0, 2 * insn_num + 1)
9278 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9279 insn_num++;
9282 if (description->insns_num != insn_num + 1)
9283 abort ();
9284 make_internal_attr
9285 (attr_printf (sizeof ("*")
9286 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9287 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9288 condexp, 0);
9293 /* The following function creates attribute which order number of insn
9294 in pipeline hazard description translator. */
9295 static void
9296 make_default_insn_latency_attr ()
9298 int i, insn_num;
9299 decl_t decl;
9300 rtx condexp;
9302 condexp = rtx_alloc (COND);
9303 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9304 XEXP (condexp, 1) = make_numeric_value (0);
9305 for (i = insn_num = 0; i < description->decls_num; i++)
9307 decl = description->decls [i];
9308 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9310 XVECEXP (condexp, 0, 2 * insn_num)
9311 = DECL_INSN_RESERV (decl)->condexp;
9312 XVECEXP (condexp, 0, 2 * insn_num + 1)
9313 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9314 insn_num++;
9317 if (description->insns_num != insn_num + 1)
9318 abort ();
9319 make_internal_attr (attr_printf (sizeof ("*")
9320 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9321 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9322 condexp, 0);
9327 /* The following function creates attribute which returns 1 if given
9328 output insn has bypassing and 0 otherwise. */
9329 static void
9330 make_bypass_attr ()
9332 int i, bypass_insn;
9333 int bypass_insns_num = 0;
9334 decl_t decl;
9335 rtx result_rtx;
9337 for (i = 0; i < description->decls_num; i++)
9339 decl = description->decls [i];
9340 if (decl->mode == dm_insn_reserv
9341 && DECL_INSN_RESERV (decl)->condexp != NULL
9342 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9343 bypass_insns_num++;
9345 if (bypass_insns_num == 0)
9346 result_rtx = make_numeric_value (0);
9347 else
9349 result_rtx = rtx_alloc (COND);
9350 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9351 XEXP (result_rtx, 1) = make_numeric_value (0);
9353 for (i = bypass_insn = 0; i < description->decls_num; i++)
9355 decl = description->decls [i];
9356 if (decl->mode == dm_insn_reserv
9357 && DECL_INSN_RESERV (decl)->condexp != NULL
9358 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9360 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9361 = DECL_INSN_RESERV (decl)->condexp;
9362 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9363 = make_numeric_value (1);
9364 bypass_insn++;
9368 make_internal_attr (attr_printf (sizeof ("*")
9369 + strlen (BYPASS_P_FUNC_NAME) + 1,
9370 "*%s", BYPASS_P_FUNC_NAME),
9371 result_rtx, 0);
9376 /* This page mainly contains top level functions of pipeline hazards
9377 description translator. */
9379 /* The following macro value is suffix of name of description file of
9380 pipeline hazards description translator. */
9381 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9383 /* The function returns suffix of given file name. The returned
9384 string can not be changed. */
9385 static const char *
9386 file_name_suffix (file_name)
9387 const char *file_name;
9389 const char *last_period;
9391 for (last_period = NULL; *file_name != '\0'; file_name++)
9392 if (*file_name == '.')
9393 last_period = file_name;
9394 return (last_period == NULL ? file_name : last_period);
9397 /* The function returns base name of given file name, i.e. pointer to
9398 first char after last `/' (or `\' for WIN32) in given file name,
9399 given file name itself if the directory name is absent. The
9400 returned string can not be changed. */
9401 static const char *
9402 base_file_name (file_name)
9403 const char *file_name;
9405 int directory_name_length;
9407 directory_name_length = strlen (file_name);
9408 #ifdef WIN32
9409 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9410 && file_name[directory_name_length] != '\\')
9411 #else
9412 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9413 #endif
9414 directory_name_length--;
9415 return file_name + directory_name_length + 1;
9418 /* The following is top level function to initialize the work of
9419 pipeline hazards description translator. */
9420 void
9421 initiate_automaton_gen (argc, argv)
9422 int argc;
9423 char **argv;
9425 const char *base_name;
9426 int i;
9428 ndfa_flag = 0;
9429 split_argument = 0; /* default value */
9430 no_minimization_flag = 0;
9431 time_flag = 0;
9432 v_flag = 0;
9433 w_flag = 0;
9434 for (i = 2; i < argc; i++)
9435 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9436 no_minimization_flag = 1;
9437 else if (strcmp (argv [i], TIME_OPTION) == 0)
9438 time_flag = 1;
9439 else if (strcmp (argv [i], V_OPTION) == 0)
9440 v_flag = 1;
9441 else if (strcmp (argv [i], W_OPTION) == 0)
9442 w_flag = 1;
9443 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9444 ndfa_flag = 1;
9445 else if (strcmp (argv [i], "-split") == 0)
9447 if (i + 1 >= argc)
9448 fatal ("-split has no argument.");
9449 fatal ("option `-split' has not been implemented yet\n");
9450 /* split_argument = atoi (argument_vect [i + 1]); */
9452 VLA_PTR_CREATE (decls, 150, "decls");
9453 /* Initialize IR storage. */
9454 obstack_init (&irp);
9455 initiate_automaton_decl_table ();
9456 initiate_insn_decl_table ();
9457 initiate_decl_table ();
9458 output_file = stdout;
9459 output_description_file = NULL;
9460 base_name = base_file_name (argv[1]);
9461 obstack_grow (&irp, base_name,
9462 strlen (base_name) - strlen (file_name_suffix (base_name)));
9463 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9464 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9465 obstack_1grow (&irp, '\0');
9466 output_description_file_name = obstack_base (&irp);
9467 obstack_finish (&irp);
9470 /* The following function checks existence at least one arc marked by
9471 each insn. */
9472 static void
9473 check_automata_insn_issues ()
9475 automaton_t automaton;
9476 ainsn_t ainsn, reserv_ainsn;
9478 for (automaton = description->first_automaton;
9479 automaton != NULL;
9480 automaton = automaton->next_automaton)
9482 for (ainsn = automaton->ainsn_list;
9483 ainsn != NULL;
9484 ainsn = ainsn->next_ainsn)
9485 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9487 for (reserv_ainsn = ainsn;
9488 reserv_ainsn != NULL;
9489 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9490 if (automaton->corresponding_automaton_decl != NULL)
9492 if (!w_flag)
9493 error ("Automaton `%s': Insn `%s' will never be issued",
9494 automaton->corresponding_automaton_decl->name,
9495 reserv_ainsn->insn_reserv_decl->name);
9496 else
9497 warning
9498 ("Automaton `%s': Insn `%s' will never be issued",
9499 automaton->corresponding_automaton_decl->name,
9500 reserv_ainsn->insn_reserv_decl->name);
9502 else
9504 if (!w_flag)
9505 error ("Insn `%s' will never be issued",
9506 reserv_ainsn->insn_reserv_decl->name);
9507 else
9508 warning ("Insn `%s' will never be issued",
9509 reserv_ainsn->insn_reserv_decl->name);
9515 /* The following vla is used for storing pointers to all achieved
9516 states. */
9517 static vla_ptr_t automaton_states;
9519 /* This function is called by function pass_states to add an achieved
9520 STATE. */
9521 static void
9522 add_automaton_state (state)
9523 state_t state;
9525 VLA_PTR_ADD (automaton_states, state);
9528 /* The following function forms list of important automata (whose
9529 states may be changed after the insn issue) for each insn. */
9530 static void
9531 form_important_insn_automata_lists ()
9533 automaton_t automaton;
9534 state_t *state_ptr;
9535 decl_t decl;
9536 ainsn_t ainsn;
9537 arc_t arc;
9538 int i;
9540 VLA_PTR_CREATE (automaton_states, 1500,
9541 "automaton states for forming important insn automata sets");
9542 /* Mark important ainsns. */
9543 for (automaton = description->first_automaton;
9544 automaton != NULL;
9545 automaton = automaton->next_automaton)
9547 VLA_PTR_NULLIFY (automaton_states);
9548 pass_states (automaton, add_automaton_state);
9549 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9550 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9551 state_ptr++)
9553 for (arc = first_out_arc (*state_ptr);
9554 arc != NULL;
9555 arc = next_out_arc (arc))
9556 if (arc->to_state != *state_ptr)
9558 if (!arc->insn->first_insn_with_same_reservs)
9559 abort ();
9560 for (ainsn = arc->insn;
9561 ainsn != NULL;
9562 ainsn = ainsn->next_same_reservs_insn)
9563 ainsn->important_p = TRUE;
9567 VLA_PTR_DELETE (automaton_states);
9568 /* Create automata sets for the insns. */
9569 for (i = 0; i < description->decls_num; i++)
9571 decl = description->decls [i];
9572 if (decl->mode == dm_insn_reserv)
9574 automata_list_start ();
9575 for (automaton = description->first_automaton;
9576 automaton != NULL;
9577 automaton = automaton->next_automaton)
9578 for (ainsn = automaton->ainsn_list;
9579 ainsn != NULL;
9580 ainsn = ainsn->next_ainsn)
9581 if (ainsn->important_p
9582 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9584 automata_list_add (automaton);
9585 break;
9587 DECL_INSN_RESERV (decl)->important_automata_list
9588 = automata_list_finish ();
9594 /* The following is top level function to generate automat(a,on) for
9595 fast recognition of pipeline hazards. */
9596 void
9597 expand_automata ()
9599 int i;
9601 description = create_node (sizeof (struct description)
9602 /* One entry for cycle advancing insn. */
9603 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9604 description->decls_num = VLA_PTR_LENGTH (decls);
9605 description->query_units_num = 0;
9606 for (i = 0; i < description->decls_num; i++)
9608 description->decls [i] = VLA_PTR (decls, i);
9609 if (description->decls [i]->mode == dm_unit
9610 && DECL_UNIT (description->decls [i])->query_p)
9611 DECL_UNIT (description->decls [i])->query_num
9612 = description->query_units_num++;
9614 all_time = create_ticker ();
9615 check_time = create_ticker ();
9616 fprintf (stderr, "Check description...");
9617 fflush (stderr);
9618 check_all_description ();
9619 fprintf (stderr, "done\n");
9620 ticker_off (&check_time);
9621 generation_time = create_ticker ();
9622 if (!have_error)
9624 transform_insn_regexps ();
9625 check_unit_distributions_to_automata ();
9627 if (!have_error)
9629 generate ();
9630 check_automata_insn_issues ();
9632 if (!have_error)
9634 form_important_insn_automata_lists ();
9635 fprintf (stderr, "Generation of attributes...");
9636 fflush (stderr);
9637 make_internal_dfa_insn_code_attr ();
9638 make_insn_alts_attr ();
9639 make_default_insn_latency_attr ();
9640 make_bypass_attr ();
9641 fprintf (stderr, "done\n");
9643 ticker_off (&generation_time);
9644 ticker_off (&all_time);
9645 fprintf (stderr, "All other genattrtab stuff...");
9646 fflush (stderr);
9649 /* The following is top level function to output PHR and to finish
9650 work with pipeline description translator. */
9651 void
9652 write_automata ()
9654 fprintf (stderr, "done\n");
9655 if (have_error)
9656 fatal ("Errors in DFA description");
9657 ticker_on (&all_time);
9658 output_time = create_ticker ();
9659 fprintf (stderr, "Forming and outputing automata tables...");
9660 fflush (stderr);
9661 output_dfa_max_issue_rate ();
9662 output_tables ();
9663 fprintf (stderr, "done\n");
9664 fprintf (stderr, "Output functions to work with automata...");
9665 fflush (stderr);
9666 output_chip_definitions ();
9667 output_max_insn_queue_index_def ();
9668 output_internal_min_issue_delay_func ();
9669 output_internal_trans_func ();
9670 /* Cache of insn dfa codes: */
9671 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9672 fprintf (output_file, "\nstatic int %s;\n\n",
9673 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9674 output_dfa_insn_code_func ();
9675 output_trans_func ();
9676 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9677 output_internal_state_alts_func ();
9678 output_state_alts_func ();
9679 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9680 AUTOMATON_STATE_ALTS_MACRO_NAME);
9681 output_min_issue_delay_func ();
9682 output_internal_dead_lock_func ();
9683 output_dead_lock_func ();
9684 output_size_func ();
9685 output_internal_reset_func ();
9686 output_reset_func ();
9687 output_min_insn_conflict_delay_func ();
9688 output_internal_insn_latency_func ();
9689 output_insn_latency_func ();
9690 output_print_reservation_func ();
9691 if (no_minimization_flag)
9693 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9694 output_get_cpu_unit_code_func ();
9695 output_cpu_unit_reservation_p ();
9696 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9697 CPU_UNITS_QUERY_MACRO_NAME);
9699 output_dfa_start_func ();
9700 output_dfa_finish_func ();
9701 fprintf (stderr, "done\n");
9702 if (v_flag)
9704 output_description_file = fopen (output_description_file_name, "w");
9705 if (output_description_file == NULL)
9707 perror (output_description_file_name);
9708 exit (FATAL_EXIT_CODE);
9710 fprintf (stderr, "Output automata description...");
9711 fflush (stderr);
9712 output_description ();
9713 output_automaton_descriptions ();
9714 fprintf (stderr, "done\n");
9715 output_statistics (output_description_file);
9717 output_statistics (stderr);
9718 ticker_off (&output_time);
9719 output_time_statistics (stderr);
9720 finish_states ();
9721 finish_arcs ();
9722 finish_automata_lists ();
9723 if (time_flag)
9725 fprintf (stderr, "Summary:\n");
9726 fprintf (stderr, " check time ");
9727 print_active_time (stderr, check_time);
9728 fprintf (stderr, ", generation time ");
9729 print_active_time (stderr, generation_time);
9730 fprintf (stderr, ", all time ");
9731 print_active_time (stderr, all_time);
9732 fprintf (stderr, "\n");
9734 /* Finish all work. */
9735 if (output_description_file != NULL)
9737 fflush (output_description_file);
9738 if (ferror (stdout) != 0)
9739 fatal ("Error in writing DFA description file %s",
9740 output_description_file_name);
9741 fclose (output_description_file);
9743 finish_automaton_decl_table ();
9744 finish_insn_decl_table ();
9745 finish_decl_table ();
9746 obstack_free (&irp, NULL);
9747 if (have_error && output_description_file != NULL)
9748 remove (output_description_file_name);