i386-protos.h (x86_emit_floatuns): Declare.
[official-gcc.git] / gcc / genautomata.c
blobbb1a9d9a6c66eabf844d5fe1a89b6d4b451f0903
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003 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 deterministically and
43 non-deterministically.
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', `final_presence_set',
52 `absence_set', and `final_absence_set').
54 5. No reverse automata are generated. Trace instruction scheduling
55 requires this. It can be easily added in the future if we
56 really need this.
58 6. Union of automaton states are not generated yet. It is planned
59 to be implemented. Such feature is needed to make more accurate
60 interlock insn scheduling to get state describing functional
61 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_final_presence_set', `gen_absence_set',
71 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
72 `gen_reserv', `gen_insn_reserv' are called from file
73 `genattrtab.c'. They transform RTL constructions describing
74 automata in .md file into internal representation convenient for
75 further processing.
77 The translator major function `expand_automata' processes the
78 description internal representation into finite state automaton.
79 It can be divided on:
81 o checking correctness of the automaton pipeline description
82 (major function is `check_all_description').
84 o generating automaton (automata) from the description (major
85 function is `make_automaton').
87 o optional transformation of nondeterministic finite state
88 automata into deterministic ones if the alternative operator
89 `|' is treated nondeterministically in the description (major
90 function is NDFA_to_DFA).
92 o optional minimization of the finite state automata by merging
93 equivalent automaton states (major function is `minimize_DFA').
95 o forming tables (some as comb vectors) and attributes
96 representing the automata (functions output_..._table).
98 Function `write_automata' outputs the created finite state
99 automaton as different tables and functions which works with the
100 automata to inquire automaton state and to change its state. These
101 function are used by gcc instruction scheduler and may be some
102 other gcc code. */
104 #include "bconfig.h"
105 #include "system.h"
106 #include "coretypes.h"
107 #include "tm.h"
108 #include "rtl.h"
109 #include "obstack.h"
110 #include "errors.h"
112 #include <math.h>
113 #include "hashtab.h"
114 #include "varray.h"
116 #ifndef CHAR_BIT
117 #define CHAR_BIT 8
118 #endif
120 #include "genattrtab.h"
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_pattern_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 pattern_set_el;
186 struct pattern_reserv;
187 struct state;
188 struct alt_state;
189 struct arc;
190 struct ainsn;
191 struct automaton;
192 struct state_ainsn_table;
194 /* The following typedefs are for brevity. */
195 typedef struct unit_decl *unit_decl_t;
196 typedef struct decl *decl_t;
197 typedef struct regexp *regexp_t;
198 typedef struct unit_set_el *unit_set_el_t;
199 typedef struct pattern_set_el *pattern_set_el_t;
200 typedef struct pattern_reserv *pattern_reserv_t;
201 typedef struct alt_state *alt_state_t;
202 typedef struct state *state_t;
203 typedef struct arc *arc_t;
204 typedef struct ainsn *ainsn_t;
205 typedef struct automaton *automaton_t;
206 typedef struct automata_list_el *automata_list_el_t;
207 typedef struct state_ainsn_table *state_ainsn_table_t;
210 /* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
211 gen_bypass, gen_excl_set, gen_presence_set, gen_final_presence_set,
212 gen_absence_set, gen_final_absence_set, gen_automaton,
213 gen_automata_option, gen_reserv, gen_insn_reserv,
214 initiate_automaton_gen, expand_automata, write_automata are
215 described on the file top because the functions are called from
216 function `main'. */
218 static void *create_node PARAMS ((size_t));
219 static void *copy_node PARAMS ((const void *, size_t));
220 static char *check_name PARAMS ((char *, pos_t));
221 static char *next_sep_el PARAMS ((char **, int, int));
222 static int n_sep_els PARAMS ((char *, int, int));
223 static char **get_str_vect PARAMS ((char *, int *, int, int));
224 static void gen_presence_absence_set PARAMS ((rtx, int, int));
225 static regexp_t gen_regexp_el PARAMS ((char *));
226 static regexp_t gen_regexp_repeat PARAMS ((char *));
227 static regexp_t gen_regexp_allof PARAMS ((char *));
228 static regexp_t gen_regexp_oneof PARAMS ((char *));
229 static regexp_t gen_regexp_sequence PARAMS ((char *));
230 static regexp_t gen_regexp PARAMS ((char *));
232 static unsigned string_hash PARAMS ((const char *));
233 static unsigned automaton_decl_hash PARAMS ((const void *));
234 static int automaton_decl_eq_p PARAMS ((const void *,
235 const void *));
236 static decl_t insert_automaton_decl PARAMS ((decl_t));
237 static decl_t find_automaton_decl PARAMS ((char *));
238 static void initiate_automaton_decl_table PARAMS ((void));
239 static void finish_automaton_decl_table PARAMS ((void));
241 static hashval_t insn_decl_hash PARAMS ((const void *));
242 static int insn_decl_eq_p PARAMS ((const void *,
243 const void *));
244 static decl_t insert_insn_decl PARAMS ((decl_t));
245 static decl_t find_insn_decl PARAMS ((char *));
246 static void initiate_insn_decl_table PARAMS ((void));
247 static void finish_insn_decl_table PARAMS ((void));
249 static hashval_t decl_hash PARAMS ((const void *));
250 static int decl_eq_p PARAMS ((const void *,
251 const void *));
252 static decl_t insert_decl PARAMS ((decl_t));
253 static decl_t find_decl PARAMS ((char *));
254 static void initiate_decl_table PARAMS ((void));
255 static void finish_decl_table PARAMS ((void));
257 static unit_set_el_t process_excls PARAMS ((char **, int, pos_t));
258 static void add_excls PARAMS ((unit_set_el_t, unit_set_el_t,
259 pos_t));
260 static unit_set_el_t process_presence_absence_names
261 PARAMS ((char **, int, pos_t,
262 int, int));
263 static pattern_set_el_t process_presence_absence_patterns
264 PARAMS ((char ***, int, pos_t,
265 int, int));
266 static void add_presence_absence PARAMS ((unit_set_el_t,
267 pattern_set_el_t,
268 pos_t, int, int));
269 static void process_decls PARAMS ((void));
270 static struct bypass_decl *find_bypass PARAMS ((struct bypass_decl *,
271 struct insn_reserv_decl *));
272 static void check_automaton_usage PARAMS ((void));
273 static regexp_t process_regexp PARAMS ((regexp_t));
274 static void process_regexp_decls PARAMS ((void));
275 static void check_usage PARAMS ((void));
276 static int loop_in_regexp PARAMS ((regexp_t, decl_t));
277 static void check_loops_in_regexps PARAMS ((void));
278 static void process_regexp_cycles PARAMS ((regexp_t, int, int,
279 int *, int *));
280 static void evaluate_max_reserv_cycles PARAMS ((void));
281 static void check_all_description PARAMS ((void));
283 static ticker_t create_ticker PARAMS ((void));
284 static void ticker_off PARAMS ((ticker_t *));
285 static void ticker_on PARAMS ((ticker_t *));
286 static int active_time PARAMS ((ticker_t));
287 static void print_active_time PARAMS ((FILE *, ticker_t));
289 static void add_advance_cycle_insn_decl PARAMS ((void));
291 static alt_state_t get_free_alt_state PARAMS ((void));
292 static void free_alt_state PARAMS ((alt_state_t));
293 static void free_alt_states PARAMS ((alt_state_t));
294 static int alt_state_cmp PARAMS ((const void *alt_state_ptr_1,
295 const void *alt_state_ptr_2));
296 static alt_state_t uniq_sort_alt_states PARAMS ((alt_state_t));
297 static int alt_states_eq PARAMS ((alt_state_t, alt_state_t));
298 static void initiate_alt_states PARAMS ((void));
299 static void finish_alt_states PARAMS ((void));
301 static reserv_sets_t alloc_empty_reserv_sets PARAMS ((void));
302 static unsigned reserv_sets_hash_value PARAMS ((reserv_sets_t));
303 static int reserv_sets_cmp PARAMS ((reserv_sets_t, reserv_sets_t));
304 static int reserv_sets_eq PARAMS ((reserv_sets_t, reserv_sets_t));
305 static void set_unit_reserv PARAMS ((reserv_sets_t, int, int));
306 static int test_unit_reserv PARAMS ((reserv_sets_t, int, int));
307 static int it_is_empty_reserv_sets PARAMS ((reserv_sets_t))
308 ATTRIBUTE_UNUSED;
309 static int reserv_sets_are_intersected PARAMS ((reserv_sets_t, reserv_sets_t));
310 static void reserv_sets_shift PARAMS ((reserv_sets_t, reserv_sets_t));
311 static void reserv_sets_or PARAMS ((reserv_sets_t, reserv_sets_t,
312 reserv_sets_t));
313 static void reserv_sets_and PARAMS ((reserv_sets_t, reserv_sets_t,
314 reserv_sets_t))
315 ATTRIBUTE_UNUSED;
316 static void output_cycle_reservs PARAMS ((FILE *, reserv_sets_t,
317 int, int));
318 static void output_reserv_sets PARAMS ((FILE *, reserv_sets_t));
319 static state_t get_free_state PARAMS ((int, automaton_t));
320 static void free_state PARAMS ((state_t));
321 static hashval_t state_hash PARAMS ((const void *));
322 static int state_eq_p PARAMS ((const void *, const void *));
323 static state_t insert_state PARAMS ((state_t));
324 static void set_state_reserv PARAMS ((state_t, int, int));
325 static int intersected_state_reservs_p PARAMS ((state_t, state_t));
326 static state_t states_union PARAMS ((state_t, state_t, reserv_sets_t));
327 static state_t state_shift PARAMS ((state_t, reserv_sets_t));
328 static void initiate_states PARAMS ((void));
329 static void finish_states PARAMS ((void));
331 static void free_arc PARAMS ((arc_t));
332 static void remove_arc PARAMS ((state_t, arc_t));
333 static arc_t find_arc PARAMS ((state_t, state_t, ainsn_t));
334 static arc_t add_arc PARAMS ((state_t, state_t, ainsn_t, int));
335 static arc_t first_out_arc PARAMS ((state_t));
336 static arc_t next_out_arc PARAMS ((arc_t));
337 static void initiate_arcs PARAMS ((void));
338 static void finish_arcs PARAMS ((void));
340 static automata_list_el_t get_free_automata_list_el PARAMS ((void));
341 static void free_automata_list_el PARAMS ((automata_list_el_t));
342 static void free_automata_list PARAMS ((automata_list_el_t));
343 static hashval_t automata_list_hash PARAMS ((const void *));
344 static int automata_list_eq_p PARAMS ((const void *, const void *));
345 static void initiate_automata_lists PARAMS ((void));
346 static void automata_list_start PARAMS ((void));
347 static void automata_list_add PARAMS ((automaton_t));
348 static automata_list_el_t automata_list_finish PARAMS ((void));
349 static void finish_automata_lists PARAMS ((void));
351 static void initiate_excl_sets PARAMS ((void));
352 static reserv_sets_t get_excl_set PARAMS ((reserv_sets_t));
354 static pattern_reserv_t form_reserv_sets_list PARAMS ((pattern_set_el_t));
355 static void initiate_presence_absence_pattern_sets PARAMS ((void));
356 static int check_presence_pattern_sets PARAMS ((reserv_sets_t,
357 reserv_sets_t, int));
358 static int check_absence_pattern_sets PARAMS ((reserv_sets_t, reserv_sets_t,
359 int));
361 static regexp_t copy_insn_regexp PARAMS ((regexp_t));
362 static regexp_t transform_1 PARAMS ((regexp_t));
363 static regexp_t transform_2 PARAMS ((regexp_t));
364 static regexp_t transform_3 PARAMS ((regexp_t));
365 static regexp_t regexp_transform_func
366 PARAMS ((regexp_t, regexp_t (*) (regexp_t)));
367 static regexp_t transform_regexp PARAMS ((regexp_t));
368 static void transform_insn_regexps PARAMS ((void));
370 static void check_unit_distribution_in_reserv PARAMS ((const char *, regexp_t,
371 regexp_t, int));
372 static void check_regexp_units_distribution PARAMS ((const char *, regexp_t));
373 static void check_unit_distributions_to_automata PARAMS ((void));
375 static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t,
376 int));
377 static void finish_forming_alt_state PARAMS ((alt_state_t,
378 automaton_t));
379 static void process_alts_for_forming_states PARAMS ((regexp_t,
380 automaton_t, int));
381 static void create_alt_states PARAMS ((automaton_t));
383 static void form_ainsn_with_same_reservs PARAMS ((automaton_t));
385 static reserv_sets_t form_reservs_matter PARAMS ((automaton_t));
386 static void make_automaton PARAMS ((automaton_t));
387 static void form_arcs_marked_by_insn PARAMS ((state_t));
388 static int create_composed_state PARAMS ((state_t, arc_t, vla_ptr_t *));
389 static void NDFA_to_DFA PARAMS ((automaton_t));
390 static void pass_state_graph PARAMS ((state_t, void (*) (state_t)));
391 static void pass_states PARAMS ((automaton_t,
392 void (*) (state_t)));
393 static void initiate_pass_states PARAMS ((void));
394 static void add_achieved_state PARAMS ((state_t));
395 static int set_out_arc_insns_equiv_num PARAMS ((state_t, int));
396 static void clear_arc_insns_equiv_num PARAMS ((state_t));
397 static void copy_equiv_class PARAMS ((vla_ptr_t *to,
398 const vla_ptr_t *from));
399 static int first_cycle_unit_presence PARAMS ((state_t, int));
400 static int state_is_differed PARAMS ((state_t, state_t, int, int));
401 static state_t init_equiv_class PARAMS ((state_t *states, int));
402 static int partition_equiv_class PARAMS ((state_t *, int,
403 vla_ptr_t *, int *));
404 static void evaluate_equiv_classes PARAMS ((automaton_t, vla_ptr_t *));
405 static void merge_states PARAMS ((automaton_t, vla_ptr_t *));
406 static void set_new_cycle_flags PARAMS ((state_t));
407 static void minimize_DFA PARAMS ((automaton_t));
408 static void incr_states_and_arcs_nums PARAMS ((state_t));
409 static void count_states_and_arcs PARAMS ((automaton_t, int *, int *));
410 static void build_automaton PARAMS ((automaton_t));
412 static void set_order_state_num PARAMS ((state_t));
413 static void enumerate_states PARAMS ((automaton_t));
415 static ainsn_t insert_ainsn_into_equiv_class PARAMS ((ainsn_t, ainsn_t));
416 static void delete_ainsn_from_equiv_class PARAMS ((ainsn_t));
417 static void process_insn_equiv_class PARAMS ((ainsn_t, arc_t *));
418 static void process_state_for_insn_equiv_partition PARAMS ((state_t));
419 static void set_insn_equiv_classes PARAMS ((automaton_t));
421 static double estimate_one_automaton_bound PARAMS ((void));
422 static int compare_max_occ_cycle_nums PARAMS ((const void *,
423 const void *));
424 static void units_to_automata_heuristic_distr PARAMS ((void));
425 static ainsn_t create_ainsns PARAMS ((void));
426 static void units_to_automata_distr PARAMS ((void));
427 static void create_automata PARAMS ((void));
429 static void form_regexp PARAMS ((regexp_t));
430 static const char *regexp_representation PARAMS ((regexp_t));
431 static void finish_regexp_representation PARAMS ((void));
433 static void output_range_type PARAMS ((FILE *, long int, long int));
434 static int longest_path_length PARAMS ((state_t));
435 static void process_state_longest_path_length PARAMS ((state_t));
436 static void output_dfa_max_issue_rate PARAMS ((void));
437 static void output_vect PARAMS ((vect_el_t *, int));
438 static void output_chip_member_name PARAMS ((FILE *, automaton_t));
439 static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t));
440 static void output_translate_vect_name PARAMS ((FILE *, automaton_t));
441 static void output_trans_full_vect_name PARAMS ((FILE *, automaton_t));
442 static void output_trans_comb_vect_name PARAMS ((FILE *, automaton_t));
443 static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t));
444 static void output_trans_base_vect_name PARAMS ((FILE *, automaton_t));
445 static void output_state_alts_full_vect_name PARAMS ((FILE *, automaton_t));
446 static void output_state_alts_comb_vect_name PARAMS ((FILE *, automaton_t));
447 static void output_state_alts_check_vect_name PARAMS ((FILE *, automaton_t));
448 static void output_state_alts_base_vect_name PARAMS ((FILE *, automaton_t));
449 static void output_min_issue_delay_vect_name PARAMS ((FILE *, automaton_t));
450 static void output_dead_lock_vect_name PARAMS ((FILE *, automaton_t));
451 static void output_reserved_units_table_name PARAMS ((FILE *, automaton_t));
452 static void output_state_member_type PARAMS ((FILE *, automaton_t));
453 static void output_chip_definitions PARAMS ((void));
454 static void output_translate_vect PARAMS ((automaton_t));
455 static int comb_vect_p PARAMS ((state_ainsn_table_t));
456 static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t));
457 static void output_state_ainsn_table
458 PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
459 void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
460 void (*) (FILE *, automaton_t)));
461 static void add_vect PARAMS ((state_ainsn_table_t,
462 int, vect_el_t *, int));
463 static int out_state_arcs_num PARAMS ((state_t));
464 static int compare_transition_els_num PARAMS ((const void *, const void *));
465 static void add_vect_el PARAMS ((vla_hwint_t *,
466 ainsn_t, int));
467 static void add_states_vect_el PARAMS ((state_t));
468 static void output_trans_table PARAMS ((automaton_t));
469 static void output_state_alts_table PARAMS ((automaton_t));
470 static int min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
471 static int min_issue_delay PARAMS ((state_t, ainsn_t));
472 static void initiate_min_issue_delay_pass_states PARAMS ((void));
473 static void output_min_issue_delay_table PARAMS ((automaton_t));
474 static void output_dead_lock_vect PARAMS ((automaton_t));
475 static void output_reserved_units_table PARAMS ((automaton_t));
476 static void output_tables PARAMS ((void));
477 static void output_max_insn_queue_index_def PARAMS ((void));
478 static void output_insn_code_cases PARAMS ((void (*) (automata_list_el_t)));
479 static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
480 static void output_internal_min_issue_delay_func PARAMS ((void));
481 static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
482 static void output_internal_trans_func PARAMS ((void));
483 static void output_internal_insn_code_evaluation PARAMS ((const char *,
484 const char *, int));
485 static void output_dfa_insn_code_func PARAMS ((void));
486 static void output_trans_func PARAMS ((void));
487 static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
488 static void output_internal_state_alts_func PARAMS ((void));
489 static void output_state_alts_func PARAMS ((void));
490 static void output_min_issue_delay_func PARAMS ((void));
491 static void output_internal_dead_lock_func PARAMS ((void));
492 static void output_dead_lock_func PARAMS ((void));
493 static void output_internal_reset_func PARAMS ((void));
494 static void output_size_func PARAMS ((void));
495 static void output_reset_func PARAMS ((void));
496 static void output_min_insn_conflict_delay_func PARAMS ((void));
497 static void output_internal_insn_latency_func PARAMS ((void));
498 static void output_insn_latency_func PARAMS ((void));
499 static void output_print_reservation_func PARAMS ((void));
500 static int units_cmp PARAMS ((const void *,
501 const void *));
502 static void output_get_cpu_unit_code_func PARAMS ((void));
503 static void output_cpu_unit_reservation_p PARAMS ((void));
504 static void output_dfa_clean_insn_cache_func PARAMS ((void));
505 static void output_dfa_start_func PARAMS ((void));
506 static void output_dfa_finish_func PARAMS ((void));
508 static void output_regexp PARAMS ((regexp_t ));
509 static void output_unit_set_el_list PARAMS ((unit_set_el_t));
510 static void output_pattern_set_el_list PARAMS ((pattern_set_el_t));
511 static void output_description PARAMS ((void));
512 static void output_automaton_name PARAMS ((FILE *, automaton_t));
513 static void output_automaton_units PARAMS ((automaton_t));
514 static void add_state_reservs PARAMS ((state_t));
515 static void output_state_arcs PARAMS ((state_t));
516 static int state_reservs_cmp PARAMS ((const void *,
517 const void *));
518 static void remove_state_duplicate_reservs PARAMS ((void));
519 static void output_state PARAMS ((state_t));
520 static void output_automaton_descriptions PARAMS ((void));
521 static void output_statistics PARAMS ((FILE *));
522 static void output_time_statistics PARAMS ((FILE *));
523 static void generate PARAMS ((void));
525 static void make_insn_alts_attr PARAMS ((void));
526 static void make_internal_dfa_insn_code_attr PARAMS ((void));
527 static void make_default_insn_latency_attr PARAMS ((void));
528 static void make_bypass_attr PARAMS ((void));
529 static const char *file_name_suffix PARAMS ((const char *));
530 static const char *base_file_name PARAMS ((const char *));
531 static void check_automata_insn_issues PARAMS ((void));
532 static void add_automaton_state PARAMS ((state_t));
533 static void form_important_insn_automata_lists PARAMS ((void));
535 /* Undefined position. */
536 static pos_t no_pos = 0;
538 /* All IR is stored in the following obstack. */
539 static struct obstack irp;
543 /* This page contains code for work with variable length array (vla)
544 of pointers. We could be use only varray. But we add new lay
545 because we add elements very frequently and this could stress OS
546 allocator when varray is used only. */
548 /* Start work with vla. */
549 #define VLA_PTR_CREATE(vla, allocated_length, name) \
550 do \
552 vla_ptr_t *const vla_ptr = &(vla); \
554 VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\
555 vla_ptr->length = 0; \
557 while (0)
559 /* Finish work with the vla. */
560 #define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
562 /* Return start address of the vla. */
563 #define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
565 /* Address of the last element of the vla. Do not use side effects in
566 the macro argument. */
567 #define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \
568 (vla).length - 1))
569 /* Nullify the vla. */
570 #define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
572 /* Shorten the vla on given number bytes. */
573 #define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
575 /* Expand the vla on N elements. The values of new elements are
576 undefined. */
577 #define VLA_PTR_EXPAND(vla, n) \
578 do { \
579 vla_ptr_t *const expand_vla_ptr = &(vla); \
580 const size_t new_length = (n) + expand_vla_ptr->length; \
582 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
583 VARRAY_GROW (expand_vla_ptr->varray, \
584 (new_length - expand_vla_ptr->length < 128 \
585 ? expand_vla_ptr->length + 128 : new_length)); \
586 expand_vla_ptr->length = new_length; \
587 } while (0)
589 /* Add element to the end of the vla. */
590 #define VLA_PTR_ADD(vla, ptr) \
591 do { \
592 vla_ptr_t *const vla_ptr = &(vla); \
594 VLA_PTR_EXPAND (*vla_ptr, 1); \
595 VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\
596 } while (0)
598 /* Length of the vla in elements. */
599 #define VLA_PTR_LENGTH(vla) ((vla).length)
601 /* N-th element of the vla. */
602 #define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
605 /* The following macros are analogous to the previous ones but for
606 VLAs of HOST WIDE INTs. */
608 #define VLA_HWINT_CREATE(vla, allocated_length, name) \
609 do { \
610 vla_hwint_t *const vla_ptr = &(vla); \
612 VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name); \
613 vla_ptr->length = 0; \
614 } while (0)
616 #define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
618 #define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
620 #define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
622 #define VLA_HWINT_EXPAND(vla, n) \
623 do { \
624 vla_hwint_t *const expand_vla_ptr = &(vla); \
625 const size_t new_length = (n) + expand_vla_ptr->length; \
627 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
628 VARRAY_GROW (expand_vla_ptr->varray, \
629 (new_length - expand_vla_ptr->length < 128 \
630 ? expand_vla_ptr->length + 128 : new_length)); \
631 expand_vla_ptr->length = new_length; \
632 } while (0)
634 #define VLA_HWINT_ADD(vla, ptr) \
635 do { \
636 vla_hwint_t *const vla_ptr = &(vla); \
638 VLA_HWINT_EXPAND (*vla_ptr, 1); \
639 VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr); \
640 } while (0)
642 #define VLA_HWINT_LENGTH(vla) ((vla).length)
644 #define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
648 /* Options with the following names can be set up in automata_option
649 construction. Because the strings occur more one time we use the
650 macros. */
652 #define NO_MINIMIZATION_OPTION "-no-minimization"
654 #define TIME_OPTION "-time"
656 #define V_OPTION "-v"
658 #define W_OPTION "-w"
660 #define NDFA_OPTION "-ndfa"
662 /* The following flags are set up by function `initiate_automaton_gen'. */
664 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
665 static int ndfa_flag;
667 /* Do not make minimization of DFA (`-no-minimization'). */
668 static int no_minimization_flag;
670 /* Value of this variable is number of automata being generated. The
671 actual number of automata may be less this value if there is not
672 sufficient number of units. This value is defined by argument of
673 option `-split' or by constructions automaton if the value is zero
674 (it is default value of the argument). */
675 static int split_argument;
677 /* Flag of output time statistics (`-time'). */
678 static int time_flag;
680 /* Flag of creation of description file which contains description of
681 result automaton and statistics information (`-v'). */
682 static int v_flag;
684 /* Flag of generating warning instead of error for non-critical errors
685 (`-w'). */
686 static int w_flag;
689 /* Output file for pipeline hazard recognizer (PHR) being generated.
690 The value is NULL if the file is not defined. */
691 static FILE *output_file;
693 /* Description file of PHR. The value is NULL if the file is not
694 created. */
695 static FILE *output_description_file;
697 /* PHR description file name. */
698 static char *output_description_file_name;
700 /* Value of the following variable is node representing description
701 being processed. This is start point of IR. */
702 static struct description *description;
706 /* This page contains description of IR structure (nodes). */
708 enum decl_mode
710 dm_unit,
711 dm_bypass,
712 dm_automaton,
713 dm_excl,
714 dm_presence,
715 dm_absence,
716 dm_reserv,
717 dm_insn_reserv
720 /* This describes define_cpu_unit and define_query_cpu_unit (see file
721 rtl.def). */
722 struct unit_decl
724 char *name;
725 /* NULL if the automaton name is absent. */
726 char *automaton_name;
727 /* If the following value is not zero, the cpu unit reservation is
728 described in define_query_cpu_unit. */
729 char query_p;
731 /* The following fields are defined by checker. */
733 /* The following field value is nonzero if the unit is used in an
734 regexp. */
735 char unit_is_used;
737 /* The following field value is order number (0, 1, ...) of given
738 unit. */
739 int unit_num;
740 /* The following field value is corresponding declaration of
741 automaton which was given in description. If the field value is
742 NULL then automaton in the unit declaration was absent. */
743 struct automaton_decl *automaton_decl;
744 /* The following field value is maximal cycle number (1, ...) on
745 which given unit occurs in insns. Zero value means that given
746 unit is not used in insns. */
747 int max_occ_cycle_num;
748 /* The following field value is minimal cycle number (0, ...) on
749 which given unit occurs in insns. -1 value means that given
750 unit is not used in insns. */
751 int min_occ_cycle_num;
752 /* The following list contains units which conflict with given
753 unit. */
754 unit_set_el_t excl_list;
755 /* The following list contains patterns which are required to
756 reservation of given unit. */
757 pattern_set_el_t presence_list;
758 pattern_set_el_t final_presence_list;
759 /* The following list contains patterns which should be not present
760 in reservation for given unit. */
761 pattern_set_el_t absence_list;
762 pattern_set_el_t final_absence_list;
763 /* The following is used only when `query_p' has nonzero value.
764 This is query number for the unit. */
765 int query_num;
767 /* The following fields are defined by automaton generator. */
769 /* The following field value is number of the automaton to which
770 given unit belongs. */
771 int corresponding_automaton_num;
772 /* If the following value is not zero, the cpu unit is present in a
773 `exclusion_set' or in right part of a `presence_set',
774 `final_presence_set', `absence_set', and
775 `final_absence_set'define_query_cpu_unit. */
776 char in_set_p;
779 /* This describes define_bypass (see file rtl.def). */
780 struct bypass_decl
782 int latency;
783 char *out_insn_name;
784 char *in_insn_name;
785 char *bypass_guard_name;
787 /* The following fields are defined by checker. */
789 /* output and input insns of given bypass. */
790 struct insn_reserv_decl *out_insn_reserv;
791 struct insn_reserv_decl *in_insn_reserv;
792 /* The next bypass for given output insn. */
793 struct bypass_decl *next;
796 /* This describes define_automaton (see file rtl.def). */
797 struct automaton_decl
799 char *name;
801 /* The following fields are defined by automaton generator. */
803 /* The following field value is nonzero if the automaton is used in
804 an regexp definition. */
805 char automaton_is_used;
807 /* The following fields are defined by checker. */
809 /* The following field value is the corresponding automaton. This
810 field is not NULL only if the automaton is present in unit
811 declarations and the automatic partition on automata is not
812 used. */
813 automaton_t corresponding_automaton;
816 /* This describes exclusion relations: exclusion_set (see file
817 rtl.def). */
818 struct excl_rel_decl
820 int all_names_num;
821 int first_list_length;
822 char *names [1];
825 /* This describes unit relations: [final_]presence_set or
826 [final_]absence_set (see file rtl.def). */
827 struct unit_pattern_rel_decl
829 int final_p;
830 int names_num;
831 int patterns_num;
832 char **names;
833 char ***patterns;
836 /* This describes define_reservation (see file rtl.def). */
837 struct reserv_decl
839 char *name;
840 regexp_t regexp;
842 /* The following fields are defined by checker. */
844 /* The following field value is nonzero if the unit is used in an
845 regexp. */
846 char reserv_is_used;
847 /* The following field is used to check up cycle in expression
848 definition. */
849 int loop_pass_num;
852 /* This describes define_insn_reservation (see file rtl.def). */
853 struct insn_reserv_decl
855 rtx condexp;
856 int default_latency;
857 regexp_t regexp;
858 char *name;
860 /* The following fields are defined by checker. */
862 /* The following field value is order number (0, 1, ...) of given
863 insn. */
864 int insn_num;
865 /* The following field value is list of bypasses in which given insn
866 is output insn. */
867 struct bypass_decl *bypass_list;
869 /* The following fields are defined by automaton generator. */
871 /* The following field is the insn regexp transformed that
872 the regexp has not optional regexp, repetition regexp, and an
873 reservation name (i.e. reservation identifiers are changed by the
874 corresponding regexp) and all alternations are the topest level
875 of the regexp. The value can be NULL only if it is special
876 insn `cycle advancing'. */
877 regexp_t transformed_regexp;
878 /* The following field value is list of arcs marked given
879 insn. The field is used in transformation NDFA -> DFA. */
880 arc_t arcs_marked_by_insn;
881 /* The two following fields are used during minimization of a finite state
882 automaton. */
883 /* The field value is number of equivalence class of state into
884 which arc marked by given insn enters from a state (fixed during
885 an automaton minimization). */
886 int equiv_class_num;
887 /* The field value is state_alts of arc leaving a state (fixed
888 during an automaton minimization) and marked by given insn
889 enters. */
890 int state_alts;
891 /* The following member value is the list to automata which can be
892 changed by the insn issue. */
893 automata_list_el_t important_automata_list;
894 /* The following member is used to process insn once for output. */
895 int processed_p;
898 /* This contains a declaration mentioned above. */
899 struct decl
901 /* What node in the union? */
902 enum decl_mode mode;
903 pos_t pos;
904 union
906 struct unit_decl unit;
907 struct bypass_decl bypass;
908 struct automaton_decl automaton;
909 struct excl_rel_decl excl;
910 struct unit_pattern_rel_decl presence;
911 struct unit_pattern_rel_decl absence;
912 struct reserv_decl reserv;
913 struct insn_reserv_decl insn_reserv;
914 } decl;
917 /* The following structures represent parsed reservation strings. */
918 enum regexp_mode
920 rm_unit,
921 rm_reserv,
922 rm_nothing,
923 rm_sequence,
924 rm_repeat,
925 rm_allof,
926 rm_oneof
929 /* Cpu unit in reservation. */
930 struct unit_regexp
932 char *name;
933 unit_decl_t unit_decl;
936 /* Define_reservation in a reservation. */
937 struct reserv_regexp
939 char *name;
940 struct reserv_decl *reserv_decl;
943 /* Absence of reservation (represented by string `nothing'). */
944 struct nothing_regexp
946 /* This used to be empty but ISO C doesn't allow that. */
947 char unused;
950 /* Representation of reservations separated by ',' (see file
951 rtl.def). */
952 struct sequence_regexp
954 int regexps_num;
955 regexp_t regexps [1];
958 /* Representation of construction `repeat' (see file rtl.def). */
959 struct repeat_regexp
961 int repeat_num;
962 regexp_t regexp;
965 /* Representation of reservations separated by '+' (see file
966 rtl.def). */
967 struct allof_regexp
969 int regexps_num;
970 regexp_t regexps [1];
973 /* Representation of reservations separated by '|' (see file
974 rtl.def). */
975 struct oneof_regexp
977 int regexps_num;
978 regexp_t regexps [1];
981 /* Representation of a reservation string. */
982 struct regexp
984 /* What node in the union? */
985 enum regexp_mode mode;
986 pos_t pos;
987 union
989 struct unit_regexp unit;
990 struct reserv_regexp reserv;
991 struct nothing_regexp nothing;
992 struct sequence_regexp sequence;
993 struct repeat_regexp repeat;
994 struct allof_regexp allof;
995 struct oneof_regexp oneof;
996 } regexp;
999 /* Represents description of pipeline hazard description based on
1000 NDFA. */
1001 struct description
1003 int decls_num;
1005 /* The following fields are defined by checker. */
1007 /* The following fields values are correspondingly number of all
1008 units, query units, and insns in the description. */
1009 int units_num;
1010 int query_units_num;
1011 int insns_num;
1012 /* The following field value is max length (in cycles) of
1013 reservations of insns. The field value is defined only for
1014 correct programs. */
1015 int max_insn_reserv_cycles;
1017 /* The following fields are defined by automaton generator. */
1019 /* The following field value is the first automaton. */
1020 automaton_t first_automaton;
1022 /* The following field is created by pipeline hazard parser and
1023 contains all declarations. We allocate additional entry for
1024 special insn "cycle advancing" which is added by the automaton
1025 generator. */
1026 decl_t decls [1];
1030 /* The following nodes are created in automaton checker. */
1032 /* The following nodes represent exclusion set for cpu units. Each
1033 element is accessed through only one excl_list. */
1034 struct unit_set_el
1036 unit_decl_t unit_decl;
1037 unit_set_el_t next_unit_set_el;
1040 /* The following nodes represent presence or absence pattern for cpu
1041 units. Each element is accessed through only one presence_list or
1042 absence_list. */
1043 struct pattern_set_el
1045 /* The number of units in unit_decls. */
1046 int units_num;
1047 /* The units forming the pattern. */
1048 struct unit_decl **unit_decls;
1049 pattern_set_el_t next_pattern_set_el;
1053 /* The following nodes are created in automaton generator. */
1056 /* The following nodes represent presence or absence pattern for cpu
1057 units. Each element is accessed through only one element of
1058 unit_presence_set_table or unit_absence_set_table. */
1059 struct pattern_reserv
1061 reserv_sets_t reserv;
1062 pattern_reserv_t next_pattern_reserv;
1065 /* The following node type describes state automaton. The state may
1066 be deterministic or non-deterministic. Non-deterministic state has
1067 several component states which represent alternative cpu units
1068 reservations. The state also is used for describing a
1069 deterministic reservation of automaton insn. */
1070 struct state
1072 /* The following member value is nonzero if there is a transition by
1073 cycle advancing. */
1074 int new_cycle_p;
1075 /* The following field is list of processor unit reservations on
1076 each cycle. */
1077 reserv_sets_t reservs;
1078 /* The following field is unique number of given state between other
1079 states. */
1080 int unique_num;
1081 /* The following field value is automaton to which given state
1082 belongs. */
1083 automaton_t automaton;
1084 /* The following field value is the first arc output from given
1085 state. */
1086 arc_t first_out_arc;
1087 /* The following field is used to form NDFA. */
1088 char it_was_placed_in_stack_for_NDFA_forming;
1089 /* The following field is used to form DFA. */
1090 char it_was_placed_in_stack_for_DFA_forming;
1091 /* The following field is used to transform NDFA to DFA and DFA
1092 minimization. The field value is not NULL if the state is a
1093 compound state. In this case the value of field `unit_sets_list'
1094 is NULL. All states in the list are in the hash table. The list
1095 is formed through field `next_sorted_alt_state'. We should
1096 support only one level of nesting state. */
1097 alt_state_t component_states;
1098 /* The following field is used for passing graph of states. */
1099 int pass_num;
1100 /* The list of states belonging to one equivalence class is formed
1101 with the aid of the following field. */
1102 state_t next_equiv_class_state;
1103 /* The two following fields are used during minimization of a finite
1104 state automaton. */
1105 int equiv_class_num_1, equiv_class_num_2;
1106 /* The following field is used during minimization of a finite state
1107 automaton. The field value is state corresponding to equivalence
1108 class to which given state belongs. */
1109 state_t equiv_class_state;
1110 /* The following field value is the order number of given state.
1111 The states in final DFA is enumerated with the aid of the
1112 following field. */
1113 int order_state_num;
1114 /* This member is used for passing states for searching minimal
1115 delay time. */
1116 int state_pass_num;
1117 /* The following member is used to evaluate min issue delay of insn
1118 for a state. */
1119 int min_insn_issue_delay;
1120 /* The following member is used to evaluate max issue rate of the
1121 processor. The value of the member is maximal length of the path
1122 from given state no containing arcs marked by special insn `cycle
1123 advancing'. */
1124 int longest_path_length;
1127 /* The following macro is an initial value of member
1128 `longest_path_length' of a state. */
1129 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1131 /* Automaton arc. */
1132 struct arc
1134 /* The following field refers for the state into which given arc
1135 enters. */
1136 state_t to_state;
1137 /* The following field describes that the insn issue (with cycle
1138 advancing for special insn `cycle advancing' and without cycle
1139 advancing for others) makes transition from given state to
1140 another given state. */
1141 ainsn_t insn;
1142 /* The following field value is the next arc output from the same
1143 state. */
1144 arc_t next_out_arc;
1145 /* List of arcs marked given insn is formed with the following
1146 field. The field is used in transformation NDFA -> DFA. */
1147 arc_t next_arc_marked_by_insn;
1148 /* The following field is defined if NDFA_FLAG is zero. The member
1149 value is number of alternative reservations which can be used for
1150 transition for given state by given insn. */
1151 int state_alts;
1154 /* The following node type describes a deterministic alternative in
1155 non-deterministic state which characterizes cpu unit reservations
1156 of automaton insn or which is part of NDFA. */
1157 struct alt_state
1159 /* The following field is a deterministic state which characterizes
1160 unit reservations of the instruction. */
1161 state_t state;
1162 /* The following field refers to the next state which characterizes
1163 unit reservations of the instruction. */
1164 alt_state_t next_alt_state;
1165 /* The following field refers to the next state in sorted list. */
1166 alt_state_t next_sorted_alt_state;
1169 /* The following node type describes insn of automaton. They are
1170 labels of FA arcs. */
1171 struct ainsn
1173 /* The following field value is the corresponding insn declaration
1174 of description. */
1175 struct insn_reserv_decl *insn_reserv_decl;
1176 /* The following field value is the next insn declaration for an
1177 automaton. */
1178 ainsn_t next_ainsn;
1179 /* The following field is states which characterize automaton unit
1180 reservations of the instruction. The value can be NULL only if it
1181 is special insn `cycle advancing'. */
1182 alt_state_t alt_states;
1183 /* The following field is sorted list of states which characterize
1184 automaton unit reservations of the instruction. The value can be
1185 NULL only if it is special insn `cycle advancing'. */
1186 alt_state_t sorted_alt_states;
1187 /* The following field refers the next automaton insn with
1188 the same reservations. */
1189 ainsn_t next_same_reservs_insn;
1190 /* The following field is flag of the first automaton insn with the
1191 same reservations in the declaration list. Only arcs marked such
1192 insn is present in the automaton. This significantly decreases
1193 memory requirements especially when several automata are
1194 formed. */
1195 char first_insn_with_same_reservs;
1196 /* The following member has nonzero value if there is arc from state of
1197 the automaton marked by the ainsn. */
1198 char arc_exists_p;
1199 /* Cyclic list of insns of an equivalence class is formed with the
1200 aid of the following field. */
1201 ainsn_t next_equiv_class_insn;
1202 /* The following field value is nonzero if the insn declaration is
1203 the first insn declaration with given equivalence number. */
1204 char first_ainsn_with_given_equialence_num;
1205 /* The following field is number of class of equivalence of insns.
1206 It is necessary because many insns may be equivalent with the
1207 point of view of pipeline hazards. */
1208 int insn_equiv_class_num;
1209 /* The following member value is TRUE if there is an arc in the
1210 automaton marked by the insn into another state. In other
1211 words, the insn can change the state of the automaton. */
1212 int important_p;
1215 /* The following describes an automaton for PHR. */
1216 struct automaton
1218 /* The following field value is the list of insn declarations for
1219 given automaton. */
1220 ainsn_t ainsn_list;
1221 /* The following field value is the corresponding automaton
1222 declaration. This field is not NULL only if the automatic
1223 partition on automata is not used. */
1224 struct automaton_decl *corresponding_automaton_decl;
1225 /* The following field value is the next automaton. */
1226 automaton_t next_automaton;
1227 /* The following field is start state of FA. There are not unit
1228 reservations in the state. */
1229 state_t start_state;
1230 /* The following field value is number of equivalence classes of
1231 insns (see field `insn_equiv_class_num' in
1232 `insn_reserv_decl'). */
1233 int insn_equiv_classes_num;
1234 /* The following field value is number of states of final DFA. */
1235 int achieved_states_num;
1236 /* The following field value is the order number (0, 1, ...) of
1237 given automaton. */
1238 int automaton_order_num;
1239 /* The following fields contain statistics information about
1240 building automaton. */
1241 int NDFA_states_num, DFA_states_num;
1242 /* The following field value is defined only if minimization of DFA
1243 is used. */
1244 int minimal_DFA_states_num;
1245 int NDFA_arcs_num, DFA_arcs_num;
1246 /* The following field value is defined only if minimization of DFA
1247 is used. */
1248 int minimal_DFA_arcs_num;
1249 /* The following two members refer for two table state x ainsn ->
1250 int. */
1251 state_ainsn_table_t trans_table;
1252 state_ainsn_table_t state_alts_table;
1253 /* The following member value is maximal value of min issue delay
1254 for insns of the automaton. */
1255 int max_min_delay;
1256 /* Usually min issue delay is small and we can place several (2, 4,
1257 8) elements in one vector element. So the compression factor can
1258 be 1 (no compression), 2, 4, 8. */
1259 int min_issue_delay_table_compression_factor;
1262 /* The following is the element of the list of automata. */
1263 struct automata_list_el
1265 /* The automaton itself. */
1266 automaton_t automaton;
1267 /* The next automata set element. */
1268 automata_list_el_t next_automata_list_el;
1271 /* The following structure describes a table state X ainsn -> int(>= 0). */
1272 struct state_ainsn_table
1274 /* Automaton to which given table belongs. */
1275 automaton_t automaton;
1276 /* The following tree vectors for comb vector implementation of the
1277 table. */
1278 vla_hwint_t comb_vect;
1279 vla_hwint_t check_vect;
1280 vla_hwint_t base_vect;
1281 /* This is simple implementation of the table. */
1282 vla_hwint_t full_vect;
1283 /* Minimal and maximal values of the previous vectors. */
1284 int min_comb_vect_el_value, max_comb_vect_el_value;
1285 int min_base_vect_el_value, max_base_vect_el_value;
1288 /* Macros to access members of unions. Use only them for access to
1289 union members of declarations and regexps. */
1291 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1293 #define DECL_UNIT(d) __extension__ \
1294 (({ struct decl *const _decl = (d); \
1295 if (_decl->mode != dm_unit) \
1296 decl_mode_check_failed (_decl->mode, "dm_unit", \
1297 __FILE__, __LINE__, __FUNCTION__); \
1298 &(_decl)->decl.unit; }))
1300 #define DECL_BYPASS(d) __extension__ \
1301 (({ struct decl *const _decl = (d); \
1302 if (_decl->mode != dm_bypass) \
1303 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1304 __FILE__, __LINE__, __FUNCTION__); \
1305 &(_decl)->decl.bypass; }))
1307 #define DECL_AUTOMATON(d) __extension__ \
1308 (({ struct decl *const _decl = (d); \
1309 if (_decl->mode != dm_automaton) \
1310 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1311 __FILE__, __LINE__, __FUNCTION__); \
1312 &(_decl)->decl.automaton; }))
1314 #define DECL_EXCL(d) __extension__ \
1315 (({ struct decl *const _decl = (d); \
1316 if (_decl->mode != dm_excl) \
1317 decl_mode_check_failed (_decl->mode, "dm_excl", \
1318 __FILE__, __LINE__, __FUNCTION__); \
1319 &(_decl)->decl.excl; }))
1321 #define DECL_PRESENCE(d) __extension__ \
1322 (({ struct decl *const _decl = (d); \
1323 if (_decl->mode != dm_presence) \
1324 decl_mode_check_failed (_decl->mode, "dm_presence", \
1325 __FILE__, __LINE__, __FUNCTION__); \
1326 &(_decl)->decl.presence; }))
1328 #define DECL_ABSENCE(d) __extension__ \
1329 (({ struct decl *const _decl = (d); \
1330 if (_decl->mode != dm_absence) \
1331 decl_mode_check_failed (_decl->mode, "dm_absence", \
1332 __FILE__, __LINE__, __FUNCTION__); \
1333 &(_decl)->decl.absence; }))
1335 #define DECL_RESERV(d) __extension__ \
1336 (({ struct decl *const _decl = (d); \
1337 if (_decl->mode != dm_reserv) \
1338 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1339 __FILE__, __LINE__, __FUNCTION__); \
1340 &(_decl)->decl.reserv; }))
1342 #define DECL_INSN_RESERV(d) __extension__ \
1343 (({ struct decl *const _decl = (d); \
1344 if (_decl->mode != dm_insn_reserv) \
1345 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1346 __FILE__, __LINE__, __FUNCTION__); \
1347 &(_decl)->decl.insn_reserv; }))
1349 static const char *decl_name PARAMS ((enum decl_mode));
1350 static void decl_mode_check_failed PARAMS ((enum decl_mode, const char *,
1351 const char *, int, const char *));
1353 /* Return string representation of declaration mode MODE. */
1354 static const char *
1355 decl_name (mode)
1356 enum decl_mode mode;
1358 static char str [100];
1360 if (mode == dm_unit)
1361 return "dm_unit";
1362 else if (mode == dm_bypass)
1363 return "dm_bypass";
1364 else if (mode == dm_automaton)
1365 return "dm_automaton";
1366 else if (mode == dm_excl)
1367 return "dm_excl";
1368 else if (mode == dm_presence)
1369 return "dm_presence";
1370 else if (mode == dm_absence)
1371 return "dm_absence";
1372 else if (mode == dm_reserv)
1373 return "dm_reserv";
1374 else if (mode == dm_insn_reserv)
1375 return "dm_insn_reserv";
1376 else
1377 sprintf (str, "unknown (%d)", (int) mode);
1378 return str;
1381 /* The function prints message about unexpected declaration and finish
1382 the program. */
1383 static void
1384 decl_mode_check_failed (mode, expected_mode_str, file, line, func)
1385 enum decl_mode mode;
1386 const char *expected_mode_str;
1387 const char *file;
1388 int line;
1389 const char *func;
1391 fprintf
1392 (stderr,
1393 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1394 file, line, func, expected_mode_str, decl_name (mode));
1395 exit (1);
1399 #define REGEXP_UNIT(r) __extension__ \
1400 (({ struct regexp *const _regexp = (r); \
1401 if (_regexp->mode != rm_unit) \
1402 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1403 __FILE__, __LINE__, __FUNCTION__); \
1404 &(_regexp)->regexp.unit; }))
1406 #define REGEXP_RESERV(r) __extension__ \
1407 (({ struct regexp *const _regexp = (r); \
1408 if (_regexp->mode != rm_reserv) \
1409 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1410 __FILE__, __LINE__, __FUNCTION__); \
1411 &(_regexp)->regexp.reserv; }))
1413 #define REGEXP_SEQUENCE(r) __extension__ \
1414 (({ struct regexp *const _regexp = (r); \
1415 if (_regexp->mode != rm_sequence) \
1416 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1417 __FILE__, __LINE__, __FUNCTION__); \
1418 &(_regexp)->regexp.sequence; }))
1420 #define REGEXP_REPEAT(r) __extension__ \
1421 (({ struct regexp *const _regexp = (r); \
1422 if (_regexp->mode != rm_repeat) \
1423 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1424 __FILE__, __LINE__, __FUNCTION__); \
1425 &(_regexp)->regexp.repeat; }))
1427 #define REGEXP_ALLOF(r) __extension__ \
1428 (({ struct regexp *const _regexp = (r); \
1429 if (_regexp->mode != rm_allof) \
1430 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1431 __FILE__, __LINE__, __FUNCTION__); \
1432 &(_regexp)->regexp.allof; }))
1434 #define REGEXP_ONEOF(r) __extension__ \
1435 (({ struct regexp *const _regexp = (r); \
1436 if (_regexp->mode != rm_oneof) \
1437 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1438 __FILE__, __LINE__, __FUNCTION__); \
1439 &(_regexp)->regexp.oneof; }))
1441 static const char *regexp_name PARAMS ((enum regexp_mode));
1442 static void regexp_mode_check_failed PARAMS ((enum regexp_mode, const char *,
1443 const char *, int,
1444 const char *));
1447 /* Return string representation of regexp mode MODE. */
1448 static const char *
1449 regexp_name (mode)
1450 enum regexp_mode mode;
1452 static char str [100];
1454 if (mode == rm_unit)
1455 return "rm_unit";
1456 else if (mode == rm_reserv)
1457 return "rm_reserv";
1458 else if (mode == rm_nothing)
1459 return "rm_nothing";
1460 else if (mode == rm_sequence)
1461 return "rm_sequence";
1462 else if (mode == rm_repeat)
1463 return "rm_repeat";
1464 else if (mode == rm_allof)
1465 return "rm_allof";
1466 else if (mode == rm_oneof)
1467 return "rm_oneof";
1468 else
1469 sprintf (str, "unknown (%d)", (int) mode);
1470 return str;
1473 /* The function prints message about unexpected regexp and finish the
1474 program. */
1475 static void
1476 regexp_mode_check_failed (mode, expected_mode_str, file, line, func)
1477 enum regexp_mode mode;
1478 const char *expected_mode_str;
1479 const char *file;
1480 int line;
1481 const char *func;
1483 fprintf
1484 (stderr,
1485 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1486 file, line, func, expected_mode_str, regexp_name (mode));
1487 exit (1);
1490 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1492 #define DECL_UNIT(d) (&(d)->decl.unit)
1493 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1494 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1495 #define DECL_EXCL(d) (&(d)->decl.excl)
1496 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1497 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1498 #define DECL_RESERV(d) (&(d)->decl.reserv)
1499 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1501 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1502 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1503 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1504 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1505 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1506 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1508 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1510 /* Create IR structure (node). */
1511 static void *
1512 create_node (size)
1513 size_t size;
1515 void *result;
1517 obstack_blank (&irp, size);
1518 result = obstack_base (&irp);
1519 obstack_finish (&irp);
1520 /* Default values of members are NULL and zero. */
1521 memset (result, 0, size);
1522 return result;
1525 /* Copy IR structure (node). */
1526 static void *
1527 copy_node (from, size)
1528 const void *from;
1529 size_t size;
1531 void *const result = create_node (size);
1532 memcpy (result, from, size);
1533 return result;
1536 /* The function checks that NAME does not contain quotes (`"'). */
1537 static char *
1538 check_name (name, pos)
1539 char * name;
1540 pos_t pos ATTRIBUTE_UNUSED;
1542 const char *str;
1544 for (str = name; *str != '\0'; str++)
1545 if (*str == '\"')
1546 error ("Name `%s' contains quotes", name);
1547 return name;
1550 /* Pointers to all declarations during IR generation are stored in the
1551 following. */
1552 static vla_ptr_t decls;
1554 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1555 string containing the next separated element, taking parentheses
1556 into account if PAR_FLAG has nonzero value. Advance the pointer to
1557 after the string scanned, or the end-of-string. Return NULL if at
1558 end of string. */
1559 static char *
1560 next_sep_el (pstr, sep, par_flag)
1561 char **pstr;
1562 int sep;
1563 int par_flag;
1565 char *out_str;
1566 char *p;
1567 int pars_num;
1568 int n_spaces;
1570 /* Remove leading whitespaces. */
1571 while (ISSPACE ((int) **pstr))
1572 (*pstr)++;
1574 if (**pstr == '\0')
1575 return NULL;
1577 n_spaces = 0;
1578 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1580 if (par_flag && *p == '(')
1581 pars_num++;
1582 else if (par_flag && *p == ')')
1583 pars_num--;
1584 else if (pars_num == 0 && *p == sep)
1585 break;
1586 if (pars_num == 0 && ISSPACE ((int) *p))
1587 n_spaces++;
1588 else
1590 for (; n_spaces != 0; n_spaces--)
1591 obstack_1grow (&irp, p [-n_spaces]);
1592 obstack_1grow (&irp, *p);
1595 obstack_1grow (&irp, '\0');
1596 out_str = obstack_base (&irp);
1597 obstack_finish (&irp);
1599 *pstr = p;
1600 if (**pstr == sep)
1601 (*pstr)++;
1603 return out_str;
1606 /* Given a string and a separator, return the number of separated
1607 elements in it, taking parentheses into account if PAR_FLAG has
1608 nonzero value. Return 0 for the null string, -1 if parentheses is
1609 not balanced. */
1610 static int
1611 n_sep_els (s, sep, par_flag)
1612 char *s;
1613 int sep;
1614 int par_flag;
1616 int n;
1617 int pars_num;
1619 if (*s == '\0')
1620 return 0;
1622 for (pars_num = 0, n = 1; *s; s++)
1623 if (par_flag && *s == '(')
1624 pars_num++;
1625 else if (par_flag && *s == ')')
1626 pars_num--;
1627 else if (pars_num == 0 && *s == sep)
1628 n++;
1630 return (pars_num != 0 ? -1 : n);
1633 /* Given a string and a separator, return vector of strings which are
1634 elements in the string and number of elements through els_num.
1635 Take parentheses into account if PAREN_P has nonzero value. The
1636 function also inserts the end marker NULL at the end of vector.
1637 Return 0 for the null string, -1 if parantheses are not balanced. */
1638 static char **
1639 get_str_vect (str, els_num, sep, paren_p)
1640 char *str;
1641 int *els_num;
1642 int sep;
1643 int paren_p;
1645 int i;
1646 char **vect;
1647 char **pstr;
1649 *els_num = n_sep_els (str, sep, paren_p);
1650 if (*els_num <= 0)
1651 return NULL;
1652 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1653 vect = (char **) obstack_base (&irp);
1654 obstack_finish (&irp);
1655 pstr = &str;
1656 for (i = 0; i < *els_num; i++)
1657 vect [i] = next_sep_el (pstr, sep, paren_p);
1658 if (next_sep_el (pstr, sep, paren_p) != NULL)
1659 abort ();
1660 vect [i] = NULL;
1661 return vect;
1664 /* Process a DEFINE_CPU_UNIT.
1666 This gives information about a unit contained in CPU. We fill a
1667 struct unit_decl with information used later by `expand_automata'. */
1668 void
1669 gen_cpu_unit (def)
1670 rtx def;
1672 decl_t decl;
1673 char **str_cpu_units;
1674 int vect_length;
1675 int i;
1677 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1678 FALSE);
1679 if (str_cpu_units == NULL)
1680 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1681 for (i = 0; i < vect_length; i++)
1683 decl = create_node (sizeof (struct decl));
1684 decl->mode = dm_unit;
1685 decl->pos = 0;
1686 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1687 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1688 DECL_UNIT (decl)->query_p = 0;
1689 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1690 DECL_UNIT (decl)->in_set_p = 0;
1691 VLA_PTR_ADD (decls, decl);
1692 num_dfa_decls++;
1696 /* Process a DEFINE_QUERY_CPU_UNIT.
1698 This gives information about a unit contained in CPU. We fill a
1699 struct unit_decl with information used later by `expand_automata'. */
1700 void
1701 gen_query_cpu_unit (def)
1702 rtx def;
1704 decl_t decl;
1705 char **str_cpu_units;
1706 int vect_length;
1707 int i;
1709 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1710 FALSE);
1711 if (str_cpu_units == NULL)
1712 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1713 for (i = 0; i < vect_length; i++)
1715 decl = create_node (sizeof (struct decl));
1716 decl->mode = dm_unit;
1717 decl->pos = 0;
1718 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1719 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1720 DECL_UNIT (decl)->query_p = 1;
1721 VLA_PTR_ADD (decls, decl);
1722 num_dfa_decls++;
1726 /* Process a DEFINE_BYPASS.
1728 This gives information about a unit contained in the CPU. We fill
1729 in a struct bypass_decl with information used later by
1730 `expand_automata'. */
1731 void
1732 gen_bypass (def)
1733 rtx def;
1735 decl_t decl;
1736 char **out_insns;
1737 int out_length;
1738 char **in_insns;
1739 int in_length;
1740 int i, j;
1742 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', FALSE);
1743 if (out_insns == NULL)
1744 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1745 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', FALSE);
1746 if (in_insns == NULL)
1747 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1748 for (i = 0; i < out_length; i++)
1749 for (j = 0; j < in_length; j++)
1751 decl = create_node (sizeof (struct decl));
1752 decl->mode = dm_bypass;
1753 decl->pos = 0;
1754 DECL_BYPASS (decl)->latency = XINT (def, 0);
1755 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1756 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1757 DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
1758 VLA_PTR_ADD (decls, decl);
1759 num_dfa_decls++;
1763 /* Process an EXCLUSION_SET.
1765 This gives information about a cpu unit conflicts. We fill a
1766 struct excl_rel_decl (excl) with information used later by
1767 `expand_automata'. */
1768 void
1769 gen_excl_set (def)
1770 rtx def;
1772 decl_t decl;
1773 char **first_str_cpu_units;
1774 char **second_str_cpu_units;
1775 int first_vect_length;
1776 int length;
1777 int i;
1779 first_str_cpu_units
1780 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', FALSE);
1781 if (first_str_cpu_units == NULL)
1782 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1783 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1784 FALSE);
1785 if (second_str_cpu_units == NULL)
1786 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1787 length += first_vect_length;
1788 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1789 decl->mode = dm_excl;
1790 decl->pos = 0;
1791 DECL_EXCL (decl)->all_names_num = length;
1792 DECL_EXCL (decl)->first_list_length = first_vect_length;
1793 for (i = 0; i < length; i++)
1794 if (i < first_vect_length)
1795 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1796 else
1797 DECL_EXCL (decl)->names [i]
1798 = second_str_cpu_units [i - first_vect_length];
1799 VLA_PTR_ADD (decls, decl);
1800 num_dfa_decls++;
1803 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1804 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1806 This gives information about a cpu unit reservation requirements.
1807 We fill a struct unit_pattern_rel_decl with information used later
1808 by `expand_automata'. */
1809 static void
1810 gen_presence_absence_set (def, presence_p, final_p)
1811 rtx def;
1812 int presence_p;
1813 int final_p;
1815 decl_t decl;
1816 char **str_cpu_units;
1817 char ***str_patterns;
1818 int cpu_units_length;
1819 int length;
1820 int patterns_length;
1821 int i;
1823 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &cpu_units_length, ',',
1824 FALSE);
1825 if (str_cpu_units == NULL)
1826 fatal ((presence_p
1827 ? (final_p
1828 ? "invalid first string `%s' in final_presence_set"
1829 : "invalid first string `%s' in presence_set")
1830 : (final_p
1831 ? "invalid first string `%s' in final_absence_set"
1832 : "invalid first string `%s' in absence_set")),
1833 XSTR (def, 0));
1834 str_patterns = (char ***) get_str_vect ((char *) XSTR (def, 1),
1835 &patterns_length, ',', FALSE);
1836 if (str_patterns == NULL)
1837 fatal ((presence_p
1838 ? (final_p
1839 ? "invalid second string `%s' in final_presence_set"
1840 : "invalid second string `%s' in presence_set")
1841 : (final_p
1842 ? "invalid second string `%s' in final_absence_set"
1843 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1844 for (i = 0; i < patterns_length; i++)
1846 str_patterns [i] = get_str_vect ((char *) str_patterns [i], &length, ' ',
1847 FALSE);
1848 if (str_patterns [i] == NULL)
1849 abort ();
1851 decl = create_node (sizeof (struct decl));
1852 decl->pos = 0;
1853 if (presence_p)
1855 decl->mode = dm_presence;
1856 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1857 DECL_PRESENCE (decl)->names = str_cpu_units;
1858 DECL_PRESENCE (decl)->patterns = str_patterns;
1859 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1860 DECL_PRESENCE (decl)->final_p = final_p;
1862 else
1864 decl->mode = dm_absence;
1865 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1866 DECL_ABSENCE (decl)->names = str_cpu_units;
1867 DECL_ABSENCE (decl)->patterns = str_patterns;
1868 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1869 DECL_ABSENCE (decl)->final_p = final_p;
1871 VLA_PTR_ADD (decls, decl);
1872 num_dfa_decls++;
1875 /* Process a PRESENCE_SET.
1877 This gives information about a cpu unit reservation requirements.
1878 We fill a struct unit_pattern_rel_decl (presence) with information
1879 used later by `expand_automata'. */
1880 void
1881 gen_presence_set (def)
1882 rtx def;
1884 gen_presence_absence_set (def, TRUE, FALSE);
1887 /* Process a FINAL_PRESENCE_SET.
1889 This gives information about a cpu unit reservation requirements.
1890 We fill a struct unit_pattern_rel_decl (presence) with information
1891 used later by `expand_automata'. */
1892 void
1893 gen_final_presence_set (def)
1894 rtx def;
1896 gen_presence_absence_set (def, TRUE, TRUE);
1899 /* Process an ABSENCE_SET.
1901 This gives information about a cpu unit reservation requirements.
1902 We fill a struct unit_pattern_rel_decl (absence) with information
1903 used later by `expand_automata'. */
1904 void
1905 gen_absence_set (def)
1906 rtx def;
1908 gen_presence_absence_set (def, FALSE, FALSE);
1911 /* Process a FINAL_ABSENCE_SET.
1913 This gives information about a cpu unit reservation requirements.
1914 We fill a struct unit_pattern_rel_decl (absence) with information
1915 used later by `expand_automata'. */
1916 void
1917 gen_final_absence_set (def)
1918 rtx def;
1920 gen_presence_absence_set (def, FALSE, TRUE);
1923 /* Process a DEFINE_AUTOMATON.
1925 This gives information about a finite state automaton used for
1926 recognizing pipeline hazards. We fill a struct automaton_decl
1927 with information used later by `expand_automata'. */
1928 void
1929 gen_automaton (def)
1930 rtx def;
1932 decl_t decl;
1933 char **str_automata;
1934 int vect_length;
1935 int i;
1937 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1938 FALSE);
1939 if (str_automata == NULL)
1940 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1941 for (i = 0; i < vect_length; i++)
1943 decl = create_node (sizeof (struct decl));
1944 decl->mode = dm_automaton;
1945 decl->pos = 0;
1946 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1947 VLA_PTR_ADD (decls, decl);
1948 num_dfa_decls++;
1952 /* Process an AUTOMATA_OPTION.
1954 This gives information how to generate finite state automaton used
1955 for recognizing pipeline hazards. */
1956 void
1957 gen_automata_option (def)
1958 rtx def;
1960 if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1961 no_minimization_flag = 1;
1962 else if (strcmp ((char *) XSTR (def, 0), TIME_OPTION + 1) == 0)
1963 time_flag = 1;
1964 else if (strcmp ((char *) XSTR (def, 0), V_OPTION + 1) == 0)
1965 v_flag = 1;
1966 else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
1967 w_flag = 1;
1968 else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
1969 ndfa_flag = 1;
1970 else
1971 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1974 /* Name in reservation to denote absence reservation. */
1975 #define NOTHING_NAME "nothing"
1977 /* The following string contains original reservation string being
1978 parsed. */
1979 static char *reserv_str;
1981 /* Parse an element in STR. */
1982 static regexp_t
1983 gen_regexp_el (str)
1984 char *str;
1986 regexp_t regexp;
1987 int len;
1989 if (*str == '(')
1991 len = strlen (str);
1992 if (str [len - 1] != ')')
1993 fatal ("garbage after ) in reservation `%s'", reserv_str);
1994 str [len - 1] = '\0';
1995 regexp = gen_regexp_sequence (str + 1);
1997 else if (strcmp (str, NOTHING_NAME) == 0)
1999 regexp = create_node (sizeof (struct decl));
2000 regexp->mode = rm_nothing;
2002 else
2004 regexp = create_node (sizeof (struct decl));
2005 regexp->mode = rm_unit;
2006 REGEXP_UNIT (regexp)->name = str;
2008 return regexp;
2011 /* Parse construction `repeat' in STR. */
2012 static regexp_t
2013 gen_regexp_repeat (str)
2014 char *str;
2016 regexp_t regexp;
2017 regexp_t repeat;
2018 char **repeat_vect;
2019 int els_num;
2020 int i;
2022 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
2023 if (repeat_vect == NULL)
2024 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2025 if (els_num > 1)
2027 regexp = gen_regexp_el (repeat_vect [0]);
2028 for (i = 1; i < els_num; i++)
2030 repeat = create_node (sizeof (struct regexp));
2031 repeat->mode = rm_repeat;
2032 REGEXP_REPEAT (repeat)->regexp = regexp;
2033 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
2034 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
2035 fatal ("repetition `%s' <= 1 in reservation `%s'",
2036 str, reserv_str);
2037 regexp = repeat;
2039 return regexp;
2041 else
2042 return gen_regexp_el (str);
2045 /* Parse reservation STR which possibly contains separator '+'. */
2046 static regexp_t
2047 gen_regexp_allof (str)
2048 char *str;
2050 regexp_t allof;
2051 char **allof_vect;
2052 int els_num;
2053 int i;
2055 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
2056 if (allof_vect == NULL)
2057 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2058 if (els_num > 1)
2060 allof = create_node (sizeof (struct regexp)
2061 + sizeof (regexp_t) * (els_num - 1));
2062 allof->mode = rm_allof;
2063 REGEXP_ALLOF (allof)->regexps_num = els_num;
2064 for (i = 0; i < els_num; i++)
2065 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
2066 return allof;
2068 else
2069 return gen_regexp_repeat (str);
2072 /* Parse reservation STR which possibly contains separator '|'. */
2073 static regexp_t
2074 gen_regexp_oneof (str)
2075 char *str;
2077 regexp_t oneof;
2078 char **oneof_vect;
2079 int els_num;
2080 int i;
2082 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
2083 if (oneof_vect == NULL)
2084 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2085 if (els_num > 1)
2087 oneof = create_node (sizeof (struct regexp)
2088 + sizeof (regexp_t) * (els_num - 1));
2089 oneof->mode = rm_oneof;
2090 REGEXP_ONEOF (oneof)->regexps_num = els_num;
2091 for (i = 0; i < els_num; i++)
2092 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
2093 return oneof;
2095 else
2096 return gen_regexp_allof (str);
2099 /* Parse reservation STR which possibly contains separator ','. */
2100 static regexp_t
2101 gen_regexp_sequence (str)
2102 char *str;
2104 regexp_t sequence;
2105 char **sequence_vect;
2106 int els_num;
2107 int i;
2109 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
2110 if (els_num > 1)
2112 sequence = create_node (sizeof (struct regexp)
2113 + sizeof (regexp_t) * (els_num - 1));
2114 sequence->mode = rm_sequence;
2115 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2116 for (i = 0; i < els_num; i++)
2117 REGEXP_SEQUENCE (sequence)->regexps [i]
2118 = gen_regexp_oneof (sequence_vect [i]);
2119 return sequence;
2121 else
2122 return gen_regexp_oneof (str);
2125 /* Parse construction reservation STR. */
2126 static regexp_t
2127 gen_regexp (str)
2128 char *str;
2130 reserv_str = str;
2131 return gen_regexp_sequence (str);;
2134 /* Process a DEFINE_RESERVATION.
2136 This gives information about a reservation of cpu units. We fill
2137 in a struct reserv_decl with information used later by
2138 `expand_automata'. */
2139 void
2140 gen_reserv (def)
2141 rtx def;
2143 decl_t decl;
2145 decl = create_node (sizeof (struct decl));
2146 decl->mode = dm_reserv;
2147 decl->pos = 0;
2148 DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2149 DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2150 VLA_PTR_ADD (decls, decl);
2151 num_dfa_decls++;
2154 /* Process a DEFINE_INSN_RESERVATION.
2156 This gives information about the reservation of cpu units by an
2157 insn. We fill a struct insn_reserv_decl with information used
2158 later by `expand_automata'. */
2159 void
2160 gen_insn_reserv (def)
2161 rtx def;
2163 decl_t decl;
2165 decl = create_node (sizeof (struct decl));
2166 decl->mode = dm_insn_reserv;
2167 decl->pos = 0;
2168 DECL_INSN_RESERV (decl)->name
2169 = check_name ((char *) XSTR (def, 0), decl->pos);
2170 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2171 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2172 DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2173 VLA_PTR_ADD (decls, decl);
2174 num_dfa_decls++;
2179 /* The function evaluates hash value (0..UINT_MAX) of string. */
2180 static unsigned
2181 string_hash (string)
2182 const char *string;
2184 unsigned result, i;
2186 for (result = i = 0;*string++ != '\0'; i++)
2187 result += ((unsigned char) *string << (i % CHAR_BIT));
2188 return result;
2193 /* This page contains abstract data `table of automaton declarations'.
2194 Elements of the table is nodes representing automaton declarations.
2195 Key of the table elements is name of given automaton. Remember
2196 that automaton names have own space. */
2198 /* The function evaluates hash value of an automaton declaration. The
2199 function is used by abstract data `hashtab'. The function returns
2200 hash value (0..UINT_MAX) of given automaton declaration. */
2201 static hashval_t
2202 automaton_decl_hash (automaton_decl)
2203 const void *automaton_decl;
2205 const decl_t decl = (decl_t) automaton_decl;
2207 if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
2208 abort ();
2209 return string_hash (DECL_AUTOMATON (decl)->name);
2212 /* The function tests automaton declarations on equality of their
2213 keys. The function is used by abstract data `hashtab'. The
2214 function returns 1 if the declarations have the same key, 0
2215 otherwise. */
2216 static int
2217 automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
2218 const void* automaton_decl_1;
2219 const void* automaton_decl_2;
2221 const decl_t decl1 = (decl_t) automaton_decl_1;
2222 const decl_t decl2 = (decl_t) automaton_decl_2;
2224 if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
2225 || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
2226 abort ();
2227 return strcmp (DECL_AUTOMATON (decl1)->name,
2228 DECL_AUTOMATON (decl2)->name) == 0;
2231 /* The automaton declaration table itself is represented by the
2232 following variable. */
2233 static htab_t automaton_decl_table;
2235 /* The function inserts automaton declaration into the table. The
2236 function does nothing if an automaton declaration with the same key
2237 exists already in the table. The function returns automaton
2238 declaration node in the table with the same key as given automaton
2239 declaration node. */
2240 static decl_t
2241 insert_automaton_decl (automaton_decl)
2242 decl_t automaton_decl;
2244 void **entry_ptr;
2246 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
2247 if (*entry_ptr == NULL)
2248 *entry_ptr = (void *) automaton_decl;
2249 return (decl_t) *entry_ptr;
2252 /* The following variable value is node representing automaton
2253 declaration. The node used for searching automaton declaration
2254 with given name. */
2255 static struct decl work_automaton_decl;
2257 /* The function searches for automaton declaration in the table with
2258 the same key as node representing name of the automaton
2259 declaration. The function returns node found in the table, NULL if
2260 such node does not exist in the table. */
2261 static decl_t
2262 find_automaton_decl (name)
2263 char *name;
2265 void *entry;
2267 work_automaton_decl.mode = dm_automaton;
2268 DECL_AUTOMATON (&work_automaton_decl)->name = name;
2269 entry = htab_find (automaton_decl_table, &work_automaton_decl);
2270 return (decl_t) entry;
2273 /* The function creates empty automaton declaration table and node
2274 representing automaton declaration and used for searching automaton
2275 declaration with given name. The function must be called only once
2276 before any work with the automaton declaration table. */
2277 static void
2278 initiate_automaton_decl_table ()
2280 work_automaton_decl.mode = dm_automaton;
2281 automaton_decl_table = htab_create (10, automaton_decl_hash,
2282 automaton_decl_eq_p, (htab_del) 0);
2285 /* The function deletes the automaton declaration table. Only call of
2286 function `initiate_automaton_decl_table' is possible immediately
2287 after this function call. */
2288 static void
2289 finish_automaton_decl_table ()
2291 htab_delete (automaton_decl_table);
2296 /* This page contains abstract data `table of insn declarations'.
2297 Elements of the table is nodes representing insn declarations. Key
2298 of the table elements is name of given insn (in corresponding
2299 define_insn_reservation). Remember that insn names have own
2300 space. */
2302 /* The function evaluates hash value of an insn declaration. The
2303 function is used by abstract data `hashtab'. The function returns
2304 hash value (0..UINT_MAX) of given insn declaration. */
2305 static hashval_t
2306 insn_decl_hash (insn_decl)
2307 const void *insn_decl;
2309 const decl_t decl = (decl_t) insn_decl;
2311 if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
2312 abort ();
2313 return string_hash (DECL_INSN_RESERV (decl)->name);
2316 /* The function tests insn declarations on equality of their keys.
2317 The function is used by abstract data `hashtab'. The function
2318 returns 1 if declarations have the same key, 0 otherwise. */
2319 static int
2320 insn_decl_eq_p (insn_decl_1, insn_decl_2)
2321 const void *insn_decl_1;
2322 const void *insn_decl_2;
2324 const decl_t decl1 = (decl_t) insn_decl_1;
2325 const decl_t decl2 = (decl_t) insn_decl_2;
2327 if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
2328 || decl2->mode != dm_insn_reserv
2329 || DECL_INSN_RESERV (decl2)->name == NULL)
2330 abort ();
2331 return strcmp (DECL_INSN_RESERV (decl1)->name,
2332 DECL_INSN_RESERV (decl2)->name) == 0;
2335 /* The insn declaration table itself is represented by the following
2336 variable. The table does not contain insn reservation
2337 declarations. */
2338 static htab_t insn_decl_table;
2340 /* The function inserts insn declaration into the table. The function
2341 does nothing if an insn declaration with the same key exists
2342 already in the table. The function returns insn declaration node
2343 in the table with the same key as given insn declaration node. */
2344 static decl_t
2345 insert_insn_decl (insn_decl)
2346 decl_t insn_decl;
2348 void **entry_ptr;
2350 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2351 if (*entry_ptr == NULL)
2352 *entry_ptr = (void *) insn_decl;
2353 return (decl_t) *entry_ptr;
2356 /* The following variable value is node representing insn reservation
2357 declaration. The node used for searching insn reservation
2358 declaration with given name. */
2359 static struct decl work_insn_decl;
2361 /* The function searches for insn reservation declaration in the table
2362 with the same key as node representing name of the insn reservation
2363 declaration. The function returns node found in the table, NULL if
2364 such node does not exist in the table. */
2365 static decl_t
2366 find_insn_decl (name)
2367 char *name;
2369 void *entry;
2371 work_insn_decl.mode = dm_insn_reserv;
2372 DECL_INSN_RESERV (&work_insn_decl)->name = name;
2373 entry = htab_find (insn_decl_table, &work_insn_decl);
2374 return (decl_t) entry;
2377 /* The function creates empty insn declaration table and node
2378 representing insn declaration and used for searching insn
2379 declaration with given name. The function must be called only once
2380 before any work with the insn declaration table. */
2381 static void
2382 initiate_insn_decl_table ()
2384 work_insn_decl.mode = dm_insn_reserv;
2385 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2386 (htab_del) 0);
2389 /* The function deletes the insn declaration table. Only call of
2390 function `initiate_insn_decl_table' is possible immediately after
2391 this function call. */
2392 static void
2393 finish_insn_decl_table ()
2395 htab_delete (insn_decl_table);
2400 /* This page contains abstract data `table of declarations'. Elements
2401 of the table is nodes representing declarations (of units and
2402 reservations). Key of the table elements is names of given
2403 declarations. */
2405 /* The function evaluates hash value of a declaration. The function
2406 is used by abstract data `hashtab'. The function returns hash
2407 value (0..UINT_MAX) of given declaration. */
2408 static hashval_t
2409 decl_hash (decl)
2410 const void *decl;
2412 const decl_t d = (const decl_t) decl;
2414 if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
2415 && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
2416 abort ();
2417 return string_hash (d->mode == dm_unit
2418 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
2421 /* The function tests declarations on equality of their keys. The
2422 function is used by abstract data `hashtab'. The function
2423 returns 1 if the declarations have the same key, 0 otherwise. */
2424 static int
2425 decl_eq_p (decl_1, decl_2)
2426 const void *decl_1;
2427 const void *decl_2;
2429 const decl_t d1 = (const decl_t) decl_1;
2430 const decl_t d2 = (const decl_t) decl_2;
2432 if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
2433 && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
2434 || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
2435 && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
2436 abort ();
2437 return strcmp ((d1->mode == dm_unit
2438 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
2439 (d2->mode == dm_unit
2440 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2443 /* The declaration table itself is represented by the following
2444 variable. */
2445 static htab_t decl_table;
2447 /* The function inserts declaration into the table. The function does
2448 nothing if a declaration with the same key exists already in the
2449 table. The function returns declaration node in the table with the
2450 same key as given declaration node. */
2452 static decl_t
2453 insert_decl (decl)
2454 decl_t decl;
2456 void **entry_ptr;
2458 entry_ptr = htab_find_slot (decl_table, decl, 1);
2459 if (*entry_ptr == NULL)
2460 *entry_ptr = (void *) decl;
2461 return (decl_t) *entry_ptr;
2464 /* The following variable value is node representing declaration. The
2465 node used for searching declaration with given name. */
2466 static struct decl work_decl;
2468 /* The function searches for declaration in the table with the same
2469 key as node representing name of the declaration. The function
2470 returns node found in the table, NULL if such node does not exist
2471 in the table. */
2472 static decl_t
2473 find_decl (name)
2474 char *name;
2476 void *entry;
2478 work_decl.mode = dm_unit;
2479 DECL_UNIT (&work_decl)->name = name;
2480 entry = htab_find (decl_table, &work_decl);
2481 return (decl_t) entry;
2484 /* The function creates empty declaration table and node representing
2485 declaration and used for searching declaration with given name.
2486 The function must be called only once before any work with the
2487 declaration table. */
2488 static void
2489 initiate_decl_table ()
2491 work_decl.mode = dm_unit;
2492 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2495 /* The function deletes the declaration table. Only call of function
2496 `initiate_declaration_table' is possible immediately after this
2497 function call. */
2498 static void
2499 finish_decl_table ()
2501 htab_delete (decl_table);
2506 /* This page contains checker of pipeline hazard description. */
2508 /* Checking NAMES in an exclusion clause vector and returning formed
2509 unit_set_el_list. */
2510 static unit_set_el_t
2511 process_excls (names, num, excl_pos)
2512 char **names;
2513 int num;
2514 pos_t excl_pos ATTRIBUTE_UNUSED;
2516 unit_set_el_t el_list;
2517 unit_set_el_t last_el;
2518 unit_set_el_t new_el;
2519 decl_t decl_in_table;
2520 int i;
2522 el_list = NULL;
2523 last_el = NULL;
2524 for (i = 0; i < num; i++)
2526 decl_in_table = find_decl (names [i]);
2527 if (decl_in_table == NULL)
2528 error ("unit `%s' in exclusion is not declared", names [i]);
2529 else if (decl_in_table->mode != dm_unit)
2530 error ("`%s' in exclusion is not unit", names [i]);
2531 else
2533 new_el = create_node (sizeof (struct unit_set_el));
2534 new_el->unit_decl = DECL_UNIT (decl_in_table);
2535 new_el->next_unit_set_el = NULL;
2536 if (last_el == NULL)
2537 el_list = last_el = new_el;
2538 else
2540 last_el->next_unit_set_el = new_el;
2541 last_el = last_el->next_unit_set_el;
2545 return el_list;
2548 /* The function adds each element from SOURCE_LIST to the exclusion
2549 list of the each element from DEST_LIST. Checking situation "unit
2550 excludes itself". */
2551 static void
2552 add_excls (dest_list, source_list, excl_pos)
2553 unit_set_el_t dest_list;
2554 unit_set_el_t source_list;
2555 pos_t excl_pos ATTRIBUTE_UNUSED;
2557 unit_set_el_t dst;
2558 unit_set_el_t src;
2559 unit_set_el_t curr_el;
2560 unit_set_el_t prev_el;
2561 unit_set_el_t copy;
2563 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2564 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2566 if (dst->unit_decl == src->unit_decl)
2568 error ("unit `%s' excludes itself", src->unit_decl->name);
2569 continue;
2571 if (dst->unit_decl->automaton_name != NULL
2572 && src->unit_decl->automaton_name != NULL
2573 && strcmp (dst->unit_decl->automaton_name,
2574 src->unit_decl->automaton_name) != 0)
2576 error ("units `%s' and `%s' in exclusion set belong to different automata",
2577 src->unit_decl->name, dst->unit_decl->name);
2578 continue;
2580 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2581 curr_el != NULL;
2582 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2583 if (curr_el->unit_decl == src->unit_decl)
2584 break;
2585 if (curr_el == NULL)
2587 /* Element not found - insert. */
2588 copy = copy_node (src, sizeof (*src));
2589 copy->next_unit_set_el = NULL;
2590 if (prev_el == NULL)
2591 dst->unit_decl->excl_list = copy;
2592 else
2593 prev_el->next_unit_set_el = copy;
2598 /* Checking NAMES in presence/absence clause and returning the
2599 formed unit_set_el_list. The function is called only after
2600 processing all exclusion sets. */
2601 static unit_set_el_t
2602 process_presence_absence_names (names, num, req_pos, presence_p, final_p)
2603 char **names;
2604 int num;
2605 pos_t req_pos ATTRIBUTE_UNUSED;
2606 int presence_p;
2607 int final_p;
2609 unit_set_el_t el_list;
2610 unit_set_el_t last_el;
2611 unit_set_el_t new_el;
2612 decl_t decl_in_table;
2613 int i;
2615 el_list = NULL;
2616 last_el = NULL;
2617 for (i = 0; i < num; i++)
2619 decl_in_table = find_decl (names [i]);
2620 if (decl_in_table == NULL)
2621 error ((presence_p
2622 ? (final_p
2623 ? "unit `%s' in final presence set is not declared"
2624 : "unit `%s' in presence set is not declared")
2625 : (final_p
2626 ? "unit `%s' in final absence set is not declared"
2627 : "unit `%s' in absence set is not declared")), names [i]);
2628 else if (decl_in_table->mode != dm_unit)
2629 error ((presence_p
2630 ? (final_p
2631 ? "`%s' in final presence set is not unit"
2632 : "`%s' in presence set is not unit")
2633 : (final_p
2634 ? "`%s' in final absence set is not unit"
2635 : "`%s' in absence set is not unit")), names [i]);
2636 else
2638 new_el = create_node (sizeof (struct unit_set_el));
2639 new_el->unit_decl = DECL_UNIT (decl_in_table);
2640 new_el->next_unit_set_el = NULL;
2641 if (last_el == NULL)
2642 el_list = last_el = new_el;
2643 else
2645 last_el->next_unit_set_el = new_el;
2646 last_el = last_el->next_unit_set_el;
2650 return el_list;
2653 /* Checking NAMES in patterns of a presence/absence clause and
2654 returning the formed pattern_set_el_list. The function is called
2655 only after processing all exclusion sets. */
2656 static pattern_set_el_t
2657 process_presence_absence_patterns (patterns, num, req_pos, presence_p, final_p)
2658 char ***patterns;
2659 int num;
2660 pos_t req_pos ATTRIBUTE_UNUSED;
2661 int presence_p;
2662 int final_p;
2664 pattern_set_el_t el_list;
2665 pattern_set_el_t last_el;
2666 pattern_set_el_t new_el;
2667 decl_t decl_in_table;
2668 int i, j;
2670 el_list = NULL;
2671 last_el = NULL;
2672 for (i = 0; i < num; i++)
2674 for (j = 0; patterns [i] [j] != NULL; j++)
2676 new_el = create_node (sizeof (struct pattern_set_el)
2677 + sizeof (struct unit_decl *) * j);
2678 new_el->unit_decls
2679 = (struct unit_decl **) ((char *) new_el
2680 + sizeof (struct pattern_set_el));
2681 new_el->next_pattern_set_el = NULL;
2682 if (last_el == NULL)
2683 el_list = last_el = new_el;
2684 else
2686 last_el->next_pattern_set_el = new_el;
2687 last_el = last_el->next_pattern_set_el;
2689 new_el->units_num = 0;
2690 for (j = 0; patterns [i] [j] != NULL; j++)
2692 decl_in_table = find_decl (patterns [i] [j]);
2693 if (decl_in_table == NULL)
2694 error ((presence_p
2695 ? (final_p
2696 ? "unit `%s' in final presence set is not declared"
2697 : "unit `%s' in presence set is not declared")
2698 : (final_p
2699 ? "unit `%s' in final absence set is not declared"
2700 : "unit `%s' in absence set is not declared")),
2701 patterns [i] [j]);
2702 else if (decl_in_table->mode != dm_unit)
2703 error ((presence_p
2704 ? (final_p
2705 ? "`%s' in final presence set is not unit"
2706 : "`%s' in presence set is not unit")
2707 : (final_p
2708 ? "`%s' in final absence set is not unit"
2709 : "`%s' in absence set is not unit")),
2710 patterns [i] [j]);
2711 else
2713 new_el->unit_decls [new_el->units_num]
2714 = DECL_UNIT (decl_in_table);
2715 new_el->units_num++;
2719 return el_list;
2722 /* The function adds each element from PATTERN_LIST to presence (if
2723 PRESENCE_P) or absence list of the each element from DEST_LIST.
2724 Checking situations "unit requires own absence", and "unit excludes
2725 and requires presence of ...", "unit requires absence and presence
2726 of ...", "units in (final) presence set belong to different
2727 automata", and "units in (final) absence set belong to different
2728 automata". Remember that we process absence sets only after all
2729 presence sets. */
2730 static void
2731 add_presence_absence (dest_list, pattern_list, req_pos, presence_p, final_p)
2732 unit_set_el_t dest_list;
2733 pattern_set_el_t pattern_list;
2734 pos_t req_pos ATTRIBUTE_UNUSED;
2735 int presence_p;
2736 int final_p;
2738 unit_set_el_t dst;
2739 pattern_set_el_t pat;
2740 struct unit_decl *unit;
2741 unit_set_el_t curr_excl_el;
2742 pattern_set_el_t curr_pat_el;
2743 pattern_set_el_t prev_el;
2744 pattern_set_el_t copy;
2745 int i;
2746 int no_error_flag;
2748 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2749 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2751 for (i = 0; i < pat->units_num; i++)
2753 unit = pat->unit_decls [i];
2754 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2756 error ("unit `%s' requires own absence", unit->name);
2757 continue;
2759 if (dst->unit_decl->automaton_name != NULL
2760 && unit->automaton_name != NULL
2761 && strcmp (dst->unit_decl->automaton_name,
2762 unit->automaton_name) != 0)
2764 error ((presence_p
2765 ? (final_p
2766 ? "units `%s' and `%s' in final presence set belong to different automata"
2767 : "units `%s' and `%s' in presence set belong to different automata")
2768 : (final_p
2769 ? "units `%s' and `%s' in final absence set belong to different automata"
2770 : "units `%s' and `%s' in absence set belong to different automata")),
2771 unit->name, dst->unit_decl->name);
2772 continue;
2774 no_error_flag = 1;
2775 if (presence_p)
2776 for (curr_excl_el = dst->unit_decl->excl_list;
2777 curr_excl_el != NULL;
2778 curr_excl_el = curr_excl_el->next_unit_set_el)
2780 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2782 if (!w_flag)
2784 error ("unit `%s' excludes and requires presence of `%s'",
2785 dst->unit_decl->name, unit->name);
2786 no_error_flag = 0;
2788 else
2789 warning
2790 ("unit `%s' excludes and requires presence of `%s'",
2791 dst->unit_decl->name, unit->name);
2794 else if (pat->units_num == 1)
2795 for (curr_pat_el = dst->unit_decl->presence_list;
2796 curr_pat_el != NULL;
2797 curr_pat_el = curr_pat_el->next_pattern_set_el)
2798 if (curr_pat_el->units_num == 1
2799 && unit == curr_pat_el->unit_decls [0])
2801 if (!w_flag)
2803 error
2804 ("unit `%s' requires absence and presence of `%s'",
2805 dst->unit_decl->name, unit->name);
2806 no_error_flag = 0;
2808 else
2809 warning
2810 ("unit `%s' requires absence and presence of `%s'",
2811 dst->unit_decl->name, unit->name);
2813 if (no_error_flag)
2815 for (prev_el = (presence_p
2816 ? (final_p
2817 ? dst->unit_decl->final_presence_list
2818 : dst->unit_decl->final_presence_list)
2819 : (final_p
2820 ? dst->unit_decl->final_absence_list
2821 : dst->unit_decl->absence_list));
2822 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2823 prev_el = prev_el->next_pattern_set_el)
2825 copy = copy_node (pat, sizeof (*pat));
2826 copy->next_pattern_set_el = NULL;
2827 if (prev_el == NULL)
2829 if (presence_p)
2831 if (final_p)
2832 dst->unit_decl->final_presence_list = copy;
2833 else
2834 dst->unit_decl->presence_list = copy;
2836 else if (final_p)
2837 dst->unit_decl->final_absence_list = copy;
2838 else
2839 dst->unit_decl->absence_list = copy;
2841 else
2842 prev_el->next_pattern_set_el = copy;
2849 /* The function searches for bypass with given IN_INSN_RESERV in given
2850 BYPASS_LIST. */
2851 static struct bypass_decl *
2852 find_bypass (bypass_list, in_insn_reserv)
2853 struct bypass_decl *bypass_list;
2854 struct insn_reserv_decl *in_insn_reserv;
2856 struct bypass_decl *bypass;
2858 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2859 if (bypass->in_insn_reserv == in_insn_reserv)
2860 break;
2861 return bypass;
2864 /* The function processes pipeline description declarations, checks
2865 their correctness, and forms exclusion/presence/absence sets. */
2866 static void
2867 process_decls ()
2869 decl_t decl;
2870 decl_t automaton_decl;
2871 decl_t decl_in_table;
2872 decl_t out_insn_reserv;
2873 decl_t in_insn_reserv;
2874 struct bypass_decl *bypass;
2875 int automaton_presence;
2876 int i;
2878 /* Checking repeated automata declarations. */
2879 automaton_presence = 0;
2880 for (i = 0; i < description->decls_num; i++)
2882 decl = description->decls [i];
2883 if (decl->mode == dm_automaton)
2885 automaton_presence = 1;
2886 decl_in_table = insert_automaton_decl (decl);
2887 if (decl_in_table != decl)
2889 if (!w_flag)
2890 error ("repeated declaration of automaton `%s'",
2891 DECL_AUTOMATON (decl)->name);
2892 else
2893 warning ("repeated declaration of automaton `%s'",
2894 DECL_AUTOMATON (decl)->name);
2898 /* Checking undeclared automata, repeated declarations (except for
2899 automata) and correctness of their attributes (insn latency times
2900 etc.). */
2901 for (i = 0; i < description->decls_num; i++)
2903 decl = description->decls [i];
2904 if (decl->mode == dm_insn_reserv)
2906 DECL_INSN_RESERV (decl)->condexp
2907 = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
2908 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2909 error ("define_insn_reservation `%s' has negative latency time",
2910 DECL_INSN_RESERV (decl)->name);
2911 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2912 description->insns_num++;
2913 decl_in_table = insert_insn_decl (decl);
2914 if (decl_in_table != decl)
2915 error ("`%s' is already used as insn reservation name",
2916 DECL_INSN_RESERV (decl)->name);
2918 else if (decl->mode == dm_bypass)
2920 if (DECL_BYPASS (decl)->latency < 0)
2921 error ("define_bypass `%s - %s' has negative latency time",
2922 DECL_BYPASS (decl)->out_insn_name,
2923 DECL_BYPASS (decl)->in_insn_name);
2925 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2927 if (decl->mode == dm_unit)
2929 DECL_UNIT (decl)->automaton_decl = NULL;
2930 if (DECL_UNIT (decl)->automaton_name != NULL)
2932 automaton_decl
2933 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2934 if (automaton_decl == NULL)
2935 error ("automaton `%s' is not declared",
2936 DECL_UNIT (decl)->automaton_name);
2937 else
2939 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2940 DECL_UNIT (decl)->automaton_decl
2941 = DECL_AUTOMATON (automaton_decl);
2944 else if (automaton_presence)
2945 error ("define_unit `%s' without automaton when one defined",
2946 DECL_UNIT (decl)->name);
2947 DECL_UNIT (decl)->unit_num = description->units_num;
2948 description->units_num++;
2949 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2951 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2952 continue;
2954 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2956 else
2958 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2960 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2961 continue;
2963 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2965 if (decl_in_table == NULL)
2966 decl_in_table = insert_decl (decl);
2967 else
2969 if (decl->mode == dm_unit)
2970 error ("repeated declaration of unit `%s'",
2971 DECL_UNIT (decl)->name);
2972 else
2973 error ("repeated declaration of reservation `%s'",
2974 DECL_RESERV (decl)->name);
2978 /* Check bypasses and form list of bypasses for each (output)
2979 insn. */
2980 for (i = 0; i < description->decls_num; i++)
2982 decl = description->decls [i];
2983 if (decl->mode == dm_bypass)
2985 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2986 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2987 if (out_insn_reserv == NULL)
2988 error ("there is no insn reservation `%s'",
2989 DECL_BYPASS (decl)->out_insn_name);
2990 else if (in_insn_reserv == NULL)
2991 error ("there is no insn reservation `%s'",
2992 DECL_BYPASS (decl)->in_insn_name);
2993 else
2995 DECL_BYPASS (decl)->out_insn_reserv
2996 = DECL_INSN_RESERV (out_insn_reserv);
2997 DECL_BYPASS (decl)->in_insn_reserv
2998 = DECL_INSN_RESERV (in_insn_reserv);
2999 bypass
3000 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
3001 DECL_BYPASS (decl)->in_insn_reserv);
3002 if (bypass != NULL)
3004 if (DECL_BYPASS (decl)->latency == bypass->latency)
3006 if (!w_flag)
3007 error
3008 ("the same bypass `%s - %s' is already defined",
3009 DECL_BYPASS (decl)->out_insn_name,
3010 DECL_BYPASS (decl)->in_insn_name);
3011 else
3012 warning
3013 ("the same bypass `%s - %s' is already defined",
3014 DECL_BYPASS (decl)->out_insn_name,
3015 DECL_BYPASS (decl)->in_insn_name);
3017 else
3018 error ("bypass `%s - %s' is already defined",
3019 DECL_BYPASS (decl)->out_insn_name,
3020 DECL_BYPASS (decl)->in_insn_name);
3022 else
3024 DECL_BYPASS (decl)->next
3025 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
3026 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
3027 = DECL_BYPASS (decl);
3033 /* Check exclusion set declarations and form exclusion sets. */
3034 for (i = 0; i < description->decls_num; i++)
3036 decl = description->decls [i];
3037 if (decl->mode == dm_excl)
3039 unit_set_el_t unit_set_el_list;
3040 unit_set_el_t unit_set_el_list_2;
3042 unit_set_el_list
3043 = process_excls (DECL_EXCL (decl)->names,
3044 DECL_EXCL (decl)->first_list_length, decl->pos);
3045 unit_set_el_list_2
3046 = process_excls (&DECL_EXCL (decl)->names
3047 [DECL_EXCL (decl)->first_list_length],
3048 DECL_EXCL (decl)->all_names_num
3049 - DECL_EXCL (decl)->first_list_length,
3050 decl->pos);
3051 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
3052 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
3056 /* Check presence set declarations and form presence sets. */
3057 for (i = 0; i < description->decls_num; i++)
3059 decl = description->decls [i];
3060 if (decl->mode == dm_presence)
3062 unit_set_el_t unit_set_el_list;
3063 pattern_set_el_t pattern_set_el_list;
3065 unit_set_el_list
3066 = process_presence_absence_names
3067 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
3068 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
3069 pattern_set_el_list
3070 = process_presence_absence_patterns
3071 (DECL_PRESENCE (decl)->patterns,
3072 DECL_PRESENCE (decl)->patterns_num,
3073 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
3074 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3075 decl->pos, TRUE,
3076 DECL_PRESENCE (decl)->final_p);
3080 /* Check absence set declarations and form absence sets. */
3081 for (i = 0; i < description->decls_num; i++)
3083 decl = description->decls [i];
3084 if (decl->mode == dm_absence)
3086 unit_set_el_t unit_set_el_list;
3087 pattern_set_el_t pattern_set_el_list;
3089 unit_set_el_list
3090 = process_presence_absence_names
3091 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
3092 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3093 pattern_set_el_list
3094 = process_presence_absence_patterns
3095 (DECL_ABSENCE (decl)->patterns,
3096 DECL_ABSENCE (decl)->patterns_num,
3097 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3098 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3099 decl->pos, FALSE,
3100 DECL_ABSENCE (decl)->final_p);
3105 /* The following function checks that declared automaton is used. If
3106 the automaton is not used, the function fixes error/warning. The
3107 following function must be called only after `process_decls'. */
3108 static void
3109 check_automaton_usage ()
3111 decl_t decl;
3112 int i;
3114 for (i = 0; i < description->decls_num; i++)
3116 decl = description->decls [i];
3117 if (decl->mode == dm_automaton
3118 && !DECL_AUTOMATON (decl)->automaton_is_used)
3120 if (!w_flag)
3121 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
3122 else
3123 warning ("automaton `%s' is not used",
3124 DECL_AUTOMATON (decl)->name);
3129 /* The following recursive function processes all regexp in order to
3130 fix usage of units or reservations and to fix errors of undeclared
3131 name. The function may change unit_regexp onto reserv_regexp.
3132 Remember that reserv_regexp does not exist before the function
3133 call. */
3134 static regexp_t
3135 process_regexp (regexp)
3136 regexp_t regexp;
3138 decl_t decl_in_table;
3139 regexp_t new_regexp;
3140 int i;
3142 if (regexp->mode == rm_unit)
3144 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
3145 if (decl_in_table == NULL)
3146 error ("undeclared unit or reservation `%s'",
3147 REGEXP_UNIT (regexp)->name);
3148 else if (decl_in_table->mode == dm_unit)
3150 DECL_UNIT (decl_in_table)->unit_is_used = 1;
3151 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
3153 else if (decl_in_table->mode == dm_reserv)
3155 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
3156 new_regexp = create_node (sizeof (struct regexp));
3157 new_regexp->mode = rm_reserv;
3158 new_regexp->pos = regexp->pos;
3159 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
3160 REGEXP_RESERV (new_regexp)->reserv_decl
3161 = DECL_RESERV (decl_in_table);
3162 regexp = new_regexp;
3164 else
3165 abort ();
3167 else if (regexp->mode == rm_sequence)
3168 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3169 REGEXP_SEQUENCE (regexp)->regexps [i]
3170 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
3171 else if (regexp->mode == rm_allof)
3172 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3173 REGEXP_ALLOF (regexp)->regexps [i]
3174 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
3175 else if (regexp->mode == rm_oneof)
3176 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3177 REGEXP_ONEOF (regexp)->regexps [i]
3178 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
3179 else if (regexp->mode == rm_repeat)
3180 REGEXP_REPEAT (regexp)->regexp
3181 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
3182 else if (regexp->mode != rm_nothing)
3183 abort ();
3184 return regexp;
3187 /* The following function processes regexp of define_reservation and
3188 define_insn_reservation with the aid of function
3189 `process_regexp'. */
3190 static void
3191 process_regexp_decls ()
3193 decl_t decl;
3194 int i;
3196 for (i = 0; i < description->decls_num; i++)
3198 decl = description->decls [i];
3199 if (decl->mode == dm_reserv)
3200 DECL_RESERV (decl)->regexp
3201 = process_regexp (DECL_RESERV (decl)->regexp);
3202 else if (decl->mode == dm_insn_reserv)
3203 DECL_INSN_RESERV (decl)->regexp
3204 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3208 /* The following function checks that declared unit is used. If the
3209 unit is not used, the function fixes errors/warnings. The
3210 following function must be called only after `process_decls',
3211 `process_regexp_decls'. */
3212 static void
3213 check_usage ()
3215 decl_t decl;
3216 int i;
3218 for (i = 0; i < description->decls_num; i++)
3220 decl = description->decls [i];
3221 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3223 if (!w_flag)
3224 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3225 else
3226 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3228 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3230 if (!w_flag)
3231 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3232 else
3233 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3238 /* The following variable value is number of reservation being
3239 processed on loop recognition. */
3240 static int curr_loop_pass_num;
3242 /* The following recursive function returns nonzero value if REGEXP
3243 contains given decl or reservations in given regexp refers for
3244 given decl. */
3245 static int
3246 loop_in_regexp (regexp, start_decl)
3247 regexp_t regexp;
3248 decl_t start_decl;
3250 int i;
3252 if (regexp == NULL)
3253 return 0;
3254 if (regexp->mode == rm_unit)
3255 return 0;
3256 else if (regexp->mode == rm_reserv)
3258 if (start_decl->mode == dm_reserv
3259 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3260 return 1;
3261 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3262 == curr_loop_pass_num)
3263 /* declaration has been processed. */
3264 return 0;
3265 else
3267 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3268 = curr_loop_pass_num;
3269 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3270 start_decl);
3273 else if (regexp->mode == rm_sequence)
3275 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3276 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3277 return 1;
3278 return 0;
3280 else if (regexp->mode == rm_allof)
3282 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3283 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3284 return 1;
3285 return 0;
3287 else if (regexp->mode == rm_oneof)
3289 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3290 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3291 return 1;
3292 return 0;
3294 else if (regexp->mode == rm_repeat)
3295 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3296 else
3298 if (regexp->mode != rm_nothing)
3299 abort ();
3300 return 0;
3304 /* The following function fixes errors "cycle in definition ...". The
3305 function uses function `loop_in_regexp' for that. */
3306 static void
3307 check_loops_in_regexps ()
3309 decl_t decl;
3310 int i;
3312 for (i = 0; i < description->decls_num; i++)
3314 decl = description->decls [i];
3315 if (decl->mode == dm_reserv)
3316 DECL_RESERV (decl)->loop_pass_num = 0;
3318 for (i = 0; i < description->decls_num; i++)
3320 decl = description->decls [i];
3321 curr_loop_pass_num = i;
3323 if (decl->mode == dm_reserv)
3325 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
3326 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3328 if (DECL_RESERV (decl)->regexp == NULL)
3329 abort ();
3330 error ("cycle in definition of reservation `%s'",
3331 DECL_RESERV (decl)->name);
3337 /* The function recursively processes IR of reservation and defines
3338 max and min cycle for reservation of unit. */
3339 static void
3340 process_regexp_cycles (regexp, max_start_cycle, min_start_cycle,
3341 max_finish_cycle, min_finish_cycle)
3342 regexp_t regexp;
3343 int max_start_cycle, min_start_cycle;
3344 int *max_finish_cycle, *min_finish_cycle;
3346 int i;
3348 if (regexp->mode == rm_unit)
3350 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
3351 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
3352 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
3353 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
3354 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
3355 *max_finish_cycle = max_start_cycle;
3356 *min_finish_cycle = min_start_cycle;
3358 else if (regexp->mode == rm_reserv)
3359 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3360 max_start_cycle, min_start_cycle,
3361 max_finish_cycle, min_finish_cycle);
3362 else if (regexp->mode == rm_repeat)
3364 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3366 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3367 max_start_cycle, min_start_cycle,
3368 max_finish_cycle, min_finish_cycle);
3369 max_start_cycle = *max_finish_cycle + 1;
3370 min_start_cycle = *min_finish_cycle + 1;
3373 else if (regexp->mode == rm_sequence)
3375 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3377 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3378 max_start_cycle, min_start_cycle,
3379 max_finish_cycle, min_finish_cycle);
3380 max_start_cycle = *max_finish_cycle + 1;
3381 min_start_cycle = *min_finish_cycle + 1;
3384 else if (regexp->mode == rm_allof)
3386 int max_cycle = 0;
3387 int min_cycle = 0;
3389 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3391 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3392 max_start_cycle, min_start_cycle,
3393 max_finish_cycle, min_finish_cycle);
3394 if (max_cycle < *max_finish_cycle)
3395 max_cycle = *max_finish_cycle;
3396 if (i == 0 || min_cycle > *min_finish_cycle)
3397 min_cycle = *min_finish_cycle;
3399 *max_finish_cycle = max_cycle;
3400 *min_finish_cycle = min_cycle;
3402 else if (regexp->mode == rm_oneof)
3404 int max_cycle = 0;
3405 int min_cycle = 0;
3407 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3409 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3410 max_start_cycle, min_start_cycle,
3411 max_finish_cycle, min_finish_cycle);
3412 if (max_cycle < *max_finish_cycle)
3413 max_cycle = *max_finish_cycle;
3414 if (i == 0 || min_cycle > *min_finish_cycle)
3415 min_cycle = *min_finish_cycle;
3417 *max_finish_cycle = max_cycle;
3418 *min_finish_cycle = min_cycle;
3420 else
3422 if (regexp->mode != rm_nothing)
3423 abort ();
3424 *max_finish_cycle = max_start_cycle;
3425 *min_finish_cycle = min_start_cycle;
3429 /* The following function is called only for correct program. The
3430 function defines max reservation of insns in cycles. */
3431 static void
3432 evaluate_max_reserv_cycles ()
3434 int max_insn_cycles_num;
3435 int min_insn_cycles_num;
3436 decl_t decl;
3437 int i;
3439 description->max_insn_reserv_cycles = 0;
3440 for (i = 0; i < description->decls_num; i++)
3442 decl = description->decls [i];
3443 if (decl->mode == dm_insn_reserv)
3445 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3446 &max_insn_cycles_num, &min_insn_cycles_num);
3447 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3448 description->max_insn_reserv_cycles = max_insn_cycles_num;
3451 description->max_insn_reserv_cycles++;
3454 /* The following function calls functions for checking all
3455 description. */
3456 static void
3457 check_all_description ()
3459 process_decls ();
3460 check_automaton_usage ();
3461 process_regexp_decls ();
3462 check_usage ();
3463 check_loops_in_regexps ();
3464 if (!have_error)
3465 evaluate_max_reserv_cycles ();
3470 /* The page contains abstract data `ticker'. This data is used to
3471 report time of different phases of building automata. It is
3472 possibly to write a description for which automata will be built
3473 during several minutes even on fast machine. */
3475 /* The following function creates ticker and makes it active. */
3476 static ticker_t
3477 create_ticker ()
3479 ticker_t ticker;
3481 ticker.modified_creation_time = get_run_time ();
3482 ticker.incremented_off_time = 0;
3483 return ticker;
3486 /* The following function switches off given ticker. */
3487 static void
3488 ticker_off (ticker)
3489 ticker_t *ticker;
3491 if (ticker->incremented_off_time == 0)
3492 ticker->incremented_off_time = get_run_time () + 1;
3495 /* The following function switches on given ticker. */
3496 static void
3497 ticker_on (ticker)
3498 ticker_t *ticker;
3500 if (ticker->incremented_off_time != 0)
3502 ticker->modified_creation_time
3503 += get_run_time () - ticker->incremented_off_time + 1;
3504 ticker->incremented_off_time = 0;
3508 /* The following function returns current time in milliseconds since
3509 the moment when given ticker was created. */
3510 static int
3511 active_time (ticker)
3512 ticker_t ticker;
3514 if (ticker.incremented_off_time != 0)
3515 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3516 else
3517 return get_run_time () - ticker.modified_creation_time;
3520 /* The following function returns string representation of active time
3521 of given ticker. The result is string representation of seconds
3522 with accuracy of 1/100 second. Only result of the last call of the
3523 function exists. Therefore the following code is not correct
3525 printf ("parser time: %s\ngeneration time: %s\n",
3526 active_time_string (parser_ticker),
3527 active_time_string (generation_ticker));
3529 Correct code has to be the following
3531 printf ("parser time: %s\n", active_time_string (parser_ticker));
3532 printf ("generation time: %s\n",
3533 active_time_string (generation_ticker));
3536 static void
3537 print_active_time (f, ticker)
3538 FILE *f;
3539 ticker_t ticker;
3541 int msecs;
3543 msecs = active_time (ticker);
3544 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3549 /* The following variable value is number of automaton which are
3550 really being created. This value is defined on the base of
3551 argument of option `-split'. If the variable has zero value the
3552 number of automata is defined by the constructions `%automaton'.
3553 This case occurs when option `-split' is absent or has zero
3554 argument. If constructions `define_automaton' is absent only one
3555 automaton is created. */
3556 static int automata_num;
3558 /* The following variable values are times of
3559 o transformation of regular expressions
3560 o building NDFA (DFA if !ndfa_flag)
3561 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3562 o DFA minimization
3563 o building insn equivalence classes
3564 o all previous ones
3565 o code output */
3566 static ticker_t transform_time;
3567 static ticker_t NDFA_time;
3568 static ticker_t NDFA_to_DFA_time;
3569 static ticker_t minimize_time;
3570 static ticker_t equiv_time;
3571 static ticker_t automaton_generation_time;
3572 static ticker_t output_time;
3574 /* The following variable values are times of
3575 all checking
3576 all generation
3577 all pipeline hazard translator work */
3578 static ticker_t check_time;
3579 static ticker_t generation_time;
3580 static ticker_t all_time;
3584 /* Pseudo insn decl which denotes advancing cycle. */
3585 static decl_t advance_cycle_insn_decl;
3586 static void
3587 add_advance_cycle_insn_decl ()
3589 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3590 advance_cycle_insn_decl->mode = dm_insn_reserv;
3591 advance_cycle_insn_decl->pos = no_pos;
3592 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3593 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
3594 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3595 = description->insns_num;
3596 description->decls [description->decls_num] = advance_cycle_insn_decl;
3597 description->decls_num++;
3598 description->insns_num++;
3599 num_dfa_decls++;
3603 /* Abstract data `alternative states' which represents
3604 nondeterministic nature of the description (see comments for
3605 structures alt_state and state). */
3607 /* List of free states. */
3608 static alt_state_t first_free_alt_state;
3610 #ifndef NDEBUG
3611 /* The following variables is maximal number of allocated nodes
3612 alt_state. */
3613 static int allocated_alt_states_num = 0;
3614 #endif
3616 /* The following function returns free node alt_state. It may be new
3617 allocated node or node freed earlier. */
3618 static alt_state_t
3619 get_free_alt_state ()
3621 alt_state_t result;
3623 if (first_free_alt_state != NULL)
3625 result = first_free_alt_state;
3626 first_free_alt_state = first_free_alt_state->next_alt_state;
3628 else
3630 #ifndef NDEBUG
3631 allocated_alt_states_num++;
3632 #endif
3633 result = create_node (sizeof (struct alt_state));
3635 result->state = NULL;
3636 result->next_alt_state = NULL;
3637 result->next_sorted_alt_state = NULL;
3638 return result;
3641 /* The function frees node ALT_STATE. */
3642 static void
3643 free_alt_state (alt_state)
3644 alt_state_t alt_state;
3646 if (alt_state == NULL)
3647 return;
3648 alt_state->next_alt_state = first_free_alt_state;
3649 first_free_alt_state = alt_state;
3652 /* The function frees list started with node ALT_STATE_LIST. */
3653 static void
3654 free_alt_states (alt_states_list)
3655 alt_state_t alt_states_list;
3657 alt_state_t curr_alt_state;
3658 alt_state_t next_alt_state;
3660 for (curr_alt_state = alt_states_list;
3661 curr_alt_state != NULL;
3662 curr_alt_state = next_alt_state)
3664 next_alt_state = curr_alt_state->next_alt_state;
3665 free_alt_state (curr_alt_state);
3669 /* The function compares unique numbers of alt states. */
3670 static int
3671 alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
3672 const void *alt_state_ptr_1;
3673 const void *alt_state_ptr_2;
3675 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3676 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3677 return 0;
3678 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3679 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3680 return -1;
3681 else
3682 return 1;
3685 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3686 states from the list. The comparison key is alt state unique
3687 number. */
3688 static alt_state_t
3689 uniq_sort_alt_states (alt_states_list)
3690 alt_state_t alt_states_list;
3692 alt_state_t curr_alt_state;
3693 vla_ptr_t alt_states;
3694 size_t i;
3695 size_t prev_unique_state_ind;
3696 alt_state_t result;
3697 alt_state_t *result_ptr;
3699 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3700 for (curr_alt_state = alt_states_list;
3701 curr_alt_state != NULL;
3702 curr_alt_state = curr_alt_state->next_alt_state)
3703 VLA_PTR_ADD (alt_states, curr_alt_state);
3704 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3705 sizeof (alt_state_t), alt_state_cmp);
3706 if (VLA_PTR_LENGTH (alt_states) == 0)
3707 result = NULL;
3708 else
3710 result_ptr = VLA_PTR_BEGIN (alt_states);
3711 prev_unique_state_ind = 0;
3712 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3713 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3715 prev_unique_state_ind++;
3716 result_ptr [prev_unique_state_ind] = result_ptr [i];
3718 #if 0
3719 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3720 free_alt_state (result_ptr [i]);
3721 #endif
3722 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3723 result_ptr = VLA_PTR_BEGIN (alt_states);
3724 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3725 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3726 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3727 result = *result_ptr;
3729 VLA_PTR_DELETE (alt_states);
3730 return result;
3733 /* The function checks equality of alt state lists. Remember that the
3734 lists must be already sorted by the previous function. */
3735 static int
3736 alt_states_eq (alt_states_1, alt_states_2)
3737 alt_state_t alt_states_1;
3738 alt_state_t alt_states_2;
3740 while (alt_states_1 != NULL && alt_states_2 != NULL
3741 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3743 alt_states_1 = alt_states_1->next_sorted_alt_state;
3744 alt_states_2 = alt_states_2->next_sorted_alt_state;
3746 return alt_states_1 == alt_states_2;
3749 /* Initialization of the abstract data. */
3750 static void
3751 initiate_alt_states ()
3753 first_free_alt_state = NULL;
3756 /* Finishing work with the abstract data. */
3757 static void
3758 finish_alt_states ()
3764 /* The page contains macros for work with bits strings. We could use
3765 standard gcc bitmap or sbitmap but it would result in difficulties
3766 of building canadian cross. */
3768 /* Set bit number bitno in the bit string. The macro is not side
3769 effect proof. */
3770 #define SET_BIT(bitstring, bitno) \
3771 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3773 #define CLEAR_BIT(bitstring, bitno) \
3774 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3776 /* Test if bit number bitno in the bitstring is set. The macro is not
3777 side effect proof. */
3778 #define TEST_BIT(bitstring, bitno) \
3779 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3783 /* This page contains abstract data `state'. */
3785 /* Maximal length of reservations in cycles (>= 1). */
3786 static int max_cycles_num;
3788 /* Number of set elements (see type set_el_t) needed for
3789 representation of one cycle reservation. It is depended on units
3790 number. */
3791 static int els_in_cycle_reserv;
3793 /* Number of set elements (see type set_el_t) needed for
3794 representation of maximal length reservation. Deterministic
3795 reservation is stored as set (bit string) of length equal to the
3796 variable value * number of bits in set_el_t. */
3797 static int els_in_reservs;
3799 /* VLA for representation of array of pointers to unit
3800 declarations. */
3801 static vla_ptr_t units_container;
3803 /* The start address of the array. */
3804 static unit_decl_t *units_array;
3806 /* Temporary reservation of maximal length. */
3807 static reserv_sets_t temp_reserv;
3809 /* The state table itself is represented by the following variable. */
3810 static htab_t state_table;
3812 /* VLA for representation of array of pointers to free nodes
3813 `state'. */
3814 static vla_ptr_t free_states;
3816 static int curr_unique_state_num;
3818 #ifndef NDEBUG
3819 /* The following variables is maximal number of allocated nodes
3820 `state'. */
3821 static int allocated_states_num = 0;
3822 #endif
3824 /* Allocate new reservation set. */
3825 static reserv_sets_t
3826 alloc_empty_reserv_sets ()
3828 reserv_sets_t result;
3830 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3831 result = (reserv_sets_t) obstack_base (&irp);
3832 obstack_finish (&irp);
3833 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3834 return result;
3837 /* Hash value of reservation set. */
3838 static unsigned
3839 reserv_sets_hash_value (reservs)
3840 reserv_sets_t reservs;
3842 set_el_t hash_value;
3843 unsigned result;
3844 int reservs_num, i;
3845 set_el_t *reserv_ptr;
3847 hash_value = 0;
3848 reservs_num = els_in_reservs;
3849 reserv_ptr = reservs;
3850 i = 0;
3851 while (reservs_num != 0)
3853 reservs_num--;
3854 hash_value += ((*reserv_ptr >> i)
3855 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3856 i++;
3857 if (i == sizeof (set_el_t) * CHAR_BIT)
3858 i = 0;
3859 reserv_ptr++;
3861 if (sizeof (set_el_t) <= sizeof (unsigned))
3862 return hash_value;
3863 result = 0;
3864 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3866 result += (unsigned) hash_value;
3867 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3869 return result;
3872 /* Comparison of given reservation sets. */
3873 static int
3874 reserv_sets_cmp (reservs_1, reservs_2)
3875 reserv_sets_t reservs_1;
3876 reserv_sets_t reservs_2;
3878 int reservs_num;
3879 set_el_t *reserv_ptr_1;
3880 set_el_t *reserv_ptr_2;
3882 if (reservs_1 == NULL || reservs_2 == NULL)
3883 abort ();
3884 reservs_num = els_in_reservs;
3885 reserv_ptr_1 = reservs_1;
3886 reserv_ptr_2 = reservs_2;
3887 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3889 reservs_num--;
3890 reserv_ptr_1++;
3891 reserv_ptr_2++;
3893 if (reservs_num == 0)
3894 return 0;
3895 else if (*reserv_ptr_1 < *reserv_ptr_2)
3896 return -1;
3897 else
3898 return 1;
3901 /* The function checks equality of the reservation sets. */
3902 static int
3903 reserv_sets_eq (reservs_1, reservs_2)
3904 reserv_sets_t reservs_1;
3905 reserv_sets_t reservs_2;
3907 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3910 /* Set up in the reservation set that unit with UNIT_NUM is used on
3911 CYCLE_NUM. */
3912 static void
3913 set_unit_reserv (reservs, cycle_num, unit_num)
3914 reserv_sets_t reservs;
3915 int cycle_num;
3916 int unit_num;
3918 if (cycle_num >= max_cycles_num)
3919 abort ();
3920 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3921 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3924 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3925 used on CYCLE_NUM. */
3926 static int
3927 test_unit_reserv (reservs, cycle_num, unit_num)
3928 reserv_sets_t reservs;
3929 int cycle_num;
3930 int unit_num;
3932 if (cycle_num >= max_cycles_num)
3933 abort ();
3934 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3935 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3938 /* The function checks that the reservation set represents no one unit
3939 reservation. */
3940 static int
3941 it_is_empty_reserv_sets (operand)
3942 reserv_sets_t operand;
3944 set_el_t *reserv_ptr;
3945 int reservs_num;
3947 if (operand == NULL)
3948 abort ();
3949 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3950 reservs_num != 0;
3951 reserv_ptr++, reservs_num--)
3952 if (*reserv_ptr != 0)
3953 return 0;
3954 return 1;
3957 /* The function checks that the reservation sets are intersected,
3958 i.e. there is a unit reservation on a cycle in both reservation
3959 sets. */
3960 static int
3961 reserv_sets_are_intersected (operand_1, operand_2)
3962 reserv_sets_t operand_1;
3963 reserv_sets_t operand_2;
3965 set_el_t *el_ptr_1;
3966 set_el_t *el_ptr_2;
3967 set_el_t *cycle_ptr_1;
3968 set_el_t *cycle_ptr_2;
3970 if (operand_1 == NULL || operand_2 == NULL)
3971 abort ();
3972 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3973 el_ptr_1 < operand_1 + els_in_reservs;
3974 el_ptr_1++, el_ptr_2++)
3975 if (*el_ptr_1 & *el_ptr_2)
3976 return 1;
3977 reserv_sets_or (temp_reserv, operand_1, operand_2);
3978 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3979 cycle_ptr_1 < operand_1 + els_in_reservs;
3980 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3982 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3983 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3984 el_ptr_1++, el_ptr_2++)
3985 if (*el_ptr_1 & *el_ptr_2)
3986 return 1;
3987 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3988 return 1;
3989 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3990 - operand_2),
3991 cycle_ptr_2, TRUE))
3992 return 1;
3993 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3994 return 1;
3995 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3996 cycle_ptr_2, TRUE))
3997 return 1;
3999 return 0;
4002 /* The function sets up RESULT bits by bits of OPERAND shifted on one
4003 cpu cycle. The remaining bits of OPERAND (representing the last
4004 cycle unit reservations) are not changed. */
4005 static void
4006 reserv_sets_shift (result, operand)
4007 reserv_sets_t result;
4008 reserv_sets_t operand;
4010 int i;
4012 if (result == NULL || operand == NULL || result == operand)
4013 abort ();
4014 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
4015 result [i - els_in_cycle_reserv] = operand [i];
4018 /* OR of the reservation sets. */
4019 static void
4020 reserv_sets_or (result, operand_1, operand_2)
4021 reserv_sets_t result;
4022 reserv_sets_t operand_1;
4023 reserv_sets_t operand_2;
4025 set_el_t *el_ptr_1;
4026 set_el_t *el_ptr_2;
4027 set_el_t *result_set_el_ptr;
4029 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
4030 abort ();
4031 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
4032 el_ptr_1 < operand_1 + els_in_reservs;
4033 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
4034 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
4037 /* AND of the reservation sets. */
4038 static void
4039 reserv_sets_and (result, operand_1, operand_2)
4040 reserv_sets_t result;
4041 reserv_sets_t operand_1;
4042 reserv_sets_t operand_2;
4044 set_el_t *el_ptr_1;
4045 set_el_t *el_ptr_2;
4046 set_el_t *result_set_el_ptr;
4048 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
4049 abort ();
4050 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
4051 el_ptr_1 < operand_1 + els_in_reservs;
4052 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
4053 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
4056 /* The function outputs string representation of units reservation on
4057 cycle START_CYCLE in the reservation set. The function uses repeat
4058 construction if REPETITION_NUM > 1. */
4059 static void
4060 output_cycle_reservs (f, reservs, start_cycle, repetition_num)
4061 FILE *f;
4062 reserv_sets_t reservs;
4063 int start_cycle;
4064 int repetition_num;
4066 int unit_num;
4067 int reserved_units_num;
4069 reserved_units_num = 0;
4070 for (unit_num = 0; unit_num < description->units_num; unit_num++)
4071 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
4072 * sizeof (set_el_t) * CHAR_BIT + unit_num))
4073 reserved_units_num++;
4074 if (repetition_num <= 0)
4075 abort ();
4076 if (repetition_num != 1 && reserved_units_num > 1)
4077 fprintf (f, "(");
4078 reserved_units_num = 0;
4079 for (unit_num = 0;
4080 unit_num < description->units_num;
4081 unit_num++)
4082 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
4083 * sizeof (set_el_t) * CHAR_BIT + unit_num))
4085 if (reserved_units_num != 0)
4086 fprintf (f, "+");
4087 reserved_units_num++;
4088 fprintf (f, "%s", units_array [unit_num]->name);
4090 if (reserved_units_num == 0)
4091 fprintf (f, NOTHING_NAME);
4092 if (repetition_num <= 0)
4093 abort ();
4094 if (repetition_num != 1 && reserved_units_num > 1)
4095 fprintf (f, ")");
4096 if (repetition_num != 1)
4097 fprintf (f, "*%d", repetition_num);
4100 /* The function outputs string representation of units reservation in
4101 the reservation set. */
4102 static void
4103 output_reserv_sets (f, reservs)
4104 FILE *f;
4105 reserv_sets_t reservs;
4107 int start_cycle = 0;
4108 int cycle;
4109 int repetition_num;
4111 repetition_num = 0;
4112 for (cycle = 0; cycle < max_cycles_num; cycle++)
4113 if (repetition_num == 0)
4115 repetition_num++;
4116 start_cycle = cycle;
4118 else if (memcmp
4119 ((char *) reservs + start_cycle * els_in_cycle_reserv
4120 * sizeof (set_el_t),
4121 (char *) reservs + cycle * els_in_cycle_reserv
4122 * sizeof (set_el_t),
4123 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
4124 repetition_num++;
4125 else
4127 if (start_cycle != 0)
4128 fprintf (f, ", ");
4129 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
4130 repetition_num = 1;
4131 start_cycle = cycle;
4133 if (start_cycle < max_cycles_num)
4135 if (start_cycle != 0)
4136 fprintf (f, ", ");
4137 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
4141 /* The following function returns free node state for AUTOMATON. It
4142 may be new allocated node or node freed earlier. The function also
4143 allocates reservation set if WITH_RESERVS has nonzero value. */
4144 static state_t
4145 get_free_state (with_reservs, automaton)
4146 int with_reservs;
4147 automaton_t automaton;
4149 state_t result;
4151 if (max_cycles_num <= 0 || automaton == NULL)
4152 abort ();
4153 if (VLA_PTR_LENGTH (free_states) != 0)
4155 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
4156 VLA_PTR_SHORTEN (free_states, 1);
4157 result->automaton = automaton;
4158 result->first_out_arc = NULL;
4159 result->it_was_placed_in_stack_for_NDFA_forming = 0;
4160 result->it_was_placed_in_stack_for_DFA_forming = 0;
4161 result->component_states = NULL;
4162 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
4164 else
4166 #ifndef NDEBUG
4167 allocated_states_num++;
4168 #endif
4169 result = create_node (sizeof (struct state));
4170 result->automaton = automaton;
4171 result->first_out_arc = NULL;
4172 result->unique_num = curr_unique_state_num;
4173 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
4174 curr_unique_state_num++;
4176 if (with_reservs)
4178 if (result->reservs == NULL)
4179 result->reservs = alloc_empty_reserv_sets ();
4180 else
4181 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
4183 return result;
4186 /* The function frees node STATE. */
4187 static void
4188 free_state (state)
4189 state_t state;
4191 free_alt_states (state->component_states);
4192 VLA_PTR_ADD (free_states, state);
4195 /* Hash value of STATE. If STATE represents deterministic state it is
4196 simply hash value of the corresponding reservation set. Otherwise
4197 it is formed from hash values of the component deterministic
4198 states. One more key is order number of state automaton. */
4199 static hashval_t
4200 state_hash (state)
4201 const void *state;
4203 unsigned int hash_value;
4204 alt_state_t alt_state;
4206 if (((state_t) state)->component_states == NULL)
4207 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
4208 else
4210 hash_value = 0;
4211 for (alt_state = ((state_t) state)->component_states;
4212 alt_state != NULL;
4213 alt_state = alt_state->next_sorted_alt_state)
4214 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4215 | (hash_value << CHAR_BIT))
4216 + alt_state->state->unique_num);
4218 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4219 | (hash_value << CHAR_BIT))
4220 + ((state_t) state)->automaton->automaton_order_num);
4221 return hash_value;
4224 /* Return nonzero value if the states are the same. */
4225 static int
4226 state_eq_p (state_1, state_2)
4227 const void *state_1;
4228 const void *state_2;
4230 alt_state_t alt_state_1;
4231 alt_state_t alt_state_2;
4233 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
4234 return 0;
4235 else if (((state_t) state_1)->component_states == NULL
4236 && ((state_t) state_2)->component_states == NULL)
4237 return reserv_sets_eq (((state_t) state_1)->reservs,
4238 ((state_t) state_2)->reservs);
4239 else if (((state_t) state_1)->component_states != NULL
4240 && ((state_t) state_2)->component_states != NULL)
4242 for (alt_state_1 = ((state_t) state_1)->component_states,
4243 alt_state_2 = ((state_t) state_2)->component_states;
4244 alt_state_1 != NULL && alt_state_2 != NULL;
4245 alt_state_1 = alt_state_1->next_sorted_alt_state,
4246 alt_state_2 = alt_state_2->next_sorted_alt_state)
4247 /* All state in the list must be already in the hash table.
4248 Also the lists must be sorted. */
4249 if (alt_state_1->state != alt_state_2->state)
4250 return 0;
4251 return alt_state_1 == alt_state_2;
4253 else
4254 return 0;
4257 /* Insert STATE into the state table. */
4258 static state_t
4259 insert_state (state)
4260 state_t state;
4262 void **entry_ptr;
4264 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
4265 if (*entry_ptr == NULL)
4266 *entry_ptr = (void *) state;
4267 return (state_t) *entry_ptr;
4270 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4271 deterministic STATE. */
4272 static void
4273 set_state_reserv (state, cycle_num, unit_num)
4274 state_t state;
4275 int cycle_num;
4276 int unit_num;
4278 set_unit_reserv (state->reservs, cycle_num, unit_num);
4281 /* Return nonzero value if the deterministic states contains a
4282 reservation of the same cpu unit on the same cpu cycle. */
4283 static int
4284 intersected_state_reservs_p (state1, state2)
4285 state_t state1;
4286 state_t state2;
4288 if (state1->automaton != state2->automaton)
4289 abort ();
4290 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
4293 /* Return deterministic state (inserted into the table) which
4294 representing the automaton state which is union of reservations of
4295 the deterministic states masked by RESERVS. */
4296 static state_t
4297 states_union (state1, state2, reservs)
4298 state_t state1;
4299 state_t state2;
4300 reserv_sets_t reservs;
4302 state_t result;
4303 state_t state_in_table;
4305 if (state1->automaton != state2->automaton)
4306 abort ();
4307 result = get_free_state (1, state1->automaton);
4308 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
4309 reserv_sets_and (result->reservs, result->reservs, reservs);
4310 state_in_table = insert_state (result);
4311 if (result != state_in_table)
4313 free_state (result);
4314 result = state_in_table;
4316 return result;
4319 /* Return deterministic state (inserted into the table) which
4320 represent the automaton state is obtained from deterministic STATE
4321 by advancing cpu cycle and masking by RESERVS. */
4322 static state_t
4323 state_shift (state, reservs)
4324 state_t state;
4325 reserv_sets_t reservs;
4327 state_t result;
4328 state_t state_in_table;
4330 result = get_free_state (1, state->automaton);
4331 reserv_sets_shift (result->reservs, state->reservs);
4332 reserv_sets_and (result->reservs, result->reservs, reservs);
4333 state_in_table = insert_state (result);
4334 if (result != state_in_table)
4336 free_state (result);
4337 result = state_in_table;
4339 return result;
4342 /* Initialization of the abstract data. */
4343 static void
4344 initiate_states ()
4346 decl_t decl;
4347 int i;
4349 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
4350 units_array
4351 = (description->decls_num && description->units_num
4352 ? VLA_PTR_BEGIN (units_container) : NULL);
4353 for (i = 0; i < description->decls_num; i++)
4355 decl = description->decls [i];
4356 if (decl->mode == dm_unit)
4357 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
4359 max_cycles_num = description->max_insn_reserv_cycles;
4360 els_in_cycle_reserv
4361 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
4362 / (sizeof (set_el_t) * CHAR_BIT));
4363 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
4364 curr_unique_state_num = 0;
4365 initiate_alt_states ();
4366 VLA_PTR_CREATE (free_states, 1500, "free states");
4367 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
4368 temp_reserv = alloc_empty_reserv_sets ();
4371 /* Finishing work with the abstract data. */
4372 static void
4373 finish_states ()
4375 VLA_PTR_DELETE (units_container);
4376 htab_delete (state_table);
4377 VLA_PTR_DELETE (free_states);
4378 finish_alt_states ();
4383 /* Abstract data `arcs'. */
4385 /* List of free arcs. */
4386 static arc_t first_free_arc;
4388 #ifndef NDEBUG
4389 /* The following variables is maximal number of allocated nodes
4390 `arc'. */
4391 static int allocated_arcs_num = 0;
4392 #endif
4394 /* The function frees node ARC. */
4395 static void
4396 free_arc (arc)
4397 arc_t arc;
4399 arc->next_out_arc = first_free_arc;
4400 first_free_arc = arc;
4403 /* The function removes and frees ARC staring from FROM_STATE. */
4404 static void
4405 remove_arc (from_state, arc)
4406 state_t from_state;
4407 arc_t arc;
4409 arc_t prev_arc;
4410 arc_t curr_arc;
4412 if (arc == NULL)
4413 abort ();
4414 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
4415 curr_arc != NULL;
4416 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4417 if (curr_arc == arc)
4418 break;
4419 if (curr_arc == NULL)
4420 abort ();
4421 if (prev_arc == NULL)
4422 from_state->first_out_arc = arc->next_out_arc;
4423 else
4424 prev_arc->next_out_arc = arc->next_out_arc;
4425 free_arc (arc);
4428 /* The functions returns arc with given characteristics (or NULL if
4429 the arc does not exist). */
4430 static arc_t
4431 find_arc (from_state, to_state, insn)
4432 state_t from_state;
4433 state_t to_state;
4434 ainsn_t insn;
4436 arc_t arc;
4438 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4439 if (arc->to_state == to_state && arc->insn == insn)
4440 return arc;
4441 return NULL;
4444 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4445 and with given STATE_ALTS. The function returns added arc (or
4446 already existing arc). */
4447 static arc_t
4448 add_arc (from_state, to_state, ainsn, state_alts)
4449 state_t from_state;
4450 state_t to_state;
4451 ainsn_t ainsn;
4452 int state_alts;
4454 arc_t new_arc;
4456 new_arc = find_arc (from_state, to_state, ainsn);
4457 if (new_arc != NULL)
4458 return new_arc;
4459 if (first_free_arc == NULL)
4461 #ifndef NDEBUG
4462 allocated_arcs_num++;
4463 #endif
4464 new_arc = create_node (sizeof (struct arc));
4465 new_arc->to_state = NULL;
4466 new_arc->insn = NULL;
4467 new_arc->next_out_arc = NULL;
4469 else
4471 new_arc = first_free_arc;
4472 first_free_arc = first_free_arc->next_out_arc;
4474 new_arc->to_state = to_state;
4475 new_arc->insn = ainsn;
4476 ainsn->arc_exists_p = 1;
4477 new_arc->next_out_arc = from_state->first_out_arc;
4478 from_state->first_out_arc = new_arc;
4479 new_arc->next_arc_marked_by_insn = NULL;
4480 new_arc->state_alts = state_alts;
4481 return new_arc;
4484 /* The function returns the first arc starting from STATE. */
4485 static arc_t
4486 first_out_arc (state)
4487 state_t state;
4489 return state->first_out_arc;
4492 /* The function returns next out arc after ARC. */
4493 static arc_t
4494 next_out_arc (arc)
4495 arc_t arc;
4497 return arc->next_out_arc;
4500 /* Initialization of the abstract data. */
4501 static void
4502 initiate_arcs ()
4504 first_free_arc = NULL;
4507 /* Finishing work with the abstract data. */
4508 static void
4509 finish_arcs ()
4515 /* Abstract data `automata lists'. */
4517 /* List of free states. */
4518 static automata_list_el_t first_free_automata_list_el;
4520 /* The list being formed. */
4521 static automata_list_el_t current_automata_list;
4523 /* Hash table of automata lists. */
4524 static htab_t automata_list_table;
4526 /* The following function returns free automata list el. It may be
4527 new allocated node or node freed earlier. */
4528 static automata_list_el_t
4529 get_free_automata_list_el ()
4531 automata_list_el_t result;
4533 if (first_free_automata_list_el != NULL)
4535 result = first_free_automata_list_el;
4536 first_free_automata_list_el
4537 = first_free_automata_list_el->next_automata_list_el;
4539 else
4540 result = create_node (sizeof (struct automata_list_el));
4541 result->automaton = NULL;
4542 result->next_automata_list_el = NULL;
4543 return result;
4546 /* The function frees node AUTOMATA_LIST_EL. */
4547 static void
4548 free_automata_list_el (automata_list_el)
4549 automata_list_el_t automata_list_el;
4551 if (automata_list_el == NULL)
4552 return;
4553 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4554 first_free_automata_list_el = automata_list_el;
4557 /* The function frees list AUTOMATA_LIST. */
4558 static void
4559 free_automata_list (automata_list)
4560 automata_list_el_t automata_list;
4562 automata_list_el_t curr_automata_list_el;
4563 automata_list_el_t next_automata_list_el;
4565 for (curr_automata_list_el = automata_list;
4566 curr_automata_list_el != NULL;
4567 curr_automata_list_el = next_automata_list_el)
4569 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4570 free_automata_list_el (curr_automata_list_el);
4574 /* Hash value of AUTOMATA_LIST. */
4575 static hashval_t
4576 automata_list_hash (automata_list)
4577 const void *automata_list;
4579 unsigned int hash_value;
4580 automata_list_el_t curr_automata_list_el;
4582 hash_value = 0;
4583 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4584 curr_automata_list_el != NULL;
4585 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4586 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4587 | (hash_value << CHAR_BIT))
4588 + curr_automata_list_el->automaton->automaton_order_num);
4589 return hash_value;
4592 /* Return nonzero value if the automata_lists are the same. */
4593 static int
4594 automata_list_eq_p (automata_list_1, automata_list_2)
4595 const void *automata_list_1;
4596 const void *automata_list_2;
4598 automata_list_el_t automata_list_el_1;
4599 automata_list_el_t automata_list_el_2;
4601 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4602 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4603 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4604 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4605 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4606 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4607 return 0;
4608 return automata_list_el_1 == automata_list_el_2;
4611 /* Initialization of the abstract data. */
4612 static void
4613 initiate_automata_lists ()
4615 first_free_automata_list_el = NULL;
4616 automata_list_table = htab_create (1500, automata_list_hash,
4617 automata_list_eq_p, (htab_del) 0);
4620 /* The following function starts new automata list and makes it the
4621 current one. */
4622 static void
4623 automata_list_start ()
4625 current_automata_list = NULL;
4628 /* The following function adds AUTOMATON to the current list. */
4629 static void
4630 automata_list_add (automaton)
4631 automaton_t automaton;
4633 automata_list_el_t el;
4635 el = get_free_automata_list_el ();
4636 el->automaton = automaton;
4637 el->next_automata_list_el = current_automata_list;
4638 current_automata_list = el;
4641 /* The following function finishes forming the current list, inserts
4642 it into the table and returns it. */
4643 static automata_list_el_t
4644 automata_list_finish ()
4646 void **entry_ptr;
4648 if (current_automata_list == NULL)
4649 return NULL;
4650 entry_ptr = htab_find_slot (automata_list_table,
4651 (void *) current_automata_list, 1);
4652 if (*entry_ptr == NULL)
4653 *entry_ptr = (void *) current_automata_list;
4654 else
4655 free_automata_list (current_automata_list);
4656 current_automata_list = NULL;
4657 return (automata_list_el_t) *entry_ptr;
4660 /* Finishing work with the abstract data. */
4661 static void
4662 finish_automata_lists ()
4664 htab_delete (automata_list_table);
4669 /* The page contains abstract data for work with exclusion sets (see
4670 exclusion_set in file rtl.def). */
4672 /* The following variable refers to an exclusion set returned by
4673 get_excl_set. This is bit string of length equal to cpu units
4674 number. If exclusion set for given unit contains 1 for a unit,
4675 then simultaneous reservation of the units is prohibited. */
4676 static reserv_sets_t excl_set;
4678 /* The array contains exclusion sets for each unit. */
4679 static reserv_sets_t *unit_excl_set_table;
4681 /* The following function forms the array containing exclusion sets
4682 for each unit. */
4683 static void
4684 initiate_excl_sets ()
4686 decl_t decl;
4687 reserv_sets_t unit_excl_set;
4688 unit_set_el_t el;
4689 int i;
4691 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4692 excl_set = (reserv_sets_t) obstack_base (&irp);
4693 obstack_finish (&irp);
4694 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4695 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4696 obstack_finish (&irp);
4697 /* Evaluate unit exclusion sets. */
4698 for (i = 0; i < description->decls_num; i++)
4700 decl = description->decls [i];
4701 if (decl->mode == dm_unit)
4703 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4704 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4705 obstack_finish (&irp);
4706 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4707 for (el = DECL_UNIT (decl)->excl_list;
4708 el != NULL;
4709 el = el->next_unit_set_el)
4711 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4712 el->unit_decl->in_set_p = TRUE;
4714 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4719 /* The function sets up and return EXCL_SET which is union of
4720 exclusion sets for each unit in IN_SET. */
4721 static reserv_sets_t
4722 get_excl_set (in_set)
4723 reserv_sets_t in_set;
4725 int excl_char_num;
4726 int chars_num;
4727 int i;
4728 int start_unit_num;
4729 int unit_num;
4731 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4732 memset (excl_set, 0, chars_num);
4733 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4734 if (((unsigned char *) in_set) [excl_char_num])
4735 for (i = CHAR_BIT - 1; i >= 0; i--)
4736 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4738 start_unit_num = excl_char_num * CHAR_BIT + i;
4739 if (start_unit_num >= description->units_num)
4740 return excl_set;
4741 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4743 excl_set [unit_num]
4744 |= unit_excl_set_table [start_unit_num] [unit_num];
4747 return excl_set;
4752 /* The page contains abstract data for work with presence/absence
4753 pattern sets (see presence_set/absence_set in file rtl.def). */
4755 /* The following arrays contain correspondingly presence, final
4756 presence, absence, and final absence patterns for each unit. */
4757 static pattern_reserv_t *unit_presence_set_table;
4758 static pattern_reserv_t *unit_final_presence_set_table;
4759 static pattern_reserv_t *unit_absence_set_table;
4760 static pattern_reserv_t *unit_final_absence_set_table;
4762 /* The following function forms list of reservation sets for given
4763 PATTERN_LIST. */
4764 static pattern_reserv_t
4765 form_reserv_sets_list (pattern_list)
4766 pattern_set_el_t pattern_list;
4768 pattern_set_el_t el;
4769 pattern_reserv_t first, curr, prev;
4770 int i;
4772 prev = first = NULL;
4773 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4775 curr = create_node (sizeof (struct pattern_reserv));
4776 curr->reserv = alloc_empty_reserv_sets ();
4777 curr->next_pattern_reserv = NULL;
4778 for (i = 0; i < el->units_num; i++)
4780 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4781 el->unit_decls [i]->in_set_p = TRUE;
4783 if (prev != NULL)
4784 prev->next_pattern_reserv = curr;
4785 else
4786 first = curr;
4787 prev = curr;
4789 return first;
4792 /* The following function forms the array containing presence and
4793 absence pattern sets for each unit. */
4794 static void
4795 initiate_presence_absence_pattern_sets ()
4797 decl_t decl;
4798 int i;
4800 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4801 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4802 obstack_finish (&irp);
4803 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4804 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4805 obstack_finish (&irp);
4806 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4807 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4808 obstack_finish (&irp);
4809 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4810 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4811 obstack_finish (&irp);
4812 /* Evaluate unit presence/absence sets. */
4813 for (i = 0; i < description->decls_num; i++)
4815 decl = description->decls [i];
4816 if (decl->mode == dm_unit)
4818 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4819 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4820 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4821 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4822 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4823 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4824 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4825 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4830 /* The function checks that CHECKED_SET satisfies all presence pattern
4831 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4832 is ok. */
4833 static int
4834 check_presence_pattern_sets (checked_set, origional_set, final_p)
4835 reserv_sets_t checked_set, origional_set;
4836 int final_p;
4838 int char_num;
4839 int chars_num;
4840 int i;
4841 int start_unit_num;
4842 int unit_num;
4843 int presence_p;
4844 pattern_reserv_t pat_reserv;
4846 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4847 for (char_num = 0; char_num < chars_num; char_num++)
4848 if (((unsigned char *) origional_set) [char_num])
4849 for (i = CHAR_BIT - 1; i >= 0; i--)
4850 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4852 start_unit_num = char_num * CHAR_BIT + i;
4853 if (start_unit_num >= description->units_num)
4854 break;
4855 if ((final_p
4856 && unit_final_presence_set_table [start_unit_num] == NULL)
4857 || (!final_p
4858 && unit_presence_set_table [start_unit_num] == NULL))
4859 continue;
4860 presence_p = FALSE;
4861 for (pat_reserv = (final_p
4862 ? unit_final_presence_set_table [start_unit_num]
4863 : unit_presence_set_table [start_unit_num]);
4864 pat_reserv != NULL;
4865 pat_reserv = pat_reserv->next_pattern_reserv)
4867 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4868 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4869 != pat_reserv->reserv [unit_num])
4870 break;
4871 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4873 if (!presence_p)
4874 return FALSE;
4876 return TRUE;
4879 /* The function checks that CHECKED_SET satisfies all absence pattern
4880 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4881 is ok. */
4882 static int
4883 check_absence_pattern_sets (checked_set, origional_set, final_p)
4884 reserv_sets_t checked_set, origional_set;
4885 int final_p;
4887 int char_num;
4888 int chars_num;
4889 int i;
4890 int start_unit_num;
4891 int unit_num;
4892 pattern_reserv_t pat_reserv;
4894 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4895 for (char_num = 0; char_num < chars_num; char_num++)
4896 if (((unsigned char *) origional_set) [char_num])
4897 for (i = CHAR_BIT - 1; i >= 0; i--)
4898 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4900 start_unit_num = char_num * CHAR_BIT + i;
4901 if (start_unit_num >= description->units_num)
4902 break;
4903 for (pat_reserv = (final_p
4904 ? unit_final_absence_set_table [start_unit_num]
4905 : unit_absence_set_table [start_unit_num]);
4906 pat_reserv != NULL;
4907 pat_reserv = pat_reserv->next_pattern_reserv)
4909 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4910 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4911 != pat_reserv->reserv [unit_num]
4912 && pat_reserv->reserv [unit_num])
4913 break;
4914 if (unit_num >= els_in_cycle_reserv)
4915 return FALSE;
4918 return TRUE;
4923 /* This page contains code for transformation of original reservations
4924 described in .md file. The main goal of transformations is
4925 simplifying reservation and lifting up all `|' on the top of IR
4926 reservation representation. */
4929 /* The following function makes copy of IR representation of
4930 reservation. The function also substitutes all reservations
4931 defined by define_reservation by corresponding value during making
4932 the copy. */
4933 static regexp_t
4934 copy_insn_regexp (regexp)
4935 regexp_t regexp;
4937 regexp_t result;
4938 int i;
4940 if (regexp->mode == rm_reserv)
4941 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4942 else if (regexp->mode == rm_unit)
4943 result = copy_node (regexp, sizeof (struct regexp));
4944 else if (regexp->mode == rm_repeat)
4946 result = copy_node (regexp, sizeof (struct regexp));
4947 REGEXP_REPEAT (result)->regexp
4948 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4950 else if (regexp->mode == rm_sequence)
4952 result = copy_node (regexp,
4953 sizeof (struct regexp) + sizeof (regexp_t)
4954 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4955 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4956 REGEXP_SEQUENCE (result)->regexps [i]
4957 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4959 else if (regexp->mode == rm_allof)
4961 result = copy_node (regexp,
4962 sizeof (struct regexp) + sizeof (regexp_t)
4963 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4964 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4965 REGEXP_ALLOF (result)->regexps [i]
4966 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4968 else if (regexp->mode == rm_oneof)
4970 result = copy_node (regexp,
4971 sizeof (struct regexp) + sizeof (regexp_t)
4972 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4973 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4974 REGEXP_ONEOF (result)->regexps [i]
4975 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4977 else
4979 if (regexp->mode != rm_nothing)
4980 abort ();
4981 result = copy_node (regexp, sizeof (struct regexp));
4983 return result;
4986 /* The following variable is set up 1 if a transformation has been
4987 applied. */
4988 static int regexp_transformed_p;
4990 /* The function makes transformation
4991 A*N -> A, A, ... */
4992 static regexp_t
4993 transform_1 (regexp)
4994 regexp_t regexp;
4996 int i;
4997 int repeat_num;
4998 regexp_t operand;
4999 pos_t pos;
5001 if (regexp->mode == rm_repeat)
5003 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
5004 if (repeat_num <= 1)
5005 abort ();
5006 operand = REGEXP_REPEAT (regexp)->regexp;
5007 pos = regexp->mode;
5008 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
5009 * (repeat_num - 1));
5010 regexp->mode = rm_sequence;
5011 regexp->pos = pos;
5012 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
5013 for (i = 0; i < repeat_num; i++)
5014 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
5015 regexp_transformed_p = 1;
5017 return regexp;
5020 /* The function makes transformations
5021 ...,(A,B,...),C,... -> ...,A,B,...,C,...
5022 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
5023 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
5024 static regexp_t
5025 transform_2 (regexp)
5026 regexp_t regexp;
5028 if (regexp->mode == rm_sequence)
5030 regexp_t sequence = NULL;
5031 regexp_t result;
5032 int sequence_index = 0;
5033 int i, j;
5035 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5036 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
5038 sequence_index = i;
5039 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
5040 break;
5042 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
5044 if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
5045 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
5046 abort ();
5047 result = create_node (sizeof (struct regexp)
5048 + sizeof (regexp_t)
5049 * (REGEXP_SEQUENCE (regexp)->regexps_num
5050 + REGEXP_SEQUENCE (sequence)->regexps_num
5051 - 2));
5052 result->mode = rm_sequence;
5053 result->pos = regexp->pos;
5054 REGEXP_SEQUENCE (result)->regexps_num
5055 = (REGEXP_SEQUENCE (regexp)->regexps_num
5056 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
5057 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5058 if (i < sequence_index)
5059 REGEXP_SEQUENCE (result)->regexps [i]
5060 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
5061 else if (i > sequence_index)
5062 REGEXP_SEQUENCE (result)->regexps
5063 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
5064 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
5065 else
5066 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
5067 REGEXP_SEQUENCE (result)->regexps [i + j]
5068 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
5069 regexp_transformed_p = 1;
5070 regexp = result;
5073 else if (regexp->mode == rm_allof)
5075 regexp_t allof = NULL;
5076 regexp_t result;
5077 int allof_index = 0;
5078 int i, j;
5080 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5081 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
5083 allof_index = i;
5084 allof = REGEXP_ALLOF (regexp)->regexps [i];
5085 break;
5087 if (i < REGEXP_ALLOF (regexp)->regexps_num)
5089 if (REGEXP_ALLOF (allof)->regexps_num <= 1
5090 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5091 abort ();
5092 result = create_node (sizeof (struct regexp)
5093 + sizeof (regexp_t)
5094 * (REGEXP_ALLOF (regexp)->regexps_num
5095 + REGEXP_ALLOF (allof)->regexps_num - 2));
5096 result->mode = rm_allof;
5097 result->pos = regexp->pos;
5098 REGEXP_ALLOF (result)->regexps_num
5099 = (REGEXP_ALLOF (regexp)->regexps_num
5100 + REGEXP_ALLOF (allof)->regexps_num - 1);
5101 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5102 if (i < allof_index)
5103 REGEXP_ALLOF (result)->regexps [i]
5104 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
5105 else if (i > allof_index)
5106 REGEXP_ALLOF (result)->regexps
5107 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
5108 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
5109 else
5110 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
5111 REGEXP_ALLOF (result)->regexps [i + j]
5112 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
5113 regexp_transformed_p = 1;
5114 regexp = result;
5117 else if (regexp->mode == rm_oneof)
5119 regexp_t oneof = NULL;
5120 regexp_t result;
5121 int oneof_index = 0;
5122 int i, j;
5124 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5125 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
5127 oneof_index = i;
5128 oneof = REGEXP_ONEOF (regexp)->regexps [i];
5129 break;
5131 if (i < REGEXP_ONEOF (regexp)->regexps_num)
5133 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5134 || REGEXP_ONEOF (regexp)->regexps_num <= 1)
5135 abort ();
5136 result = create_node (sizeof (struct regexp)
5137 + sizeof (regexp_t)
5138 * (REGEXP_ONEOF (regexp)->regexps_num
5139 + REGEXP_ONEOF (oneof)->regexps_num - 2));
5140 result->mode = rm_oneof;
5141 result->pos = regexp->pos;
5142 REGEXP_ONEOF (result)->regexps_num
5143 = (REGEXP_ONEOF (regexp)->regexps_num
5144 + REGEXP_ONEOF (oneof)->regexps_num - 1);
5145 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5146 if (i < oneof_index)
5147 REGEXP_ONEOF (result)->regexps [i]
5148 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
5149 else if (i > oneof_index)
5150 REGEXP_ONEOF (result)->regexps
5151 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
5152 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
5153 else
5154 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
5155 REGEXP_ONEOF (result)->regexps [i + j]
5156 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
5157 regexp_transformed_p = 1;
5158 regexp = result;
5161 return regexp;
5164 /* The function makes transformations
5165 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
5166 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
5167 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
5168 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
5169 static regexp_t
5170 transform_3 (regexp)
5171 regexp_t regexp;
5173 if (regexp->mode == rm_sequence)
5175 regexp_t oneof = NULL;
5176 int oneof_index = 0;
5177 regexp_t result;
5178 regexp_t sequence;
5179 int i, j;
5181 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5182 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
5184 oneof_index = i;
5185 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
5186 break;
5188 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
5190 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5191 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
5192 abort ();
5193 result = create_node (sizeof (struct regexp)
5194 + sizeof (regexp_t)
5195 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5196 result->mode = rm_oneof;
5197 result->pos = regexp->pos;
5198 REGEXP_ONEOF (result)->regexps_num
5199 = REGEXP_ONEOF (oneof)->regexps_num;
5200 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5202 sequence
5203 = create_node (sizeof (struct regexp)
5204 + sizeof (regexp_t)
5205 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
5206 sequence->mode = rm_sequence;
5207 sequence->pos = regexp->pos;
5208 REGEXP_SEQUENCE (sequence)->regexps_num
5209 = REGEXP_SEQUENCE (regexp)->regexps_num;
5210 REGEXP_ONEOF (result)->regexps [i] = sequence;
5211 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
5212 if (j != oneof_index)
5213 REGEXP_SEQUENCE (sequence)->regexps [j]
5214 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
5215 else
5216 REGEXP_SEQUENCE (sequence)->regexps [j]
5217 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5219 regexp_transformed_p = 1;
5220 regexp = result;
5223 else if (regexp->mode == rm_allof)
5225 regexp_t oneof = NULL;
5226 regexp_t seq;
5227 int oneof_index = 0;
5228 int max_seq_length, allof_length;
5229 regexp_t result;
5230 regexp_t allof = NULL;
5231 regexp_t allof_op = NULL;
5232 int i, j;
5234 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5235 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
5237 oneof_index = i;
5238 oneof = REGEXP_ALLOF (regexp)->regexps [i];
5239 break;
5241 if (i < REGEXP_ALLOF (regexp)->regexps_num)
5243 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5244 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5245 abort ();
5246 result = create_node (sizeof (struct regexp)
5247 + sizeof (regexp_t)
5248 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5249 result->mode = rm_oneof;
5250 result->pos = regexp->pos;
5251 REGEXP_ONEOF (result)->regexps_num
5252 = REGEXP_ONEOF (oneof)->regexps_num;
5253 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5255 allof
5256 = create_node (sizeof (struct regexp)
5257 + sizeof (regexp_t)
5258 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
5259 allof->mode = rm_allof;
5260 allof->pos = regexp->pos;
5261 REGEXP_ALLOF (allof)->regexps_num
5262 = REGEXP_ALLOF (regexp)->regexps_num;
5263 REGEXP_ONEOF (result)->regexps [i] = allof;
5264 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
5265 if (j != oneof_index)
5266 REGEXP_ALLOF (allof)->regexps [j]
5267 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
5268 else
5269 REGEXP_ALLOF (allof)->regexps [j]
5270 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5272 regexp_transformed_p = 1;
5273 regexp = result;
5275 max_seq_length = 0;
5276 if (regexp->mode == rm_allof)
5277 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5279 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
5281 seq = REGEXP_ALLOF (regexp)->regexps [i];
5282 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
5283 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
5285 else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit
5286 && REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_nothing)
5288 max_seq_length = 0;
5289 break;
5292 if (max_seq_length != 0)
5294 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5295 abort ();
5296 result = create_node (sizeof (struct regexp)
5297 + sizeof (regexp_t) * (max_seq_length - 1));
5298 result->mode = rm_sequence;
5299 result->pos = regexp->pos;
5300 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5301 for (i = 0; i < max_seq_length; i++)
5303 allof_length = 0;
5304 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5305 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5306 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5307 ->regexps [j])->regexps_num)))
5309 allof_op
5310 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5311 ->regexps [i]);
5312 allof_length++;
5314 else if (i == 0
5315 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5316 == rm_unit
5317 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5318 == rm_nothing)))
5320 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5321 allof_length++;
5323 if (allof_length == 1)
5324 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5325 else
5327 allof = create_node (sizeof (struct regexp)
5328 + sizeof (regexp_t)
5329 * (allof_length - 1));
5330 allof->mode = rm_allof;
5331 allof->pos = regexp->pos;
5332 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5333 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5334 allof_length = 0;
5335 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5336 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5337 && (i <
5338 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5339 ->regexps [j])->regexps_num)))
5341 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5342 ->regexps [j])
5343 ->regexps [i]);
5344 REGEXP_ALLOF (allof)->regexps [allof_length]
5345 = allof_op;
5346 allof_length++;
5348 else if (i == 0
5349 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5350 == rm_unit
5351 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5352 == rm_nothing)))
5354 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5355 REGEXP_ALLOF (allof)->regexps [allof_length]
5356 = allof_op;
5357 allof_length++;
5361 regexp_transformed_p = 1;
5362 regexp = result;
5365 return regexp;
5368 /* The function traverses IR of reservation and applies transformations
5369 implemented by FUNC. */
5370 static regexp_t
5371 regexp_transform_func (regexp, func)
5372 regexp_t regexp;
5373 regexp_t (*func) PARAMS ((regexp_t regexp));
5375 int i;
5377 if (regexp->mode == rm_sequence)
5378 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5379 REGEXP_SEQUENCE (regexp)->regexps [i]
5380 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5381 else if (regexp->mode == rm_allof)
5382 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5383 REGEXP_ALLOF (regexp)->regexps [i]
5384 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5385 else if (regexp->mode == rm_oneof)
5386 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5387 REGEXP_ONEOF (regexp)->regexps [i]
5388 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5389 else if (regexp->mode == rm_repeat)
5390 REGEXP_REPEAT (regexp)->regexp
5391 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5392 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5393 abort ();
5394 return (*func) (regexp);
5397 /* The function applies all transformations for IR representation of
5398 reservation REGEXP. */
5399 static regexp_t
5400 transform_regexp (regexp)
5401 regexp_t regexp;
5403 regexp = regexp_transform_func (regexp, transform_1);
5406 regexp_transformed_p = 0;
5407 regexp = regexp_transform_func (regexp, transform_2);
5408 regexp = regexp_transform_func (regexp, transform_3);
5410 while (regexp_transformed_p);
5411 return regexp;
5414 /* The function applies all transformations for reservations of all
5415 insn declarations. */
5416 static void
5417 transform_insn_regexps ()
5419 decl_t decl;
5420 int i;
5422 transform_time = create_ticker ();
5423 add_advance_cycle_insn_decl ();
5424 fprintf (stderr, "Reservation transformation...");
5425 fflush (stderr);
5426 for (i = 0; i < description->decls_num; i++)
5428 decl = description->decls [i];
5429 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5430 DECL_INSN_RESERV (decl)->transformed_regexp
5431 = transform_regexp (copy_insn_regexp
5432 (DECL_INSN_RESERV (decl)->regexp));
5434 fprintf (stderr, "done\n");
5435 ticker_off (&transform_time);
5436 fflush (stderr);
5441 /* The following variable value is TRUE if the first annotated message
5442 about units to automata distribution has been output. */
5443 static int annotation_message_reported_p;
5445 /* The function processes all alternative reservations on CYCLE in
5446 given REGEXP of insn reservation with INSN_RESERV_NAME to check the
5447 UNIT (or another unit from the same automaton) is not reserved on
5448 the all alternatives. If it is true, the function outputs message
5449 about the rule violation. */
5450 static void
5451 check_unit_distribution_in_reserv (insn_reserv_name, unit, regexp, cycle)
5452 const char *insn_reserv_name;
5453 regexp_t unit;
5454 regexp_t regexp;
5455 int cycle;
5457 int i, k;
5458 regexp_t seq, allof;
5459 unit_decl_t unit_decl;
5461 if (regexp == NULL || regexp->mode != rm_oneof)
5462 abort ();
5463 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5464 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5466 seq = REGEXP_ONEOF (regexp)->regexps [i];
5467 if (seq->mode == rm_sequence)
5469 if (cycle >= REGEXP_SEQUENCE (seq)->regexps_num)
5470 continue;
5471 allof = REGEXP_SEQUENCE (seq)->regexps [cycle];
5472 if (allof->mode == rm_allof)
5474 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5475 if (REGEXP_ALLOF (allof)->regexps [k]->mode == rm_unit
5476 && (REGEXP_UNIT (REGEXP_ALLOF (allof)->regexps [k])
5477 ->unit_decl->automaton_decl
5478 == unit_decl->automaton_decl))
5479 break;
5480 if (k >= REGEXP_ALLOF (allof)->regexps_num)
5481 break;
5483 else if (allof->mode == rm_unit
5484 && (REGEXP_UNIT (allof)->unit_decl->automaton_decl
5485 != unit_decl->automaton_decl))
5486 break;
5488 else if (cycle != 0)
5489 continue;
5490 else if (seq->mode == rm_allof)
5492 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5493 if (REGEXP_ALLOF (seq)->regexps [k]->mode == rm_unit
5494 && (REGEXP_UNIT (REGEXP_ALLOF (seq)->regexps [k])
5495 ->unit_decl->automaton_decl == unit_decl->automaton_decl))
5496 break;
5497 if (k >= REGEXP_ALLOF (seq)->regexps_num)
5498 break;
5500 else if (seq->mode == rm_unit
5501 && (REGEXP_UNIT (seq)->unit_decl->automaton_decl
5502 != unit_decl->automaton_decl))
5503 break;
5505 if (i >= 0)
5507 if (!annotation_message_reported_p)
5509 fprintf (stderr, "\n");
5510 error ("The following units do not satisfy units-automata distribution rule");
5511 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5512 annotation_message_reported_p = TRUE;
5514 error ("Unit %s, reserv. %s, cycle %d",
5515 unit_decl->name, insn_reserv_name, cycle);
5519 /* The function processes given REGEXP to find units with the wrong
5520 distribution. */
5521 static void
5522 check_regexp_units_distribution (insn_reserv_name, regexp)
5523 const char *insn_reserv_name;
5524 regexp_t regexp;
5526 int i, j, k;
5527 regexp_t seq, allof, unit;
5529 if (regexp == NULL || regexp->mode != rm_oneof)
5530 return;
5531 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5533 seq = REGEXP_ONEOF (regexp)->regexps [i];
5534 if (seq->mode == rm_sequence)
5535 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5537 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5538 if (allof->mode == rm_allof)
5539 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5541 unit = REGEXP_ALLOF (allof)->regexps [k];
5542 if (unit->mode == rm_unit)
5543 check_unit_distribution_in_reserv (insn_reserv_name, unit,
5544 regexp, j);
5545 else if (unit->mode != rm_nothing)
5546 abort ();
5548 else if (allof->mode == rm_unit)
5549 check_unit_distribution_in_reserv (insn_reserv_name, allof,
5550 regexp, j);
5551 else if (allof->mode != rm_nothing)
5552 abort ();
5554 else if (seq->mode == rm_allof)
5555 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5557 unit = REGEXP_ALLOF (seq)->regexps [k];
5558 if (unit->mode == rm_unit)
5559 check_unit_distribution_in_reserv (insn_reserv_name, unit,
5560 regexp, 0);
5561 else if (unit->mode != rm_nothing)
5562 abort ();
5564 else if (seq->mode == rm_unit)
5565 check_unit_distribution_in_reserv (insn_reserv_name, seq, regexp, 0);
5566 else if (seq->mode != rm_nothing)
5567 abort ();
5571 /* The function finds units which violates units to automata
5572 distribution rule. If the units exist, report about them. */
5573 static void
5574 check_unit_distributions_to_automata ()
5576 decl_t decl;
5577 int i;
5579 fprintf (stderr, "Check unit distributions to automata...");
5580 annotation_message_reported_p = FALSE;
5581 for (i = 0; i < description->decls_num; i++)
5583 decl = description->decls [i];
5584 if (decl->mode == dm_insn_reserv)
5585 check_regexp_units_distribution
5586 (DECL_INSN_RESERV (decl)->name,
5587 DECL_INSN_RESERV (decl)->transformed_regexp);
5589 fprintf (stderr, "done\n");
5594 /* The page contains code for building alt_states (see comments for
5595 IR) describing all possible insns reservations of an automaton. */
5597 /* Current state being formed for which the current alt_state
5598 refers. */
5599 static state_t state_being_formed;
5601 /* Current alt_state being formed. */
5602 static alt_state_t alt_state_being_formed;
5604 /* This recursive function processes `,' and units in reservation
5605 REGEXP for forming alt_states of AUTOMATON. It is believed that
5606 CURR_CYCLE is start cycle of all reservation REGEXP. */
5607 static int
5608 process_seq_for_forming_states (regexp, automaton, curr_cycle)
5609 regexp_t regexp;
5610 automaton_t automaton;
5611 int curr_cycle;
5613 int i;
5615 if (regexp == NULL)
5616 return curr_cycle;
5617 else if (regexp->mode == rm_unit)
5619 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5620 == automaton->automaton_order_num)
5621 set_state_reserv (state_being_formed, curr_cycle,
5622 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5623 return curr_cycle;
5625 else if (regexp->mode == rm_sequence)
5627 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5628 curr_cycle
5629 = process_seq_for_forming_states
5630 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5631 return curr_cycle;
5633 else if (regexp->mode == rm_allof)
5635 int finish_cycle = 0;
5636 int cycle;
5638 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5640 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5641 ->regexps [i],
5642 automaton, curr_cycle);
5643 if (finish_cycle < cycle)
5644 finish_cycle = cycle;
5646 return finish_cycle;
5648 else
5650 if (regexp->mode != rm_nothing)
5651 abort ();
5652 return curr_cycle;
5656 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5657 inserts alt_state into the table. */
5658 static void
5659 finish_forming_alt_state (alt_state, automaton)
5660 alt_state_t alt_state;
5661 automaton_t automaton ATTRIBUTE_UNUSED;
5663 state_t state_in_table;
5664 state_t corresponding_state;
5666 corresponding_state = alt_state->state;
5667 state_in_table = insert_state (corresponding_state);
5668 if (state_in_table != corresponding_state)
5670 free_state (corresponding_state);
5671 alt_state->state = state_in_table;
5675 /* The following variable value is current automaton insn for whose
5676 reservation the alt states are created. */
5677 static ainsn_t curr_ainsn;
5679 /* This recursive function processes `|' in reservation REGEXP for
5680 forming alt_states of AUTOMATON. List of the alt states should
5681 have the same order as in the description. */
5682 static void
5683 process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5684 regexp_t regexp;
5685 automaton_t automaton;
5686 int inside_oneof_p;
5688 int i;
5690 if (regexp->mode != rm_oneof)
5692 alt_state_being_formed = get_free_alt_state ();
5693 state_being_formed = get_free_state (1, automaton);
5694 alt_state_being_formed->state = state_being_formed;
5695 /* We inserts in reverse order but we process alternatives also
5696 in reverse order. So we have the same order of alternative
5697 as in the description. */
5698 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5699 curr_ainsn->alt_states = alt_state_being_formed;
5700 (void) process_seq_for_forming_states (regexp, automaton, 0);
5701 finish_forming_alt_state (alt_state_being_formed, automaton);
5703 else
5705 if (inside_oneof_p)
5706 abort ();
5707 /* We processes it in reverse order to get list with the same
5708 order as in the description. See also the previous
5709 commentary. */
5710 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5711 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5712 automaton, 1);
5716 /* Create nodes alt_state for all AUTOMATON insns. */
5717 static void
5718 create_alt_states (automaton)
5719 automaton_t automaton;
5721 struct insn_reserv_decl *reserv_decl;
5723 for (curr_ainsn = automaton->ainsn_list;
5724 curr_ainsn != NULL;
5725 curr_ainsn = curr_ainsn->next_ainsn)
5727 reserv_decl = curr_ainsn->insn_reserv_decl;
5728 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5730 curr_ainsn->alt_states = NULL;
5731 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5732 automaton, 0);
5733 curr_ainsn->sorted_alt_states
5734 = uniq_sort_alt_states (curr_ainsn->alt_states);
5741 /* The page contains major code for building DFA(s) for fast pipeline
5742 hazards recognition. */
5744 /* The function forms list of ainsns of AUTOMATON with the same
5745 reservation. */
5746 static void
5747 form_ainsn_with_same_reservs (automaton)
5748 automaton_t automaton;
5750 ainsn_t curr_ainsn;
5751 size_t i;
5752 vla_ptr_t first_insns;
5753 vla_ptr_t last_insns;
5755 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5756 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5757 for (curr_ainsn = automaton->ainsn_list;
5758 curr_ainsn != NULL;
5759 curr_ainsn = curr_ainsn->next_ainsn)
5760 if (curr_ainsn->insn_reserv_decl
5761 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5763 curr_ainsn->next_same_reservs_insn = NULL;
5764 curr_ainsn->first_insn_with_same_reservs = 1;
5766 else
5768 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5769 if (alt_states_eq
5770 (curr_ainsn->sorted_alt_states,
5771 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5772 break;
5773 curr_ainsn->next_same_reservs_insn = NULL;
5774 if (i < VLA_PTR_LENGTH (first_insns))
5776 curr_ainsn->first_insn_with_same_reservs = 0;
5777 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5778 = curr_ainsn;
5779 VLA_PTR (last_insns, i) = curr_ainsn;
5781 else
5783 VLA_PTR_ADD (first_insns, curr_ainsn);
5784 VLA_PTR_ADD (last_insns, curr_ainsn);
5785 curr_ainsn->first_insn_with_same_reservs = 1;
5788 VLA_PTR_DELETE (first_insns);
5789 VLA_PTR_DELETE (last_insns);
5792 /* Forming unit reservations which can affect creating the automaton
5793 states achieved from a given state. It permits to build smaller
5794 automata in many cases. We would have the same automata after
5795 the minimization without such optimization, but the automaton
5796 right after the building could be huge. So in other words, usage
5797 of reservs_matter means some minimization during building the
5798 automaton. */
5799 static reserv_sets_t
5800 form_reservs_matter (automaton)
5801 automaton_t automaton;
5803 int cycle, unit;
5804 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5806 for (cycle = 0; cycle < max_cycles_num; cycle++)
5807 for (unit = 0; unit < description->units_num; unit++)
5808 if (units_array [unit]->automaton_decl
5809 == automaton->corresponding_automaton_decl
5810 && (cycle >= units_array [unit]->min_occ_cycle_num
5811 /* We can not remove queried unit from reservations. */
5812 || units_array [unit]->query_p
5813 /* We can not remove units which are used
5814 `exclusion_set', `presence_set',
5815 `final_presence_set', `absence_set', and
5816 `final_absence_set'. */
5817 || units_array [unit]->in_set_p))
5818 set_unit_reserv (reservs_matter, cycle, unit);
5819 return reservs_matter;
5822 /* The following function creates all states of nondeterministic (if
5823 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5824 static void
5825 make_automaton (automaton)
5826 automaton_t automaton;
5828 ainsn_t ainsn;
5829 struct insn_reserv_decl *insn_reserv_decl;
5830 alt_state_t alt_state;
5831 state_t state;
5832 state_t start_state;
5833 state_t state2;
5834 ainsn_t advance_cycle_ainsn;
5835 arc_t added_arc;
5836 vla_ptr_t state_stack;
5837 int states_n;
5838 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5840 VLA_PTR_CREATE (state_stack, 150, "state stack");
5841 /* Create the start state (empty state). */
5842 start_state = insert_state (get_free_state (1, automaton));
5843 automaton->start_state = start_state;
5844 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5845 VLA_PTR_ADD (state_stack, start_state);
5846 states_n = 1;
5847 while (VLA_PTR_LENGTH (state_stack) != 0)
5849 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5850 VLA_PTR_SHORTEN (state_stack, 1);
5851 advance_cycle_ainsn = NULL;
5852 for (ainsn = automaton->ainsn_list;
5853 ainsn != NULL;
5854 ainsn = ainsn->next_ainsn)
5855 if (ainsn->first_insn_with_same_reservs)
5857 insn_reserv_decl = ainsn->insn_reserv_decl;
5858 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5860 /* We process alt_states in the same order as they are
5861 present in the description. */
5862 added_arc = NULL;
5863 for (alt_state = ainsn->alt_states;
5864 alt_state != NULL;
5865 alt_state = alt_state->next_alt_state)
5867 state2 = alt_state->state;
5868 if (!intersected_state_reservs_p (state, state2))
5870 state2 = states_union (state, state2, reservs_matter);
5871 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5873 state2->it_was_placed_in_stack_for_NDFA_forming
5874 = 1;
5875 VLA_PTR_ADD (state_stack, state2);
5876 states_n++;
5877 if (states_n % 100 == 0)
5878 fprintf (stderr, "*");
5880 added_arc = add_arc (state, state2, ainsn, 1);
5881 if (!ndfa_flag)
5882 break;
5885 if (!ndfa_flag && added_arc != NULL)
5887 added_arc->state_alts = 0;
5888 for (alt_state = ainsn->alt_states;
5889 alt_state != NULL;
5890 alt_state = alt_state->next_alt_state)
5892 state2 = alt_state->state;
5893 if (!intersected_state_reservs_p (state, state2))
5894 added_arc->state_alts++;
5898 else
5899 advance_cycle_ainsn = ainsn;
5901 /* Add transition to advance cycle. */
5902 state2 = state_shift (state, reservs_matter);
5903 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5905 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5906 VLA_PTR_ADD (state_stack, state2);
5907 states_n++;
5908 if (states_n % 100 == 0)
5909 fprintf (stderr, "*");
5911 if (advance_cycle_ainsn == NULL)
5912 abort ();
5913 add_arc (state, state2, advance_cycle_ainsn, 1);
5915 VLA_PTR_DELETE (state_stack);
5918 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5919 static void
5920 form_arcs_marked_by_insn (state)
5921 state_t state;
5923 decl_t decl;
5924 arc_t arc;
5925 int i;
5927 for (i = 0; i < description->decls_num; i++)
5929 decl = description->decls [i];
5930 if (decl->mode == dm_insn_reserv)
5931 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5933 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5935 if (arc->insn == NULL)
5936 abort ();
5937 arc->next_arc_marked_by_insn
5938 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5939 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5943 /* The function creates composed state (see comments for IR) from
5944 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5945 same insn. If the composed state is not in STATE_STACK yet, it is
5946 pushed into STATE_STACK. */
5947 static int
5948 create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5949 state_t original_state;
5950 arc_t arcs_marked_by_insn;
5951 vla_ptr_t *state_stack;
5953 state_t state;
5954 alt_state_t alt_state, curr_alt_state;
5955 alt_state_t new_alt_state;
5956 arc_t curr_arc;
5957 arc_t next_arc;
5958 state_t state_in_table;
5959 state_t temp_state;
5960 alt_state_t canonical_alt_states_list;
5961 int alts_number;
5962 int new_state_p = 0;
5964 if (arcs_marked_by_insn == NULL)
5965 return new_state_p;
5966 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5967 state = arcs_marked_by_insn->to_state;
5968 else
5970 if (!ndfa_flag)
5971 abort ();
5972 /* Create composed state. */
5973 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5974 curr_alt_state = NULL;
5975 for (curr_arc = arcs_marked_by_insn;
5976 curr_arc != NULL;
5977 curr_arc = curr_arc->next_arc_marked_by_insn)
5978 if (curr_arc->to_state->component_states == NULL)
5980 new_alt_state = get_free_alt_state ();
5981 new_alt_state->next_alt_state = curr_alt_state;
5982 new_alt_state->state = curr_arc->to_state;
5983 curr_alt_state = new_alt_state;
5985 else
5986 for (alt_state = curr_arc->to_state->component_states;
5987 alt_state != NULL;
5988 alt_state = alt_state->next_sorted_alt_state)
5990 new_alt_state = get_free_alt_state ();
5991 new_alt_state->next_alt_state = curr_alt_state;
5992 new_alt_state->state = alt_state->state;
5993 if (alt_state->state->component_states != NULL)
5994 abort ();
5995 curr_alt_state = new_alt_state;
5997 /* There are not identical sets in the alt state list. */
5998 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5999 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
6001 temp_state = state;
6002 state = canonical_alt_states_list->state;
6003 free_state (temp_state);
6005 else
6007 state->component_states = canonical_alt_states_list;
6008 state_in_table = insert_state (state);
6009 if (state_in_table != state)
6011 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
6012 abort ();
6013 free_state (state);
6014 state = state_in_table;
6016 else
6018 if (state->it_was_placed_in_stack_for_DFA_forming)
6019 abort ();
6020 new_state_p = 1;
6021 for (curr_alt_state = state->component_states;
6022 curr_alt_state != NULL;
6023 curr_alt_state = curr_alt_state->next_sorted_alt_state)
6024 for (curr_arc = first_out_arc (curr_alt_state->state);
6025 curr_arc != NULL;
6026 curr_arc = next_out_arc (curr_arc))
6027 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
6029 arcs_marked_by_insn->to_state = state;
6030 for (alts_number = 0,
6031 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
6032 curr_arc != NULL;
6033 curr_arc = next_arc)
6035 next_arc = curr_arc->next_arc_marked_by_insn;
6036 remove_arc (original_state, curr_arc);
6037 alts_number++;
6039 arcs_marked_by_insn->state_alts = alts_number;
6042 if (!state->it_was_placed_in_stack_for_DFA_forming)
6044 state->it_was_placed_in_stack_for_DFA_forming = 1;
6045 VLA_PTR_ADD (*state_stack, state);
6047 return new_state_p;
6050 /* The function transforms nondeterministic AUTOMATON into
6051 deterministic. */
6052 static void
6053 NDFA_to_DFA (automaton)
6054 automaton_t automaton;
6056 state_t start_state;
6057 state_t state;
6058 decl_t decl;
6059 vla_ptr_t state_stack;
6060 int i;
6061 int states_n;
6063 VLA_PTR_CREATE (state_stack, 150, "state stack");
6064 /* Create the start state (empty state). */
6065 start_state = automaton->start_state;
6066 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
6067 VLA_PTR_ADD (state_stack, start_state);
6068 states_n = 1;
6069 while (VLA_PTR_LENGTH (state_stack) != 0)
6071 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
6072 VLA_PTR_SHORTEN (state_stack, 1);
6073 form_arcs_marked_by_insn (state);
6074 for (i = 0; i < description->decls_num; i++)
6076 decl = description->decls [i];
6077 if (decl->mode == dm_insn_reserv
6078 && create_composed_state
6079 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
6080 &state_stack))
6082 states_n++;
6083 if (states_n % 100 == 0)
6084 fprintf (stderr, "*");
6088 VLA_PTR_DELETE (state_stack);
6091 /* The following variable value is current number (1, 2, ...) of passing
6092 graph of states. */
6093 static int curr_state_graph_pass_num;
6095 /* This recursive function passes all states achieved from START_STATE
6096 and applies APPLIED_FUNC to them. */
6097 static void
6098 pass_state_graph (start_state, applied_func)
6099 state_t start_state;
6100 void (*applied_func) PARAMS ((state_t state));
6102 arc_t arc;
6104 if (start_state->pass_num == curr_state_graph_pass_num)
6105 return;
6106 start_state->pass_num = curr_state_graph_pass_num;
6107 (*applied_func) (start_state);
6108 for (arc = first_out_arc (start_state);
6109 arc != NULL;
6110 arc = next_out_arc (arc))
6111 pass_state_graph (arc->to_state, applied_func);
6114 /* This recursive function passes all states of AUTOMATON and applies
6115 APPLIED_FUNC to them. */
6116 static void
6117 pass_states (automaton, applied_func)
6118 automaton_t automaton;
6119 void (*applied_func) PARAMS ((state_t state));
6121 curr_state_graph_pass_num++;
6122 pass_state_graph (automaton->start_state, applied_func);
6125 /* The function initializes code for passing of all states. */
6126 static void
6127 initiate_pass_states ()
6129 curr_state_graph_pass_num = 0;
6132 /* The following vla is used for storing pointers to all achieved
6133 states. */
6134 static vla_ptr_t all_achieved_states;
6136 /* This function is called by function pass_states to add an achieved
6137 STATE. */
6138 static void
6139 add_achieved_state (state)
6140 state_t state;
6142 VLA_PTR_ADD (all_achieved_states, state);
6145 /* The function sets up equivalence numbers of insns which mark all
6146 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
6147 nonzero value) or by equiv_class_num_2 of the destination state.
6148 The function returns number of out arcs of STATE. */
6149 static int
6150 set_out_arc_insns_equiv_num (state, odd_iteration_flag)
6151 state_t state;
6152 int odd_iteration_flag;
6154 int state_out_arcs_num;
6155 arc_t arc;
6157 state_out_arcs_num = 0;
6158 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6160 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
6161 || arc->insn->insn_reserv_decl->state_alts != 0)
6162 abort ();
6163 state_out_arcs_num++;
6164 arc->insn->insn_reserv_decl->equiv_class_num
6165 = (odd_iteration_flag
6166 ? arc->to_state->equiv_class_num_1
6167 : arc->to_state->equiv_class_num_2);
6168 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
6169 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
6170 || arc->insn->insn_reserv_decl->state_alts <= 0)
6171 abort ();
6173 return state_out_arcs_num;
6176 /* The function clears equivalence numbers and alt_states in all insns
6177 which mark all out arcs of STATE. */
6178 static void
6179 clear_arc_insns_equiv_num (state)
6180 state_t state;
6182 arc_t arc;
6184 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6186 arc->insn->insn_reserv_decl->equiv_class_num = 0;
6187 arc->insn->insn_reserv_decl->state_alts = 0;
6191 /* The function copies pointers to equivalent states from vla FROM
6192 into vla TO. */
6193 static void
6194 copy_equiv_class (to, from)
6195 vla_ptr_t *to;
6196 const vla_ptr_t *from;
6198 state_t *class_ptr;
6200 VLA_PTR_NULLIFY (*to);
6201 for (class_ptr = VLA_PTR_BEGIN (*from);
6202 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
6203 class_ptr++)
6204 VLA_PTR_ADD (*to, *class_ptr);
6207 /* The following function returns TRUE if STATE reserves the unit with
6208 UNIT_NUM on the first cycle. */
6209 static int
6210 first_cycle_unit_presence (state, unit_num)
6211 state_t state;
6212 int unit_num;
6214 int presence_p;
6216 if (state->component_states == NULL)
6217 presence_p = test_unit_reserv (state->reservs, 0, unit_num);
6218 else
6219 presence_p
6220 = test_unit_reserv (state->component_states->state->reservs,
6221 0, unit_num);
6222 return presence_p;
6225 /* The function returns nonzero value if STATE is not equivalent to
6226 ANOTHER_STATE from the same current partition on equivalence
6227 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
6228 output arcs. Iteration of making equivalence partition is defined
6229 by ODD_ITERATION_FLAG. */
6230 static int
6231 state_is_differed (state, another_state, another_state_out_arcs_num,
6232 odd_iteration_flag)
6233 state_t state, another_state;
6234 int another_state_out_arcs_num;
6235 int odd_iteration_flag;
6237 arc_t arc;
6238 int state_out_arcs_num;
6239 int i, presence1_p, presence2_p;
6241 state_out_arcs_num = 0;
6242 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6244 state_out_arcs_num++;
6245 if ((odd_iteration_flag
6246 ? arc->to_state->equiv_class_num_1
6247 : arc->to_state->equiv_class_num_2)
6248 != arc->insn->insn_reserv_decl->equiv_class_num
6249 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
6250 return 1;
6252 if (state_out_arcs_num != another_state_out_arcs_num)
6253 return 1;
6254 /* Now we are looking at the states with the point of view of query
6255 units. */
6256 for (i = 0; i < description->units_num; i++)
6257 if (units_array [i]->query_p)
6259 presence1_p = first_cycle_unit_presence (state, i);
6260 presence2_p = first_cycle_unit_presence (another_state, i);
6261 if ((presence1_p && !presence2_p) || (!presence1_p && presence2_p))
6262 return 1;
6264 return 0;
6267 /* The function makes initial partition of STATES on equivalent
6268 classes. */
6269 static state_t
6270 init_equiv_class (states, states_num)
6271 state_t *states;
6272 int states_num;
6274 state_t *state_ptr;
6275 state_t result_equiv_class;
6277 result_equiv_class = NULL;
6278 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
6280 (*state_ptr)->equiv_class_num_1 = 1;
6281 (*state_ptr)->next_equiv_class_state = result_equiv_class;
6282 result_equiv_class = *state_ptr;
6284 return result_equiv_class;
6287 /* The function processes equivalence class given by its pointer
6288 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
6289 are not equivalent states, the function partitions the class
6290 removing nonequivalent states and placing them in
6291 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6292 assigns it to the state equivalence number. If the class has been
6293 partitioned, the function returns nonzero value. */
6294 static int
6295 partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6296 next_iteration_classes, new_equiv_class_num_ptr)
6297 state_t *equiv_class_ptr;
6298 int odd_iteration_flag;
6299 vla_ptr_t *next_iteration_classes;
6300 int *new_equiv_class_num_ptr;
6302 state_t new_equiv_class;
6303 int partition_p;
6304 state_t first_state;
6305 state_t curr_state;
6306 state_t prev_state;
6307 state_t next_state;
6308 int out_arcs_num;
6310 partition_p = 0;
6311 if (*equiv_class_ptr == NULL)
6312 abort ();
6313 for (first_state = *equiv_class_ptr;
6314 first_state != NULL;
6315 first_state = new_equiv_class)
6317 new_equiv_class = NULL;
6318 if (first_state->next_equiv_class_state != NULL)
6320 /* There are more one states in the class equivalence. */
6321 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
6322 odd_iteration_flag);
6323 for (prev_state = first_state,
6324 curr_state = first_state->next_equiv_class_state;
6325 curr_state != NULL;
6326 curr_state = next_state)
6328 next_state = curr_state->next_equiv_class_state;
6329 if (state_is_differed (curr_state, first_state, out_arcs_num,
6330 odd_iteration_flag))
6332 /* Remove curr state from the class equivalence. */
6333 prev_state->next_equiv_class_state = next_state;
6334 /* Add curr state to the new class equivalence. */
6335 curr_state->next_equiv_class_state = new_equiv_class;
6336 if (new_equiv_class == NULL)
6337 (*new_equiv_class_num_ptr)++;
6338 if (odd_iteration_flag)
6339 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6340 else
6341 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6342 new_equiv_class = curr_state;
6343 partition_p = 1;
6345 else
6346 prev_state = curr_state;
6348 clear_arc_insns_equiv_num (first_state);
6350 if (new_equiv_class != NULL)
6351 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
6353 return partition_p;
6356 /* The function finds equivalent states of AUTOMATON. */
6357 static void
6358 evaluate_equiv_classes (automaton, equiv_classes)
6359 automaton_t automaton;
6360 vla_ptr_t *equiv_classes;
6362 state_t new_equiv_class;
6363 int new_equiv_class_num;
6364 int odd_iteration_flag;
6365 int finish_flag;
6366 vla_ptr_t next_iteration_classes;
6367 state_t *equiv_class_ptr;
6368 state_t *state_ptr;
6370 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6371 pass_states (automaton, add_achieved_state);
6372 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6373 VLA_PTR_LENGTH (all_achieved_states));
6374 odd_iteration_flag = 0;
6375 new_equiv_class_num = 1;
6376 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6377 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6380 odd_iteration_flag = !odd_iteration_flag;
6381 finish_flag = 1;
6382 copy_equiv_class (equiv_classes, &next_iteration_classes);
6383 /* Transfer equiv numbers for the next iteration. */
6384 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6385 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6386 state_ptr++)
6387 if (odd_iteration_flag)
6388 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6389 else
6390 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6391 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6392 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6393 equiv_class_ptr++)
6394 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6395 &next_iteration_classes,
6396 &new_equiv_class_num))
6397 finish_flag = 0;
6399 while (!finish_flag);
6400 VLA_PTR_DELETE (next_iteration_classes);
6401 VLA_PTR_DELETE (all_achieved_states);
6404 /* The function merges equivalent states of AUTOMATON. */
6405 static void
6406 merge_states (automaton, equiv_classes)
6407 automaton_t automaton;
6408 vla_ptr_t *equiv_classes;
6410 state_t *equiv_class_ptr;
6411 state_t curr_state;
6412 state_t new_state;
6413 state_t first_class_state;
6414 alt_state_t alt_states;
6415 alt_state_t alt_state, new_alt_state;
6416 arc_t curr_arc;
6417 arc_t next_arc;
6419 /* Create states corresponding to equivalence classes containing two
6420 or more states. */
6421 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6422 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6423 equiv_class_ptr++)
6424 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6426 /* There are more one states in the class equivalence. */
6427 /* Create new compound state. */
6428 new_state = get_free_state (0, automaton);
6429 alt_states = NULL;
6430 first_class_state = *equiv_class_ptr;
6431 for (curr_state = first_class_state;
6432 curr_state != NULL;
6433 curr_state = curr_state->next_equiv_class_state)
6435 curr_state->equiv_class_state = new_state;
6436 if (curr_state->component_states == NULL)
6438 new_alt_state = get_free_alt_state ();
6439 new_alt_state->state = curr_state;
6440 new_alt_state->next_alt_state = alt_states;
6441 alt_states = new_alt_state;
6443 else
6444 for (alt_state = curr_state->component_states;
6445 alt_state != NULL;
6446 alt_state = alt_state->next_sorted_alt_state)
6448 new_alt_state = get_free_alt_state ();
6449 new_alt_state->state = alt_state->state;
6450 new_alt_state->next_alt_state = alt_states;
6451 alt_states = new_alt_state;
6454 /* Its is important that alt states were sorted before and
6455 after merging to have the same quering results. */
6456 new_state->component_states = uniq_sort_alt_states (alt_states);
6458 else
6459 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6460 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6461 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6462 equiv_class_ptr++)
6463 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6465 first_class_state = *equiv_class_ptr;
6466 /* Create new arcs output from the state corresponding to
6467 equiv class. */
6468 for (curr_arc = first_out_arc (first_class_state);
6469 curr_arc != NULL;
6470 curr_arc = next_out_arc (curr_arc))
6471 add_arc (first_class_state->equiv_class_state,
6472 curr_arc->to_state->equiv_class_state,
6473 curr_arc->insn, curr_arc->state_alts);
6474 /* Delete output arcs from states of given class equivalence. */
6475 for (curr_state = first_class_state;
6476 curr_state != NULL;
6477 curr_state = curr_state->next_equiv_class_state)
6479 if (automaton->start_state == curr_state)
6480 automaton->start_state = curr_state->equiv_class_state;
6481 /* Delete the state and its output arcs. */
6482 for (curr_arc = first_out_arc (curr_state);
6483 curr_arc != NULL;
6484 curr_arc = next_arc)
6486 next_arc = next_out_arc (curr_arc);
6487 free_arc (curr_arc);
6491 else
6493 /* Change `to_state' of arcs output from the state of given
6494 equivalence class. */
6495 for (curr_arc = first_out_arc (*equiv_class_ptr);
6496 curr_arc != NULL;
6497 curr_arc = next_out_arc (curr_arc))
6498 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6502 /* The function sets up new_cycle_p for states if there is arc to the
6503 state marked by advance_cycle_insn_decl. */
6504 static void
6505 set_new_cycle_flags (state)
6506 state_t state;
6508 arc_t arc;
6510 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6511 if (arc->insn->insn_reserv_decl
6512 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6513 arc->to_state->new_cycle_p = 1;
6516 /* The top level function for minimization of deterministic
6517 AUTOMATON. */
6518 static void
6519 minimize_DFA (automaton)
6520 automaton_t automaton;
6522 vla_ptr_t equiv_classes;
6524 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6525 evaluate_equiv_classes (automaton, &equiv_classes);
6526 merge_states (automaton, &equiv_classes);
6527 pass_states (automaton, set_new_cycle_flags);
6528 VLA_PTR_DELETE (equiv_classes);
6531 /* Values of two variables are counted number of states and arcs in an
6532 automaton. */
6533 static int curr_counted_states_num;
6534 static int curr_counted_arcs_num;
6536 /* The function is called by function `pass_states' to count states
6537 and arcs of an automaton. */
6538 static void
6539 incr_states_and_arcs_nums (state)
6540 state_t state;
6542 arc_t arc;
6544 curr_counted_states_num++;
6545 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6546 curr_counted_arcs_num++;
6549 /* The function counts states and arcs of AUTOMATON. */
6550 static void
6551 count_states_and_arcs (automaton, states_num, arcs_num)
6552 automaton_t automaton;
6553 int *states_num;
6554 int *arcs_num;
6556 curr_counted_states_num = 0;
6557 curr_counted_arcs_num = 0;
6558 pass_states (automaton, incr_states_and_arcs_nums);
6559 *states_num = curr_counted_states_num;
6560 *arcs_num = curr_counted_arcs_num;
6563 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6564 recognition after checking and simplifying IR of the
6565 description. */
6566 static void
6567 build_automaton (automaton)
6568 automaton_t automaton;
6570 int states_num;
6571 int arcs_num;
6573 ticker_on (&NDFA_time);
6574 if (automaton->corresponding_automaton_decl == NULL)
6575 fprintf (stderr, "Create anonymous automaton (1 star is 100 new states):");
6576 else
6577 fprintf (stderr, "Create automaton `%s' (1 star is 100 new states):",
6578 automaton->corresponding_automaton_decl->name);
6579 make_automaton (automaton);
6580 fprintf (stderr, " done\n");
6581 ticker_off (&NDFA_time);
6582 count_states_and_arcs (automaton, &states_num, &arcs_num);
6583 automaton->NDFA_states_num = states_num;
6584 automaton->NDFA_arcs_num = arcs_num;
6585 ticker_on (&NDFA_to_DFA_time);
6586 if (automaton->corresponding_automaton_decl == NULL)
6587 fprintf (stderr, "Make anonymous DFA (1 star is 100 new states):");
6588 else
6589 fprintf (stderr, "Make DFA `%s' (1 star is 100 new states):",
6590 automaton->corresponding_automaton_decl->name);
6591 NDFA_to_DFA (automaton);
6592 fprintf (stderr, " done\n");
6593 ticker_off (&NDFA_to_DFA_time);
6594 count_states_and_arcs (automaton, &states_num, &arcs_num);
6595 automaton->DFA_states_num = states_num;
6596 automaton->DFA_arcs_num = arcs_num;
6597 if (!no_minimization_flag)
6599 ticker_on (&minimize_time);
6600 if (automaton->corresponding_automaton_decl == NULL)
6601 fprintf (stderr, "Minimize anonymous DFA...");
6602 else
6603 fprintf (stderr, "Minimize DFA `%s'...",
6604 automaton->corresponding_automaton_decl->name);
6605 minimize_DFA (automaton);
6606 fprintf (stderr, "done\n");
6607 ticker_off (&minimize_time);
6608 count_states_and_arcs (automaton, &states_num, &arcs_num);
6609 automaton->minimal_DFA_states_num = states_num;
6610 automaton->minimal_DFA_arcs_num = arcs_num;
6616 /* The page contains code for enumeration of all states of an automaton. */
6618 /* Variable used for enumeration of all states of an automaton. Its
6619 value is current number of automaton states. */
6620 static int curr_state_order_num;
6622 /* The function is called by function `pass_states' for enumerating
6623 states. */
6624 static void
6625 set_order_state_num (state)
6626 state_t state;
6628 state->order_state_num = curr_state_order_num;
6629 curr_state_order_num++;
6632 /* The function enumerates all states of AUTOMATON. */
6633 static void
6634 enumerate_states (automaton)
6635 automaton_t automaton;
6637 curr_state_order_num = 0;
6638 pass_states (automaton, set_order_state_num);
6639 automaton->achieved_states_num = curr_state_order_num;
6644 /* The page contains code for finding equivalent automaton insns
6645 (ainsns). */
6647 /* The function inserts AINSN into cyclic list
6648 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6649 static ainsn_t
6650 insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6651 ainsn_t ainsn;
6652 ainsn_t cyclic_equiv_class_insn_list;
6654 if (cyclic_equiv_class_insn_list == NULL)
6655 ainsn->next_equiv_class_insn = ainsn;
6656 else
6658 ainsn->next_equiv_class_insn
6659 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6660 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6662 return ainsn;
6665 /* The function deletes equiv_class_insn into cyclic list of
6666 equivalent ainsns. */
6667 static void
6668 delete_ainsn_from_equiv_class (equiv_class_insn)
6669 ainsn_t equiv_class_insn;
6671 ainsn_t curr_equiv_class_insn;
6672 ainsn_t prev_equiv_class_insn;
6674 prev_equiv_class_insn = equiv_class_insn;
6675 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6676 curr_equiv_class_insn != equiv_class_insn;
6677 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6678 prev_equiv_class_insn = curr_equiv_class_insn;
6679 if (prev_equiv_class_insn != equiv_class_insn)
6680 prev_equiv_class_insn->next_equiv_class_insn
6681 = equiv_class_insn->next_equiv_class_insn;
6684 /* The function processes AINSN of a state in order to find equivalent
6685 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6686 state. */
6687 static void
6688 process_insn_equiv_class (ainsn, insn_arcs_array)
6689 ainsn_t ainsn;
6690 arc_t *insn_arcs_array;
6692 ainsn_t next_insn;
6693 ainsn_t curr_insn;
6694 ainsn_t cyclic_insn_list;
6695 arc_t arc;
6697 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6698 abort ();
6699 curr_insn = ainsn;
6700 /* New class of ainsns which are not equivalent to given ainsn. */
6701 cyclic_insn_list = NULL;
6704 next_insn = curr_insn->next_equiv_class_insn;
6705 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6706 if (arc == NULL
6707 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6708 != arc->to_state))
6710 delete_ainsn_from_equiv_class (curr_insn);
6711 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6712 cyclic_insn_list);
6714 curr_insn = next_insn;
6716 while (curr_insn != ainsn);
6719 /* The function processes STATE in order to find equivalent ainsns. */
6720 static void
6721 process_state_for_insn_equiv_partition (state)
6722 state_t state;
6724 arc_t arc;
6725 arc_t *insn_arcs_array;
6726 int i;
6727 vla_ptr_t insn_arcs_vect;
6729 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6730 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6731 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6732 /* Process insns of the arcs. */
6733 for (i = 0; i < description->insns_num; i++)
6734 insn_arcs_array [i] = NULL;
6735 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6736 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6737 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6738 process_insn_equiv_class (arc->insn, insn_arcs_array);
6739 VLA_PTR_DELETE (insn_arcs_vect);
6742 /* The function searches for equivalent ainsns of AUTOMATON. */
6743 static void
6744 set_insn_equiv_classes (automaton)
6745 automaton_t automaton;
6747 ainsn_t ainsn;
6748 ainsn_t first_insn;
6749 ainsn_t curr_insn;
6750 ainsn_t cyclic_insn_list;
6751 ainsn_t insn_with_same_reservs;
6752 int equiv_classes_num;
6754 /* All insns are included in one equivalence class. */
6755 cyclic_insn_list = NULL;
6756 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6757 if (ainsn->first_insn_with_same_reservs)
6758 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6759 cyclic_insn_list);
6760 /* Process insns in order to make equivalence partition. */
6761 pass_states (automaton, process_state_for_insn_equiv_partition);
6762 /* Enumerate equiv classes. */
6763 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6764 /* Set undefined value. */
6765 ainsn->insn_equiv_class_num = -1;
6766 equiv_classes_num = 0;
6767 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6768 if (ainsn->insn_equiv_class_num < 0)
6770 first_insn = ainsn;
6771 if (!first_insn->first_insn_with_same_reservs)
6772 abort ();
6773 first_insn->first_ainsn_with_given_equialence_num = 1;
6774 curr_insn = first_insn;
6777 for (insn_with_same_reservs = curr_insn;
6778 insn_with_same_reservs != NULL;
6779 insn_with_same_reservs
6780 = insn_with_same_reservs->next_same_reservs_insn)
6781 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6782 curr_insn = curr_insn->next_equiv_class_insn;
6784 while (curr_insn != first_insn);
6785 equiv_classes_num++;
6787 automaton->insn_equiv_classes_num = equiv_classes_num;
6792 /* This page contains code for creating DFA(s) and calls functions
6793 building them. */
6796 /* The following value is used to prevent floating point overflow for
6797 estimating an automaton bound. The value should be less DBL_MAX on
6798 the host machine. We use here approximate minimum of maximal
6799 double floating point value required by ANSI C standard. It
6800 will work for non ANSI sun compiler too. */
6802 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6804 /* The function estimate size of the single DFA used by PHR (pipeline
6805 hazards recognizer). */
6806 static double
6807 estimate_one_automaton_bound ()
6809 decl_t decl;
6810 double one_automaton_estimation_bound;
6811 double root_value;
6812 int i;
6814 one_automaton_estimation_bound = 1.0;
6815 for (i = 0; i < description->decls_num; i++)
6817 decl = description->decls [i];
6818 if (decl->mode == dm_unit)
6820 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6821 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6822 / automata_num);
6823 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6824 > one_automaton_estimation_bound)
6825 one_automaton_estimation_bound *= root_value;
6828 return one_automaton_estimation_bound;
6831 /* The function compares unit declarations according to their maximal
6832 cycle in reservations. */
6833 static int
6834 compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6835 const void *unit_decl_1;
6836 const void *unit_decl_2;
6838 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6839 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6840 return 1;
6841 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6842 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6843 return 0;
6844 else
6845 return -1;
6848 /* The function makes heuristic assigning automata to units. Actually
6849 efficacy of the algorithm has been checked yet??? */
6850 static void
6851 units_to_automata_heuristic_distr ()
6853 double estimation_bound;
6854 decl_t decl;
6855 decl_t *unit_decl_ptr;
6856 int automaton_num;
6857 int rest_units_num;
6858 double bound_value;
6859 vla_ptr_t unit_decls;
6860 int i;
6862 if (description->units_num == 0)
6863 return;
6864 estimation_bound = estimate_one_automaton_bound ();
6865 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6866 for (i = 0; i < description->decls_num; i++)
6868 decl = description->decls [i];
6869 if (decl->mode == dm_unit)
6870 VLA_PTR_ADD (unit_decls, decl);
6872 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6873 sizeof (decl_t), compare_max_occ_cycle_nums);
6874 automaton_num = 0;
6875 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6876 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6877 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6878 for (unit_decl_ptr++;
6879 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6880 unit_decl_ptr++)
6882 rest_units_num
6883 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6884 if (automata_num - automaton_num - 1 > rest_units_num)
6885 abort ();
6886 if (automaton_num < automata_num - 1
6887 && ((automata_num - automaton_num - 1 == rest_units_num)
6888 || (bound_value
6889 > (estimation_bound
6890 / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6892 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6893 automaton_num++;
6895 else
6896 bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6897 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6899 if (automaton_num != automata_num - 1)
6900 abort ();
6901 VLA_PTR_DELETE (unit_decls);
6904 /* The functions creates automaton insns for each automata. Automaton
6905 insn is simply insn for given automaton which makes reservation
6906 only of units of the automaton. */
6907 static ainsn_t
6908 create_ainsns ()
6910 decl_t decl;
6911 ainsn_t first_ainsn;
6912 ainsn_t curr_ainsn;
6913 ainsn_t prev_ainsn;
6914 int i;
6916 first_ainsn = NULL;
6917 prev_ainsn = NULL;
6918 for (i = 0; i < description->decls_num; i++)
6920 decl = description->decls [i];
6921 if (decl->mode == dm_insn_reserv)
6923 curr_ainsn = create_node (sizeof (struct ainsn));
6924 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6925 curr_ainsn->important_p = FALSE;
6926 curr_ainsn->next_ainsn = NULL;
6927 if (prev_ainsn == NULL)
6928 first_ainsn = curr_ainsn;
6929 else
6930 prev_ainsn->next_ainsn = curr_ainsn;
6931 prev_ainsn = curr_ainsn;
6934 return first_ainsn;
6937 /* The function assigns automata to units according to constructions
6938 `define_automaton' in the description. */
6939 static void
6940 units_to_automata_distr ()
6942 decl_t decl;
6943 int i;
6945 for (i = 0; i < description->decls_num; i++)
6947 decl = description->decls [i];
6948 if (decl->mode == dm_unit)
6950 if (DECL_UNIT (decl)->automaton_decl == NULL
6951 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6952 == NULL))
6953 /* Distribute to the first automaton. */
6954 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6955 else
6956 DECL_UNIT (decl)->corresponding_automaton_num
6957 = (DECL_UNIT (decl)->automaton_decl
6958 ->corresponding_automaton->automaton_order_num);
6963 /* The function creates DFA(s) for fast pipeline hazards recognition
6964 after checking and simplifying IR of the description. */
6965 static void
6966 create_automata ()
6968 automaton_t curr_automaton;
6969 automaton_t prev_automaton;
6970 decl_t decl;
6971 int curr_automaton_num;
6972 int i;
6974 if (automata_num != 0)
6976 units_to_automata_heuristic_distr ();
6977 for (prev_automaton = NULL, curr_automaton_num = 0;
6978 curr_automaton_num < automata_num;
6979 curr_automaton_num++, prev_automaton = curr_automaton)
6981 curr_automaton = create_node (sizeof (struct automaton));
6982 curr_automaton->ainsn_list = create_ainsns ();
6983 curr_automaton->corresponding_automaton_decl = NULL;
6984 curr_automaton->next_automaton = NULL;
6985 curr_automaton->automaton_order_num = curr_automaton_num;
6986 if (prev_automaton == NULL)
6987 description->first_automaton = curr_automaton;
6988 else
6989 prev_automaton->next_automaton = curr_automaton;
6992 else
6994 curr_automaton_num = 0;
6995 prev_automaton = NULL;
6996 for (i = 0; i < description->decls_num; i++)
6998 decl = description->decls [i];
6999 if (decl->mode == dm_automaton
7000 && DECL_AUTOMATON (decl)->automaton_is_used)
7002 curr_automaton = create_node (sizeof (struct automaton));
7003 curr_automaton->ainsn_list = create_ainsns ();
7004 curr_automaton->corresponding_automaton_decl
7005 = DECL_AUTOMATON (decl);
7006 curr_automaton->next_automaton = NULL;
7007 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
7008 curr_automaton->automaton_order_num = curr_automaton_num;
7009 if (prev_automaton == NULL)
7010 description->first_automaton = curr_automaton;
7011 else
7012 prev_automaton->next_automaton = curr_automaton;
7013 curr_automaton_num++;
7014 prev_automaton = curr_automaton;
7017 if (curr_automaton_num == 0)
7019 curr_automaton = create_node (sizeof (struct automaton));
7020 curr_automaton->ainsn_list = create_ainsns ();
7021 curr_automaton->corresponding_automaton_decl = NULL;
7022 curr_automaton->next_automaton = NULL;
7023 description->first_automaton = curr_automaton;
7025 units_to_automata_distr ();
7027 NDFA_time = create_ticker ();
7028 ticker_off (&NDFA_time);
7029 NDFA_to_DFA_time = create_ticker ();
7030 ticker_off (&NDFA_to_DFA_time);
7031 minimize_time = create_ticker ();
7032 ticker_off (&minimize_time);
7033 equiv_time = create_ticker ();
7034 ticker_off (&equiv_time);
7035 for (curr_automaton = description->first_automaton;
7036 curr_automaton != NULL;
7037 curr_automaton = curr_automaton->next_automaton)
7039 if (curr_automaton->corresponding_automaton_decl == NULL)
7040 fprintf (stderr, "Prepare anonymous automaton creation ... ");
7041 else
7042 fprintf (stderr, "Prepare automaton `%s' creation...",
7043 curr_automaton->corresponding_automaton_decl->name);
7044 create_alt_states (curr_automaton);
7045 form_ainsn_with_same_reservs (curr_automaton);
7046 fprintf (stderr, "done\n");
7047 build_automaton (curr_automaton);
7048 enumerate_states (curr_automaton);
7049 ticker_on (&equiv_time);
7050 set_insn_equiv_classes (curr_automaton);
7051 ticker_off (&equiv_time);
7057 /* This page contains code for forming string representation of
7058 regexp. The representation is formed on IR obstack. So you should
7059 not work with IR obstack between regexp_representation and
7060 finish_regexp_representation calls. */
7062 /* This recursive function forms string representation of regexp
7063 (without tailing '\0'). */
7064 static void
7065 form_regexp (regexp)
7066 regexp_t regexp;
7068 int i;
7070 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
7072 const char *name = (regexp->mode == rm_unit
7073 ? REGEXP_UNIT (regexp)->name
7074 : REGEXP_RESERV (regexp)->name);
7076 obstack_grow (&irp, name, strlen (name));
7078 else if (regexp->mode == rm_sequence)
7079 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
7081 if (i != 0)
7082 obstack_1grow (&irp, ',');
7083 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
7085 else if (regexp->mode == rm_allof)
7087 obstack_1grow (&irp, '(');
7088 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
7090 if (i != 0)
7091 obstack_1grow (&irp, '+');
7092 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
7093 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
7094 obstack_1grow (&irp, '(');
7095 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
7096 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
7097 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
7098 obstack_1grow (&irp, ')');
7100 obstack_1grow (&irp, ')');
7102 else if (regexp->mode == rm_oneof)
7103 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
7105 if (i != 0)
7106 obstack_1grow (&irp, '|');
7107 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
7108 obstack_1grow (&irp, '(');
7109 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
7110 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
7111 obstack_1grow (&irp, ')');
7113 else if (regexp->mode == rm_repeat)
7115 char digits [30];
7117 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
7118 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
7119 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
7120 obstack_1grow (&irp, '(');
7121 form_regexp (REGEXP_REPEAT (regexp)->regexp);
7122 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
7123 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
7124 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
7125 obstack_1grow (&irp, ')');
7126 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
7127 obstack_grow (&irp, digits, strlen (digits));
7129 else if (regexp->mode == rm_nothing)
7130 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
7131 else
7132 abort ();
7135 /* The function returns string representation of REGEXP on IR
7136 obstack. */
7137 static const char *
7138 regexp_representation (regexp)
7139 regexp_t regexp;
7141 form_regexp (regexp);
7142 obstack_1grow (&irp, '\0');
7143 return obstack_base (&irp);
7146 /* The function frees memory allocated for last formed string
7147 representation of regexp. */
7148 static void
7149 finish_regexp_representation ()
7151 int length = obstack_object_size (&irp);
7153 obstack_blank_fast (&irp, -length);
7158 /* This page contains code for output PHR (pipeline hazards recognizer). */
7160 /* The function outputs minimal C type which is sufficient for
7161 representation numbers in range min_range_value and
7162 max_range_value. Because host machine and build machine may be
7163 different, we use here minimal values required by ANSI C standard
7164 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
7165 approximation. */
7167 static void
7168 output_range_type (f, min_range_value, max_range_value)
7169 FILE *f;
7170 long int min_range_value;
7171 long int max_range_value;
7173 if (min_range_value >= 0 && max_range_value <= 255)
7174 fprintf (f, "unsigned char");
7175 else if (min_range_value >= -127 && max_range_value <= 127)
7176 fprintf (f, "signed char");
7177 else if (min_range_value >= 0 && max_range_value <= 65535)
7178 fprintf (f, "unsigned short");
7179 else if (min_range_value >= -32767 && max_range_value <= 32767)
7180 fprintf (f, "short");
7181 else
7182 fprintf (f, "int");
7185 /* The following macro value is used as value of member
7186 `longest_path_length' of state when we are processing path and the
7187 state on the path. */
7189 #define ON_THE_PATH -2
7191 /* The following recursive function searches for the length of the
7192 longest path starting from STATE which does not contain cycles and
7193 `cycle advance' arcs. */
7195 static int
7196 longest_path_length (state)
7197 state_t state;
7199 arc_t arc;
7200 int length, result;
7202 if (state->longest_path_length == ON_THE_PATH)
7203 /* We don't expect the path cycle here. Our graph may contain
7204 only cycles with one state on the path not containing `cycle
7205 advance' arcs -- see comment below. */
7206 abort ();
7207 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
7208 /* We already visited the state. */
7209 return state->longest_path_length;
7211 result = 0;
7212 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7213 /* Ignore cycles containing one state and `cycle advance' arcs. */
7214 if (arc->to_state != state
7215 && (arc->insn->insn_reserv_decl
7216 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
7218 length = longest_path_length (arc->to_state);
7219 if (length > result)
7220 result = length;
7222 state->longest_path_length = result + 1;
7223 return result;
7226 /* The following variable value is value of the corresponding global
7227 variable in the automaton based pipeline interface. */
7229 static int max_dfa_issue_rate;
7231 /* The following function processes the longest path length staring
7232 from STATE to find MAX_DFA_ISSUE_RATE. */
7234 static void
7235 process_state_longest_path_length (state)
7236 state_t state;
7238 int value;
7240 value = longest_path_length (state);
7241 if (value > max_dfa_issue_rate)
7242 max_dfa_issue_rate = value;
7245 /* The following macro value is name of the corresponding global
7246 variable in the automaton based pipeline interface. */
7248 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
7250 /* The following function calculates value of the corresponding
7251 global variable and outputs its declaration. */
7253 static void
7254 output_dfa_max_issue_rate ()
7256 automaton_t automaton;
7258 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
7259 abort ();
7260 max_dfa_issue_rate = 0;
7261 for (automaton = description->first_automaton;
7262 automaton != NULL;
7263 automaton = automaton->next_automaton)
7264 pass_states (automaton, process_state_longest_path_length);
7265 fprintf (output_file, "\nint %s = %d;\n",
7266 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
7269 /* The function outputs all initialization values of VECT with length
7270 vect_length. */
7271 static void
7272 output_vect (vect, vect_length)
7273 vect_el_t *vect;
7274 int vect_length;
7276 int els_on_line;
7278 els_on_line = 1;
7279 if (vect_length == 0)
7280 fprintf (output_file,
7281 "0 /* This is dummy el because the vect is empty */");
7282 else
7286 fprintf (output_file, "%5ld", (long) *vect);
7287 vect_length--;
7288 if (els_on_line == 10)
7290 els_on_line = 0;
7291 fprintf (output_file, ",\n");
7293 else if (vect_length != 0)
7294 fprintf (output_file, ", ");
7295 els_on_line++;
7296 vect++;
7298 while (vect_length != 0);
7302 /* The following is name of the structure which represents DFA(s) for
7303 PHR. */
7304 #define CHIP_NAME "DFA_chip"
7306 /* The following is name of member which represents state of a DFA for
7307 PHR. */
7308 static void
7309 output_chip_member_name (f, automaton)
7310 FILE *f;
7311 automaton_t automaton;
7313 if (automaton->corresponding_automaton_decl == NULL)
7314 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
7315 else
7316 fprintf (f, "%s_automaton_state",
7317 automaton->corresponding_automaton_decl->name);
7320 /* The following is name of temporary variable which stores state of a
7321 DFA for PHR. */
7322 static void
7323 output_temp_chip_member_name (f, automaton)
7324 FILE *f;
7325 automaton_t automaton;
7327 fprintf (f, "_");
7328 output_chip_member_name (f, automaton);
7331 /* This is name of macro value which is code of pseudo_insn
7332 representing advancing cpu cycle. Its value is used as internal
7333 code unknown insn. */
7334 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7336 /* Output name of translate vector for given automaton. */
7337 static void
7338 output_translate_vect_name (f, automaton)
7339 FILE *f;
7340 automaton_t automaton;
7342 if (automaton->corresponding_automaton_decl == NULL)
7343 fprintf (f, "translate_%d", automaton->automaton_order_num);
7344 else
7345 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
7348 /* Output name for simple transition table representation. */
7349 static void
7350 output_trans_full_vect_name (f, automaton)
7351 FILE *f;
7352 automaton_t automaton;
7354 if (automaton->corresponding_automaton_decl == NULL)
7355 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7356 else
7357 fprintf (f, "%s_transitions",
7358 automaton->corresponding_automaton_decl->name);
7361 /* Output name of comb vector of the transition table for given
7362 automaton. */
7363 static void
7364 output_trans_comb_vect_name (f, automaton)
7365 FILE *f;
7366 automaton_t automaton;
7368 if (automaton->corresponding_automaton_decl == NULL)
7369 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7370 else
7371 fprintf (f, "%s_transitions",
7372 automaton->corresponding_automaton_decl->name);
7375 /* Output name of check vector of the transition table for given
7376 automaton. */
7377 static void
7378 output_trans_check_vect_name (f, automaton)
7379 FILE *f;
7380 automaton_t automaton;
7382 if (automaton->corresponding_automaton_decl == NULL)
7383 fprintf (f, "check_%d", automaton->automaton_order_num);
7384 else
7385 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7388 /* Output name of base vector of the transition table for given
7389 automaton. */
7390 static void
7391 output_trans_base_vect_name (f, automaton)
7392 FILE *f;
7393 automaton_t automaton;
7395 if (automaton->corresponding_automaton_decl == NULL)
7396 fprintf (f, "base_%d", automaton->automaton_order_num);
7397 else
7398 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7401 /* Output name for simple alternatives number representation. */
7402 static void
7403 output_state_alts_full_vect_name (f, automaton)
7404 FILE *f;
7405 automaton_t automaton;
7407 if (automaton->corresponding_automaton_decl == NULL)
7408 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7409 else
7410 fprintf (f, "%s_state_alts",
7411 automaton->corresponding_automaton_decl->name);
7414 /* Output name of comb vector of the alternatives number table for given
7415 automaton. */
7416 static void
7417 output_state_alts_comb_vect_name (f, automaton)
7418 FILE *f;
7419 automaton_t automaton;
7421 if (automaton->corresponding_automaton_decl == NULL)
7422 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7423 else
7424 fprintf (f, "%s_state_alts",
7425 automaton->corresponding_automaton_decl->name);
7428 /* Output name of check vector of the alternatives number table for given
7429 automaton. */
7430 static void
7431 output_state_alts_check_vect_name (f, automaton)
7432 FILE *f;
7433 automaton_t automaton;
7435 if (automaton->corresponding_automaton_decl == NULL)
7436 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7437 else
7438 fprintf (f, "%s_check_state_alts",
7439 automaton->corresponding_automaton_decl->name);
7442 /* Output name of base vector of the alternatives number table for given
7443 automaton. */
7444 static void
7445 output_state_alts_base_vect_name (f, automaton)
7446 FILE *f;
7447 automaton_t automaton;
7449 if (automaton->corresponding_automaton_decl == NULL)
7450 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7451 else
7452 fprintf (f, "%s_base_state_alts",
7453 automaton->corresponding_automaton_decl->name);
7456 /* Output name of simple min issue delay table representation. */
7457 static void
7458 output_min_issue_delay_vect_name (f, automaton)
7459 FILE *f;
7460 automaton_t automaton;
7462 if (automaton->corresponding_automaton_decl == NULL)
7463 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7464 else
7465 fprintf (f, "%s_min_issue_delay",
7466 automaton->corresponding_automaton_decl->name);
7469 /* Output name of deadlock vector for given automaton. */
7470 static void
7471 output_dead_lock_vect_name (f, automaton)
7472 FILE *f;
7473 automaton_t automaton;
7475 if (automaton->corresponding_automaton_decl == NULL)
7476 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7477 else
7478 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7481 /* Output name of reserved units table for AUTOMATON into file F. */
7482 static void
7483 output_reserved_units_table_name (f, automaton)
7484 FILE *f;
7485 automaton_t automaton;
7487 if (automaton->corresponding_automaton_decl == NULL)
7488 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7489 else
7490 fprintf (f, "%s_reserved_units",
7491 automaton->corresponding_automaton_decl->name);
7494 /* Name of the PHR interface macro. */
7495 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7497 /* Name of the PHR interface macro. */
7498 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7500 /* Names of an internal functions: */
7501 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7503 /* This is external type of DFA(s) state. */
7504 #define STATE_TYPE_NAME "state_t"
7506 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7508 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7510 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7512 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7514 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7516 /* Name of cache of insn dfa codes. */
7517 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7519 /* Name of length of cache of insn dfa codes. */
7520 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7522 /* Names of the PHR interface functions: */
7523 #define SIZE_FUNC_NAME "state_size"
7525 #define TRANSITION_FUNC_NAME "state_transition"
7527 #define STATE_ALTS_FUNC_NAME "state_alts"
7529 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7531 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7533 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7535 #define RESET_FUNC_NAME "state_reset"
7537 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7539 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7541 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7543 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7545 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7547 #define DFA_START_FUNC_NAME "dfa_start"
7549 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7551 /* Names of parameters of the PHR interface functions. */
7552 #define STATE_NAME "state"
7554 #define INSN_PARAMETER_NAME "insn"
7556 #define INSN2_PARAMETER_NAME "insn2"
7558 #define CHIP_PARAMETER_NAME "chip"
7560 #define FILE_PARAMETER_NAME "f"
7562 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7564 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7566 /* Names of the variables whose values are internal insn code of rtx
7567 insn. */
7568 #define INTERNAL_INSN_CODE_NAME "insn_code"
7570 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7572 /* Names of temporary variables in some functions. */
7573 #define TEMPORARY_VARIABLE_NAME "temp"
7575 #define I_VARIABLE_NAME "i"
7577 /* Name of result variable in some functions. */
7578 #define RESULT_VARIABLE_NAME "res"
7580 /* Name of function (attribute) to translate insn into internal insn
7581 code. */
7582 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7584 /* Name of function (attribute) to translate insn into internal insn
7585 code with caching. */
7586 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7588 /* Name of function (attribute) to translate insn into internal insn
7589 code. */
7590 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7592 /* Name of function (attribute) to translate insn into internal insn
7593 code. */
7594 #define BYPASS_P_FUNC_NAME "bypass_p"
7596 /* Output C type which is used for representation of codes of states
7597 of AUTOMATON. */
7598 static void
7599 output_state_member_type (f, automaton)
7600 FILE *f;
7601 automaton_t automaton;
7603 output_range_type (f, 0, automaton->achieved_states_num);
7606 /* Output definition of the structure representing current DFA(s)
7607 state(s). */
7608 static void
7609 output_chip_definitions ()
7611 automaton_t automaton;
7613 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7614 for (automaton = description->first_automaton;
7615 automaton != NULL;
7616 automaton = automaton->next_automaton)
7618 fprintf (output_file, " ");
7619 output_state_member_type (output_file, automaton);
7620 fprintf (output_file, " ");
7621 output_chip_member_name (output_file, automaton);
7622 fprintf (output_file, ";\n");
7624 fprintf (output_file, "};\n\n");
7625 #if 0
7626 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7627 #endif
7631 /* The function outputs translate vector of internal insn code into
7632 insn equivalence class number. The equivalence class number is
7633 used to access to table and vectors representing DFA(s). */
7634 static void
7635 output_translate_vect (automaton)
7636 automaton_t automaton;
7638 ainsn_t ainsn;
7639 int insn_value;
7640 vla_hwint_t translate_vect;
7642 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7643 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7644 for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
7645 /* Undefined value */
7646 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7647 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7648 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7649 = ainsn->insn_equiv_class_num;
7650 fprintf (output_file,
7651 "/* Vector translating external insn codes to internal ones.*/\n");
7652 fprintf (output_file, "static const ");
7653 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7654 fprintf (output_file, " ");
7655 output_translate_vect_name (output_file, automaton);
7656 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7657 output_vect (VLA_HWINT_BEGIN (translate_vect),
7658 VLA_HWINT_LENGTH (translate_vect));
7659 fprintf (output_file, "};\n\n");
7660 VLA_HWINT_DELETE (translate_vect);
7663 /* The value in a table state x ainsn -> something which represents
7664 undefined value. */
7665 static int undefined_vect_el_value;
7667 /* The following function returns nonzero value if the best
7668 representation of the table is comb vector. */
7669 static int
7670 comb_vect_p (tab)
7671 state_ainsn_table_t tab;
7673 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7674 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7677 /* The following function creates new table for AUTOMATON. */
7678 static state_ainsn_table_t
7679 create_state_ainsn_table (automaton)
7680 automaton_t automaton;
7682 state_ainsn_table_t tab;
7683 int full_vect_length;
7684 int i;
7686 tab = create_node (sizeof (struct state_ainsn_table));
7687 tab->automaton = automaton;
7688 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7689 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7690 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7691 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7692 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7693 full_vect_length = (automaton->insn_equiv_classes_num
7694 * automaton->achieved_states_num);
7695 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7696 for (i = 0; i < full_vect_length; i++)
7697 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7698 tab->min_base_vect_el_value = 0;
7699 tab->max_base_vect_el_value = 0;
7700 tab->min_comb_vect_el_value = 0;
7701 tab->max_comb_vect_el_value = 0;
7702 return tab;
7705 /* The following function outputs the best C representation of the
7706 table TAB of given TABLE_NAME. */
7707 static void
7708 output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7709 output_comb_vect_name_func,
7710 output_check_vect_name_func,
7711 output_base_vect_name_func)
7712 state_ainsn_table_t tab;
7713 char *table_name;
7714 void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7715 void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7716 void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7717 void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7719 if (!comb_vect_p (tab))
7721 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7722 fprintf (output_file, "static const ");
7723 output_range_type (output_file, tab->min_comb_vect_el_value,
7724 tab->max_comb_vect_el_value);
7725 fprintf (output_file, " ");
7726 (*output_full_vect_name_func) (output_file, tab->automaton);
7727 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7728 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7729 VLA_HWINT_LENGTH (tab->full_vect));
7730 fprintf (output_file, "};\n\n");
7732 else
7734 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7735 fprintf (output_file, "static const ");
7736 output_range_type (output_file, tab->min_comb_vect_el_value,
7737 tab->max_comb_vect_el_value);
7738 fprintf (output_file, " ");
7739 (*output_comb_vect_name_func) (output_file, tab->automaton);
7740 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7741 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7742 VLA_HWINT_LENGTH (tab->comb_vect));
7743 fprintf (output_file, "};\n\n");
7744 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7745 fprintf (output_file, "static const ");
7746 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7747 fprintf (output_file, " ");
7748 (*output_check_vect_name_func) (output_file, tab->automaton);
7749 fprintf (output_file, "[] = {\n");
7750 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7751 VLA_HWINT_LENGTH (tab->check_vect));
7752 fprintf (output_file, "};\n\n");
7753 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7754 fprintf (output_file, "static const ");
7755 output_range_type (output_file, tab->min_base_vect_el_value,
7756 tab->max_base_vect_el_value);
7757 fprintf (output_file, " ");
7758 (*output_base_vect_name_func) (output_file, tab->automaton);
7759 fprintf (output_file, "[] = {\n");
7760 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7761 VLA_HWINT_LENGTH (tab->base_vect));
7762 fprintf (output_file, "};\n\n");
7766 /* The following function adds vector with length VECT_LENGTH and
7767 elements pointed by VECT to table TAB as its line with number
7768 VECT_NUM. */
7769 static void
7770 add_vect (tab, vect_num, vect, vect_length)
7771 state_ainsn_table_t tab;
7772 int vect_num;
7773 vect_el_t *vect;
7774 int vect_length;
7776 int real_vect_length;
7777 vect_el_t *comb_vect_start;
7778 vect_el_t *check_vect_start;
7779 int comb_vect_index;
7780 int comb_vect_els_num;
7781 int vect_index;
7782 int first_unempty_vect_index;
7783 int additional_els_num;
7784 int no_state_value;
7785 vect_el_t vect_el;
7786 int i;
7788 if (vect_length == 0)
7789 abort ();
7790 real_vect_length = tab->automaton->insn_equiv_classes_num;
7791 if (vect [vect_length - 1] == undefined_vect_el_value)
7792 abort ();
7793 /* Form full vector in the table: */
7794 for (i = 0; i < vect_length; i++)
7795 VLA_HWINT (tab->full_vect,
7796 i + tab->automaton->insn_equiv_classes_num * vect_num)
7797 = vect [i];
7798 /* Form comb vector in the table: */
7799 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7800 abort ();
7801 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7802 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7803 for (first_unempty_vect_index = 0;
7804 first_unempty_vect_index < vect_length;
7805 first_unempty_vect_index++)
7806 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7807 break;
7808 /* Search for the place in comb vect for the inserted vect. */
7809 for (comb_vect_index = 0;
7810 comb_vect_index < comb_vect_els_num;
7811 comb_vect_index++)
7813 for (vect_index = first_unempty_vect_index;
7814 vect_index < vect_length
7815 && vect_index + comb_vect_index < comb_vect_els_num;
7816 vect_index++)
7817 if (vect [vect_index] != undefined_vect_el_value
7818 && (comb_vect_start [vect_index + comb_vect_index]
7819 != undefined_vect_el_value))
7820 break;
7821 if (vect_index >= vect_length
7822 || vect_index + comb_vect_index >= comb_vect_els_num)
7823 break;
7825 /* Slot was found. */
7826 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7827 if (additional_els_num < 0)
7828 additional_els_num = 0;
7829 /* Expand comb and check vectors. */
7830 vect_el = undefined_vect_el_value;
7831 no_state_value = tab->automaton->achieved_states_num;
7832 while (additional_els_num > 0)
7834 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7835 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7836 additional_els_num--;
7838 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7839 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7840 if (VLA_HWINT_LENGTH (tab->comb_vect)
7841 < (size_t) (comb_vect_index + real_vect_length))
7842 abort ();
7843 /* Fill comb and check vectors. */
7844 for (vect_index = 0; vect_index < vect_length; vect_index++)
7845 if (vect [vect_index] != undefined_vect_el_value)
7847 if (comb_vect_start [comb_vect_index + vect_index]
7848 != undefined_vect_el_value)
7849 abort ();
7850 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7851 if (vect [vect_index] < 0)
7852 abort ();
7853 if (tab->max_comb_vect_el_value < vect [vect_index])
7854 tab->max_comb_vect_el_value = vect [vect_index];
7855 if (tab->min_comb_vect_el_value > vect [vect_index])
7856 tab->min_comb_vect_el_value = vect [vect_index];
7857 check_vect_start [comb_vect_index + vect_index] = vect_num;
7859 if (tab->max_base_vect_el_value < comb_vect_index)
7860 tab->max_base_vect_el_value = comb_vect_index;
7861 if (tab->min_base_vect_el_value > comb_vect_index)
7862 tab->min_base_vect_el_value = comb_vect_index;
7863 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7866 /* Return number of out arcs of STATE. */
7867 static int
7868 out_state_arcs_num (state)
7869 state_t state;
7871 int result;
7872 arc_t arc;
7874 result = 0;
7875 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7877 if (arc->insn == NULL)
7878 abort ();
7879 if (arc->insn->first_ainsn_with_given_equialence_num)
7880 result++;
7882 return result;
7885 /* Compare number of possible transitions from the states. */
7886 static int
7887 compare_transition_els_num (state_ptr_1, state_ptr_2)
7888 const void *state_ptr_1;
7889 const void *state_ptr_2;
7891 int transition_els_num_1;
7892 int transition_els_num_2;
7894 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7895 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7896 if (transition_els_num_1 < transition_els_num_2)
7897 return 1;
7898 else if (transition_els_num_1 == transition_els_num_2)
7899 return 0;
7900 else
7901 return -1;
7904 /* The function adds element EL_VALUE to vector VECT for a table state
7905 x AINSN. */
7906 static void
7907 add_vect_el (vect, ainsn, el_value)
7908 vla_hwint_t *vect;
7909 ainsn_t ainsn;
7910 int el_value;
7912 int equiv_class_num;
7913 int vect_index;
7915 if (ainsn == NULL)
7916 abort ();
7917 equiv_class_num = ainsn->insn_equiv_class_num;
7918 for (vect_index = VLA_HWINT_LENGTH (*vect);
7919 vect_index <= equiv_class_num;
7920 vect_index++)
7921 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7922 VLA_HWINT (*vect, equiv_class_num) = el_value;
7925 /* This is for forming vector of states of an automaton. */
7926 static vla_ptr_t output_states_vect;
7928 /* The function is called by function pass_states. The function adds
7929 STATE to `output_states_vect'. */
7930 static void
7931 add_states_vect_el (state)
7932 state_t state;
7934 VLA_PTR_ADD (output_states_vect, state);
7937 /* Form and output vectors (comb, check, base or full vector)
7938 representing transition table of AUTOMATON. */
7939 static void
7940 output_trans_table (automaton)
7941 automaton_t automaton;
7943 state_t *state_ptr;
7944 arc_t arc;
7945 vla_hwint_t transition_vect;
7947 undefined_vect_el_value = automaton->achieved_states_num;
7948 automaton->trans_table = create_state_ainsn_table (automaton);
7949 /* Create vect of pointers to states ordered by num of transitions
7950 from the state (state with the maximum num is the first). */
7951 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7952 pass_states (automaton, add_states_vect_el);
7953 qsort (VLA_PTR_BEGIN (output_states_vect),
7954 VLA_PTR_LENGTH (output_states_vect),
7955 sizeof (state_t), compare_transition_els_num);
7956 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7957 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7958 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7959 state_ptr++)
7961 VLA_HWINT_NULLIFY (transition_vect);
7962 for (arc = first_out_arc (*state_ptr);
7963 arc != NULL;
7964 arc = next_out_arc (arc))
7966 if (arc->insn == NULL)
7967 abort ();
7968 if (arc->insn->first_ainsn_with_given_equialence_num)
7969 add_vect_el (&transition_vect, arc->insn,
7970 arc->to_state->order_state_num);
7972 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7973 VLA_HWINT_BEGIN (transition_vect),
7974 VLA_HWINT_LENGTH (transition_vect));
7976 output_state_ainsn_table
7977 (automaton->trans_table, (char *) "state transitions",
7978 output_trans_full_vect_name, output_trans_comb_vect_name,
7979 output_trans_check_vect_name, output_trans_base_vect_name);
7980 VLA_PTR_DELETE (output_states_vect);
7981 VLA_HWINT_DELETE (transition_vect);
7984 /* Form and output vectors (comb, check, base or simple vect)
7985 representing alts number table of AUTOMATON. The table is state x
7986 ainsn -> number of possible alternative reservations by the
7987 ainsn. */
7988 static void
7989 output_state_alts_table (automaton)
7990 automaton_t automaton;
7992 state_t *state_ptr;
7993 arc_t arc;
7994 vla_hwint_t state_alts_vect;
7996 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7997 automaton->state_alts_table = create_state_ainsn_table (automaton);
7998 /* Create vect of pointers to states ordered by num of transitions
7999 from the state (state with the maximum num is the first). */
8000 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8001 pass_states (automaton, add_states_vect_el);
8002 qsort (VLA_PTR_BEGIN (output_states_vect),
8003 VLA_PTR_LENGTH (output_states_vect),
8004 sizeof (state_t), compare_transition_els_num);
8005 /* Create base, comb, and check vectors. */
8006 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
8007 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8008 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8009 state_ptr++)
8011 VLA_HWINT_NULLIFY (state_alts_vect);
8012 for (arc = first_out_arc (*state_ptr);
8013 arc != NULL;
8014 arc = next_out_arc (arc))
8016 if (arc->insn == NULL)
8017 abort ();
8018 if (arc->insn->first_ainsn_with_given_equialence_num)
8019 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
8021 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
8022 VLA_HWINT_BEGIN (state_alts_vect),
8023 VLA_HWINT_LENGTH (state_alts_vect));
8025 output_state_ainsn_table
8026 (automaton->state_alts_table, (char *) "state insn alternatives",
8027 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
8028 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
8029 VLA_PTR_DELETE (output_states_vect);
8030 VLA_HWINT_DELETE (state_alts_vect);
8033 /* The current number of passing states to find minimal issue delay
8034 value for an ainsn and state. */
8035 static int curr_state_pass_num;
8037 /* This recursive function passes states to find minimal issue delay
8038 value for AINSN. The state being visited is STATE. The function
8039 returns minimal issue delay value for AINSN in STATE or -1 if we
8040 enter into a loop. */
8041 static int
8042 min_issue_delay_pass_states (state, ainsn)
8043 state_t state;
8044 ainsn_t ainsn;
8046 arc_t arc;
8047 int min_insn_issue_delay, insn_issue_delay;
8049 if (state->state_pass_num == curr_state_pass_num
8050 || state->min_insn_issue_delay != -1)
8051 /* We've entered into a loop or already have the correct value for
8052 given state and ainsn. */
8053 return state->min_insn_issue_delay;
8054 state->state_pass_num = curr_state_pass_num;
8055 min_insn_issue_delay = -1;
8056 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8057 if (arc->insn == ainsn)
8059 min_insn_issue_delay = 0;
8060 break;
8062 else
8064 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
8065 if (insn_issue_delay != -1)
8067 if (arc->insn->insn_reserv_decl
8068 == DECL_INSN_RESERV (advance_cycle_insn_decl))
8069 insn_issue_delay++;
8070 if (min_insn_issue_delay == -1
8071 || min_insn_issue_delay > insn_issue_delay)
8073 min_insn_issue_delay = insn_issue_delay;
8074 if (insn_issue_delay == 0)
8075 break;
8079 return min_insn_issue_delay;
8082 /* The function searches minimal issue delay value for AINSN in STATE.
8083 The function can return negative value if we can not issue AINSN. We
8084 will report about it later. */
8085 static int
8086 min_issue_delay (state, ainsn)
8087 state_t state;
8088 ainsn_t ainsn;
8090 curr_state_pass_num++;
8091 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
8092 return state->min_insn_issue_delay;
8095 /* The function initiates code for finding minimal issue delay values.
8096 It should be called only once. */
8097 static void
8098 initiate_min_issue_delay_pass_states ()
8100 curr_state_pass_num = 0;
8103 /* Form and output vectors representing minimal issue delay table of
8104 AUTOMATON. The table is state x ainsn -> minimal issue delay of
8105 the ainsn. */
8106 static void
8107 output_min_issue_delay_table (automaton)
8108 automaton_t automaton;
8110 vla_hwint_t min_issue_delay_vect;
8111 vla_hwint_t compressed_min_issue_delay_vect;
8112 vect_el_t min_delay;
8113 ainsn_t ainsn;
8114 state_t *state_ptr;
8115 int i;
8117 /* Create vect of pointers to states ordered by num of transitions
8118 from the state (state with the maximum num is the first). */
8119 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8120 pass_states (automaton, add_states_vect_el);
8121 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
8122 VLA_HWINT_EXPAND (min_issue_delay_vect,
8123 VLA_HWINT_LENGTH (output_states_vect)
8124 * automaton->insn_equiv_classes_num);
8125 for (i = 0;
8126 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
8127 * automaton->insn_equiv_classes_num);
8128 i++)
8129 VLA_HWINT (min_issue_delay_vect, i) = 0;
8130 automaton->max_min_delay = 0;
8131 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
8132 if (ainsn->first_ainsn_with_given_equialence_num)
8134 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8135 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8136 state_ptr++)
8137 (*state_ptr)->min_insn_issue_delay = -1;
8138 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8139 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8140 state_ptr++)
8142 min_delay = min_issue_delay (*state_ptr, ainsn);
8143 if (automaton->max_min_delay < min_delay)
8144 automaton->max_min_delay = min_delay;
8145 VLA_HWINT (min_issue_delay_vect,
8146 (*state_ptr)->order_state_num
8147 * automaton->insn_equiv_classes_num
8148 + ainsn->insn_equiv_class_num) = min_delay;
8151 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
8152 fprintf (output_file, "static const ");
8153 output_range_type (output_file, 0, automaton->max_min_delay);
8154 fprintf (output_file, " ");
8155 output_min_issue_delay_vect_name (output_file, automaton);
8156 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
8157 /* Compress the vector */
8158 if (automaton->max_min_delay < 2)
8159 automaton->min_issue_delay_table_compression_factor = 8;
8160 else if (automaton->max_min_delay < 4)
8161 automaton->min_issue_delay_table_compression_factor = 4;
8162 else if (automaton->max_min_delay < 16)
8163 automaton->min_issue_delay_table_compression_factor = 2;
8164 else
8165 automaton->min_issue_delay_table_compression_factor = 1;
8166 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
8167 "compressed min issue delay vector");
8168 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
8169 (VLA_HWINT_LENGTH (min_issue_delay_vect)
8170 + automaton->min_issue_delay_table_compression_factor
8171 - 1)
8172 / automaton->min_issue_delay_table_compression_factor);
8173 for (i = 0;
8174 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
8175 i++)
8176 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
8177 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
8178 VLA_HWINT (compressed_min_issue_delay_vect,
8179 i / automaton->min_issue_delay_table_compression_factor)
8180 |= (VLA_HWINT (min_issue_delay_vect, i)
8181 << (8 - (i % automaton->min_issue_delay_table_compression_factor
8182 + 1)
8183 * (8 / automaton->min_issue_delay_table_compression_factor)));
8184 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
8185 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
8186 fprintf (output_file, "};\n\n");
8187 VLA_PTR_DELETE (output_states_vect);
8188 VLA_HWINT_DELETE (min_issue_delay_vect);
8189 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
8192 #ifndef NDEBUG
8193 /* Number of states which contains transition only by advancing cpu
8194 cycle. */
8195 static int locked_states_num;
8196 #endif
8198 /* Form and output vector representing the locked states of
8199 AUTOMATON. */
8200 static void
8201 output_dead_lock_vect (automaton)
8202 automaton_t automaton;
8204 state_t *state_ptr;
8205 arc_t arc;
8206 vla_hwint_t dead_lock_vect;
8208 /* Create vect of pointers to states ordered by num of
8209 transitions from the state (state with the maximum num is the
8210 first). */
8211 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8212 pass_states (automaton, add_states_vect_el);
8213 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
8214 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
8215 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8216 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8217 state_ptr++)
8219 arc = first_out_arc (*state_ptr);
8220 if (arc == NULL)
8221 abort ();
8222 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
8223 = (next_out_arc (arc) == NULL
8224 && (arc->insn->insn_reserv_decl
8225 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
8226 #ifndef NDEBUG
8227 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
8228 locked_states_num++;
8229 #endif
8231 fprintf (output_file, "/* Vector for locked state flags. */\n");
8232 fprintf (output_file, "static const ");
8233 output_range_type (output_file, 0, 1);
8234 fprintf (output_file, " ");
8235 output_dead_lock_vect_name (output_file, automaton);
8236 fprintf (output_file, "[] = {\n");
8237 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
8238 VLA_HWINT_LENGTH (dead_lock_vect));
8239 fprintf (output_file, "};\n\n");
8240 VLA_HWINT_DELETE (dead_lock_vect);
8241 VLA_PTR_DELETE (output_states_vect);
8244 /* Form and output vector representing reserved units of the states of
8245 AUTOMATON. */
8246 static void
8247 output_reserved_units_table (automaton)
8248 automaton_t automaton;
8250 state_t *curr_state_ptr;
8251 vla_hwint_t reserved_units_table;
8252 size_t state_byte_size;
8253 int i;
8255 /* Create vect of pointers to states. */
8256 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8257 pass_states (automaton, add_states_vect_el);
8258 /* Create vector. */
8259 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
8260 state_byte_size = (description->query_units_num + 7) / 8;
8261 VLA_HWINT_EXPAND (reserved_units_table,
8262 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8263 for (i = 0;
8264 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8265 i++)
8266 VLA_HWINT (reserved_units_table, i) = 0;
8267 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
8268 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8269 curr_state_ptr++)
8271 for (i = 0; i < description->units_num; i++)
8272 if (units_array [i]->query_p
8273 && first_cycle_unit_presence (*curr_state_ptr, i))
8274 VLA_HWINT (reserved_units_table,
8275 (*curr_state_ptr)->order_state_num * state_byte_size
8276 + units_array [i]->query_num / 8)
8277 += (1 << (units_array [i]->query_num % 8));
8279 fprintf (output_file, "/* Vector for reserved units of states. */\n");
8280 fprintf (output_file, "static const ");
8281 output_range_type (output_file, 0, 255);
8282 fprintf (output_file, " ");
8283 output_reserved_units_table_name (output_file, automaton);
8284 fprintf (output_file, "[] = {\n");
8285 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
8286 VLA_HWINT_LENGTH (reserved_units_table));
8287 fprintf (output_file, "};\n\n");
8288 VLA_HWINT_DELETE (reserved_units_table);
8289 VLA_PTR_DELETE (output_states_vect);
8292 /* The function outputs all tables representing DFA(s) used for fast
8293 pipeline hazards recognition. */
8294 static void
8295 output_tables ()
8297 automaton_t automaton;
8299 #ifndef NDEBUG
8300 locked_states_num = 0;
8301 #endif
8302 initiate_min_issue_delay_pass_states ();
8303 for (automaton = description->first_automaton;
8304 automaton != NULL;
8305 automaton = automaton->next_automaton)
8307 output_translate_vect (automaton);
8308 output_trans_table (automaton);
8309 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
8310 output_state_alts_table (automaton);
8311 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8312 AUTOMATON_STATE_ALTS_MACRO_NAME);
8313 output_min_issue_delay_table (automaton);
8314 output_dead_lock_vect (automaton);
8315 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
8316 output_reserved_units_table (automaton);
8317 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8318 CPU_UNITS_QUERY_MACRO_NAME);
8320 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
8321 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8324 /* The function outputs definition and value of PHR interface variable
8325 `max_insn_queue_index'. Its value is not less than maximal queue
8326 length needed for the insn scheduler. */
8327 static void
8328 output_max_insn_queue_index_def ()
8330 int i, max, latency;
8331 decl_t decl;
8333 max = description->max_insn_reserv_cycles;
8334 for (i = 0; i < description->decls_num; i++)
8336 decl = description->decls [i];
8337 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8339 latency = DECL_INSN_RESERV (decl)->default_latency;
8340 if (latency > max)
8341 max = latency;
8343 else if (decl->mode == dm_bypass)
8345 latency = DECL_BYPASS (decl)->latency;
8346 if (latency > max)
8347 max = latency;
8350 for (i = 0; (1 << i) <= max; i++)
8352 if (i < 0)
8353 abort ();
8354 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
8358 /* The function outputs switch cases for insn reservations using
8359 function *output_automata_list_code. */
8360 static void
8361 output_insn_code_cases (output_automata_list_code)
8362 void (*output_automata_list_code) PARAMS ((automata_list_el_t));
8364 decl_t decl, decl2;
8365 int i, j;
8367 for (i = 0; i < description->decls_num; i++)
8369 decl = description->decls [i];
8370 if (decl->mode == dm_insn_reserv)
8371 DECL_INSN_RESERV (decl)->processed_p = FALSE;
8373 for (i = 0; i < description->decls_num; i++)
8375 decl = description->decls [i];
8376 if (decl->mode == dm_insn_reserv
8377 && !DECL_INSN_RESERV (decl)->processed_p)
8379 for (j = i; j < description->decls_num; j++)
8381 decl2 = description->decls [j];
8382 if (decl2->mode == dm_insn_reserv
8383 && (DECL_INSN_RESERV (decl2)->important_automata_list
8384 == DECL_INSN_RESERV (decl)->important_automata_list))
8386 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8387 fprintf (output_file, " case %d: /* %s */\n",
8388 DECL_INSN_RESERV (decl2)->insn_num,
8389 DECL_INSN_RESERV (decl2)->name);
8392 (*output_automata_list_code)
8393 (DECL_INSN_RESERV (decl)->important_automata_list);
8399 /* The function outputs a code for evaluation of a minimal delay of
8400 issue of insns which have reservations in given AUTOMATA_LIST. */
8401 static void
8402 output_automata_list_min_issue_delay_code (automata_list)
8403 automata_list_el_t automata_list;
8405 automata_list_el_t el;
8406 automaton_t automaton;
8408 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8410 automaton = el->automaton;
8411 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8412 output_min_issue_delay_vect_name (output_file, automaton);
8413 fprintf (output_file,
8414 (automaton->min_issue_delay_table_compression_factor != 1
8415 ? " [(" : " ["));
8416 output_translate_vect_name (output_file, automaton);
8417 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8418 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8419 output_chip_member_name (output_file, automaton);
8420 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8421 if (automaton->min_issue_delay_table_compression_factor == 1)
8422 fprintf (output_file, "];\n");
8423 else
8425 fprintf (output_file, ") / %d];\n",
8426 automaton->min_issue_delay_table_compression_factor);
8427 fprintf (output_file, " %s = (%s >> (8 - (",
8428 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8429 output_translate_vect_name (output_file, automaton);
8430 fprintf
8431 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8432 INTERNAL_INSN_CODE_NAME,
8433 automaton->min_issue_delay_table_compression_factor,
8434 8 / automaton->min_issue_delay_table_compression_factor,
8435 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8436 - 1);
8438 if (el == automata_list)
8439 fprintf (output_file, " %s = %s;\n",
8440 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8441 else
8443 fprintf (output_file, " if (%s > %s)\n",
8444 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8445 fprintf (output_file, " %s = %s;\n",
8446 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8449 fprintf (output_file, " break;\n\n");
8452 /* Output function `internal_min_issue_delay'. */
8453 static void
8454 output_internal_min_issue_delay_func ()
8456 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8457 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
8458 fprintf (output_file,
8459 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8460 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8461 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8462 CHIP_PARAMETER_NAME);
8463 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8464 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8465 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8466 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8467 fprintf (output_file,
8468 "\n default:\n %s = -1;\n break;\n }\n",
8469 RESULT_VARIABLE_NAME);
8470 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8471 fprintf (output_file, "}\n\n");
8474 /* The function outputs a code changing state after issue of insns
8475 which have reservations in given AUTOMATA_LIST. */
8476 static void
8477 output_automata_list_transition_code (automata_list)
8478 automata_list_el_t automata_list;
8480 automata_list_el_t el, next_el;
8482 fprintf (output_file, " {\n");
8483 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8484 for (el = automata_list;; el = next_el)
8486 next_el = el->next_automata_list_el;
8487 if (next_el == NULL)
8488 break;
8489 fprintf (output_file, " ");
8490 output_state_member_type (output_file, el->automaton);
8491 fprintf (output_file, " ");
8492 output_temp_chip_member_name (output_file, el->automaton);
8493 fprintf (output_file, ";\n");
8495 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8496 if (comb_vect_p (el->automaton->trans_table))
8498 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8499 output_trans_base_vect_name (output_file, el->automaton);
8500 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8501 output_chip_member_name (output_file, el->automaton);
8502 fprintf (output_file, "] + ");
8503 output_translate_vect_name (output_file, el->automaton);
8504 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8505 fprintf (output_file, " if (");
8506 output_trans_check_vect_name (output_file, el->automaton);
8507 fprintf (output_file, " [%s] != %s->",
8508 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8509 output_chip_member_name (output_file, el->automaton);
8510 fprintf (output_file, ")\n");
8511 fprintf (output_file, " return %s (%s, %s);\n",
8512 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8513 CHIP_PARAMETER_NAME);
8514 fprintf (output_file, " else\n");
8515 fprintf (output_file, " ");
8516 if (el->next_automata_list_el != NULL)
8517 output_temp_chip_member_name (output_file, el->automaton);
8518 else
8520 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8521 output_chip_member_name (output_file, el->automaton);
8523 fprintf (output_file, " = ");
8524 output_trans_comb_vect_name (output_file, el->automaton);
8525 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8527 else
8529 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8530 output_trans_full_vect_name (output_file, el->automaton);
8531 fprintf (output_file, " [");
8532 output_translate_vect_name (output_file, el->automaton);
8533 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8534 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8535 output_chip_member_name (output_file, el->automaton);
8536 fprintf (output_file, " * %d];\n",
8537 el->automaton->insn_equiv_classes_num);
8538 fprintf (output_file, " if (%s >= %d)\n",
8539 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8540 fprintf (output_file, " return %s (%s, %s);\n",
8541 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8542 CHIP_PARAMETER_NAME);
8543 fprintf (output_file, " else\n ");
8544 if (el->next_automata_list_el != NULL)
8545 output_temp_chip_member_name (output_file, el->automaton);
8546 else
8548 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8549 output_chip_member_name (output_file, el->automaton);
8551 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8553 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8554 for (el = automata_list;; el = next_el)
8556 next_el = el->next_automata_list_el;
8557 if (next_el == NULL)
8558 break;
8559 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8560 output_chip_member_name (output_file, el->automaton);
8561 fprintf (output_file, " = ");
8562 output_temp_chip_member_name (output_file, el->automaton);
8563 fprintf (output_file, ";\n");
8565 fprintf (output_file, " return -1;\n");
8566 fprintf (output_file, " }\n");
8569 /* Output function `internal_state_transition'. */
8570 static void
8571 output_internal_trans_func ()
8573 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8574 INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
8575 fprintf (output_file,
8576 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8577 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8578 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
8579 CHIP_NAME, CHIP_PARAMETER_NAME);
8580 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8581 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8582 output_insn_code_cases (output_automata_list_transition_code);
8583 fprintf (output_file, "\n default:\n return -1;\n }\n");
8584 fprintf (output_file, "}\n\n");
8587 /* Output code
8589 if (insn != 0)
8591 insn_code = dfa_insn_code (insn);
8592 if (insn_code > DFA__ADVANCE_CYCLE)
8593 return code;
8595 else
8596 insn_code = DFA__ADVANCE_CYCLE;
8598 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8599 code denotes CODE. */
8600 static void
8601 output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
8602 const char *insn_name;
8603 const char *insn_code_name;
8604 int code;
8606 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8607 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8608 DFA_INSN_CODE_FUNC_NAME, insn_name);
8609 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8610 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8611 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8612 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8616 /* This function outputs `dfa_insn_code' and its helper function
8617 `dfa_insn_code_enlarge'. */
8618 static void
8619 output_dfa_insn_code_func ()
8621 /* Emacs c-mode gets really confused if there's a { or } in column 0
8622 inside a string, so don't do that. */
8623 fprintf (output_file, "\
8624 static void dfa_insn_code_enlarge PARAMS ((int));\n\
8625 static void\n\
8626 dfa_insn_code_enlarge (uid)\n\
8627 int uid;\n{\n\
8628 int i = %s;\n\
8629 %s = 2 * uid;\n\
8630 %s = xrealloc (%s,\n\
8631 %s * sizeof(int));\n\
8632 for (; i < %s; i++)\n\
8633 %s[i] = -1;\n}\n\n",
8634 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8635 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8636 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8637 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8638 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8639 DFA_INSN_CODES_VARIABLE_NAME);
8640 fprintf (output_file, "\
8641 static inline int %s PARAMS ((rtx));\n\
8642 static inline int\n%s (%s)\n\
8643 rtx %s;\n{\n\
8644 int uid = INSN_UID (%s);\n\
8645 int %s;\n\n",
8646 DFA_INSN_CODE_FUNC_NAME, DFA_INSN_CODE_FUNC_NAME,
8647 INSN_PARAMETER_NAME, INSN_PARAMETER_NAME,
8648 INSN_PARAMETER_NAME,
8649 INTERNAL_INSN_CODE_NAME);
8651 fprintf (output_file,
8652 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8653 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8654 fprintf (output_file, " %s = %s[uid];\n",
8655 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8656 fprintf (output_file, "\
8657 if (%s < 0)\n\
8658 {\n\
8659 %s = %s (%s);\n\
8660 %s[uid] = %s;\n\
8661 }\n",
8662 INTERNAL_INSN_CODE_NAME,
8663 INTERNAL_INSN_CODE_NAME,
8664 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8665 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8666 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8669 /* The function outputs PHR interface function `state_transition'. */
8670 static void
8671 output_trans_func ()
8673 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8674 TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8675 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8676 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8677 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8678 INTERNAL_INSN_CODE_NAME, -1);
8679 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8680 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8683 /* The function outputs a code for evaluation of alternative states
8684 number for insns which have reservations in given AUTOMATA_LIST. */
8685 static void
8686 output_automata_list_state_alts_code (automata_list)
8687 automata_list_el_t automata_list;
8689 automata_list_el_t el;
8690 automaton_t automaton;
8692 fprintf (output_file, " {\n");
8693 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8694 if (comb_vect_p (el->automaton->state_alts_table))
8696 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8697 break;
8699 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8701 automaton = el->automaton;
8702 if (comb_vect_p (automaton->state_alts_table))
8704 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8705 output_state_alts_base_vect_name (output_file, automaton);
8706 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8707 output_chip_member_name (output_file, automaton);
8708 fprintf (output_file, "] + ");
8709 output_translate_vect_name (output_file, automaton);
8710 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8711 fprintf (output_file, " if (");
8712 output_state_alts_check_vect_name (output_file, automaton);
8713 fprintf (output_file, " [%s] != %s->",
8714 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8715 output_chip_member_name (output_file, automaton);
8716 fprintf (output_file, ")\n");
8717 fprintf (output_file, " return 0;\n");
8718 fprintf (output_file, " else\n");
8719 fprintf (output_file,
8720 (el == automata_list
8721 ? " %s = " : " %s += "),
8722 RESULT_VARIABLE_NAME);
8723 output_state_alts_comb_vect_name (output_file, automaton);
8724 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8726 else
8728 fprintf (output_file,
8729 (el == automata_list
8730 ? "\n %s = " : " %s += "),
8731 RESULT_VARIABLE_NAME);
8732 output_state_alts_full_vect_name (output_file, automaton);
8733 fprintf (output_file, " [");
8734 output_translate_vect_name (output_file, automaton);
8735 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8736 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8737 output_chip_member_name (output_file, automaton);
8738 fprintf (output_file, " * %d];\n",
8739 automaton->insn_equiv_classes_num);
8742 fprintf (output_file, " break;\n }\n\n");
8745 /* Output function `internal_state_alts'. */
8746 static void
8747 output_internal_state_alts_func ()
8749 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8750 INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8751 fprintf (output_file,
8752 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8753 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8754 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8755 CHIP_PARAMETER_NAME);
8756 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8757 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8758 output_insn_code_cases (output_automata_list_state_alts_code);
8759 fprintf (output_file,
8760 "\n default:\n %s = 0;\n break;\n }\n",
8761 RESULT_VARIABLE_NAME);
8762 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8763 fprintf (output_file, "}\n\n");
8766 /* The function outputs PHR interface function `state_alts'. */
8767 static void
8768 output_state_alts_func ()
8770 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8771 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8772 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8773 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8774 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8775 INTERNAL_INSN_CODE_NAME, 0);
8776 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8777 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8780 /* Output function `min_issue_delay'. */
8781 static void
8782 output_min_issue_delay_func ()
8784 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8785 MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8786 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8787 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8788 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8789 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8790 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8791 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8792 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8793 fprintf (output_file, " }\n else\n %s = %s;\n",
8794 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8795 fprintf (output_file, "\n return %s (%s, %s);\n",
8796 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8797 STATE_NAME);
8798 fprintf (output_file, "}\n\n");
8801 /* Output function `internal_dead_lock'. */
8802 static void
8803 output_internal_dead_lock_func ()
8805 automaton_t automaton;
8807 fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8808 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8809 fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8810 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8811 CHIP_PARAMETER_NAME);
8812 fprintf (output_file, "{\n");
8813 for (automaton = description->first_automaton;
8814 automaton != NULL;
8815 automaton = automaton->next_automaton)
8817 fprintf (output_file, " if (");
8818 output_dead_lock_vect_name (output_file, automaton);
8819 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8820 output_chip_member_name (output_file, automaton);
8821 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8823 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8826 /* The function outputs PHR interface function `state_dead_lock_p'. */
8827 static void
8828 output_dead_lock_func ()
8830 fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8831 DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8832 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8833 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8836 /* Output function `internal_reset'. */
8837 static void
8838 output_internal_reset_func ()
8840 fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8841 INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8842 fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8843 INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8844 CHIP_NAME, CHIP_PARAMETER_NAME);
8845 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8846 CHIP_PARAMETER_NAME, CHIP_NAME);
8849 /* The function outputs PHR interface function `state_size'. */
8850 static void
8851 output_size_func ()
8853 fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8854 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8857 /* The function outputs PHR interface function `state_reset'. */
8858 static void
8859 output_reset_func ()
8861 fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8862 RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8863 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8864 STATE_NAME);
8867 /* Output function `min_insn_conflict_delay'. */
8868 static void
8869 output_min_insn_conflict_delay_func ()
8871 fprintf (output_file,
8872 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8873 MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8874 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8875 STATE_TYPE_NAME, STATE_NAME,
8876 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8877 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8878 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8879 INTERNAL_INSN2_CODE_NAME);
8880 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8881 INTERNAL_INSN_CODE_NAME, 0);
8882 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8883 INTERNAL_INSN2_CODE_NAME, 0);
8884 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8885 CHIP_NAME, STATE_NAME, CHIP_NAME);
8886 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8887 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8888 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8889 fprintf (output_file, " return %s (%s, &%s);\n",
8890 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8891 CHIP_NAME);
8892 fprintf (output_file, "}\n\n");
8895 /* Output function `internal_insn_latency'. */
8896 static void
8897 output_internal_insn_latency_func ()
8899 decl_t decl;
8900 struct bypass_decl *bypass;
8901 int i, j, col;
8902 const char *tabletype = "unsigned char";
8904 /* Find the smallest integer type that can hold all the default
8905 latency values. */
8906 for (i = 0; i < description->decls_num; i++)
8907 if (description->decls[i]->mode == dm_insn_reserv)
8909 decl = description->decls[i];
8910 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8911 && tabletype[0] != 'i') /* don't shrink it */
8912 tabletype = "unsigned short";
8913 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8914 tabletype = "int";
8917 fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8918 INTERNAL_INSN_LATENCY_FUNC_NAME);
8919 fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8920 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8921 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8922 INSN2_PARAMETER_NAME);
8923 fprintf (output_file,
8924 "\n\tint %s ATTRIBUTE_UNUSED;\n\tint %s ATTRIBUTE_UNUSED;\n",
8925 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8926 fprintf (output_file,
8927 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n{\n",
8928 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8930 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8932 fputs (" return 0;\n}\n\n", output_file);
8933 return;
8936 fprintf (output_file, " static const %s default_latencies[] =\n {",
8937 tabletype);
8939 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8940 if (description->decls[i]->mode == dm_insn_reserv
8941 && description->decls[i] != advance_cycle_insn_decl)
8943 if ((col = (col+1) % 8) == 0)
8944 fputs ("\n ", output_file);
8945 decl = description->decls[i];
8946 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
8947 abort ();
8948 fprintf (output_file, "% 4d,",
8949 DECL_INSN_RESERV (decl)->default_latency);
8951 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8952 abort ();
8953 fputs ("\n };\n", output_file);
8955 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8956 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8957 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8959 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8960 for (i = 0; i < description->decls_num; i++)
8961 if (description->decls[i]->mode == dm_insn_reserv
8962 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8964 decl = description->decls [i];
8965 fprintf (output_file,
8966 " case %d:\n switch (%s)\n {\n",
8967 DECL_INSN_RESERV (decl)->insn_num,
8968 INTERNAL_INSN2_CODE_NAME);
8969 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8970 bypass != NULL;
8971 bypass = bypass->next)
8973 if (bypass->in_insn_reserv->insn_num
8974 == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8975 abort ();
8976 fprintf (output_file, " case %d:\n",
8977 bypass->in_insn_reserv->insn_num);
8978 if (bypass->bypass_guard_name == NULL)
8979 fprintf (output_file, " return %d;\n",
8980 bypass->latency);
8981 else
8983 fprintf (output_file,
8984 " if (%s (%s, %s))\n",
8985 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8986 INSN2_PARAMETER_NAME);
8987 fprintf (output_file,
8988 " return %d;\n break;\n",
8989 bypass->latency);
8992 fputs (" }\n break;\n", output_file);
8995 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8996 INTERNAL_INSN_CODE_NAME);
8999 /* The function outputs PHR interface function `insn_latency'. */
9000 static void
9001 output_insn_latency_func ()
9003 fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
9004 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
9005 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
9006 fprintf (output_file, "{\n int %s, %s;\n",
9007 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
9008 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
9009 INTERNAL_INSN_CODE_NAME, 0);
9010 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
9011 INTERNAL_INSN2_CODE_NAME, 0);
9012 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
9013 INTERNAL_INSN_LATENCY_FUNC_NAME,
9014 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
9015 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
9018 /* The function outputs PHR interface function `print_reservation'. */
9019 static void
9020 output_print_reservation_func ()
9022 decl_t decl;
9023 int i, j;
9025 fprintf (output_file,
9026 "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s ATTRIBUTE_UNUSED;\n{\n",
9027 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
9028 INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
9029 INSN_PARAMETER_NAME);
9031 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
9033 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
9034 NOTHING_NAME, FILE_PARAMETER_NAME);
9035 return;
9039 fputs (" static const char *const reservation_names[] =\n {",
9040 output_file);
9042 for (i = 0, j = 0; i < description->decls_num; i++)
9044 decl = description->decls [i];
9045 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9047 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
9048 abort ();
9049 fprintf (output_file, "\n \"%s\",",
9050 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
9051 finish_regexp_representation ();
9054 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
9055 abort ();
9057 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
9058 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
9060 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
9061 INSN_PARAMETER_NAME,
9062 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
9063 fprintf (output_file, " else\n\
9064 {\n\
9065 %s = %s (%s);\n\
9066 if (%s > %s)\n\
9067 %s = %s;\n\
9068 }\n",
9069 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
9070 INSN_PARAMETER_NAME,
9071 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
9072 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
9074 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
9075 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
9078 /* The following function is used to sort unit declaration by their
9079 names. */
9080 static int
9081 units_cmp (unit1, unit2)
9082 const void *unit1, *unit2;
9084 const unit_decl_t u1 = *(unit_decl_t *) unit1;
9085 const unit_decl_t u2 = *(unit_decl_t *) unit2;
9087 return strcmp (u1->name, u2->name);
9090 /* The following macro value is name of struct containing unit name
9091 and unit code. */
9092 #define NAME_CODE_STRUCT_NAME "name_code"
9094 /* The following macro value is name of table of struct name_code. */
9095 #define NAME_CODE_TABLE_NAME "name_code_table"
9097 /* The following macro values are member names for struct name_code. */
9098 #define NAME_MEMBER_NAME "name"
9099 #define CODE_MEMBER_NAME "code"
9101 /* The following macro values are local variable names for function
9102 `get_cpu_unit_code'. */
9103 #define CMP_VARIABLE_NAME "cmp"
9104 #define LOW_VARIABLE_NAME "l"
9105 #define MIDDLE_VARIABLE_NAME "m"
9106 #define HIGH_VARIABLE_NAME "h"
9108 /* The following function outputs function to obtain internal cpu unit
9109 code by the cpu unit name. */
9110 static void
9111 output_get_cpu_unit_code_func ()
9113 int i;
9114 unit_decl_t *units;
9116 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
9117 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
9118 CPU_UNIT_NAME_PARAMETER_NAME);
9119 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
9120 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
9121 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
9122 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
9123 fprintf (output_file, " static struct %s %s [] =\n {\n",
9124 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
9125 units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
9126 * description->units_num);
9127 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
9128 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
9129 for (i = 0; i < description->units_num; i++)
9130 if (units [i]->query_p)
9131 fprintf (output_file, " {\"%s\", %d},\n",
9132 units[i]->name, units[i]->query_num);
9133 fprintf (output_file, " };\n\n");
9134 fprintf (output_file, " /* The following is binary search: */\n");
9135 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
9136 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
9137 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
9138 fprintf (output_file, " while (%s <= %s)\n {\n",
9139 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
9140 fprintf (output_file, " %s = (%s + %s) / 2;\n",
9141 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
9142 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
9143 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
9144 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
9145 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
9146 fprintf (output_file, " %s = %s - 1;\n",
9147 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
9148 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
9149 fprintf (output_file, " %s = %s + 1;\n",
9150 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
9151 fprintf (output_file, " else\n");
9152 fprintf (output_file, " return %s [%s].%s;\n }\n",
9153 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
9154 fprintf (output_file, " return -1;\n}\n\n");
9155 free (units);
9158 /* The following function outputs function to check reservation of cpu
9159 unit (its internal code will be passed as the function argument) in
9160 given cpu state. */
9161 static void
9162 output_cpu_unit_reservation_p ()
9164 automaton_t automaton;
9166 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
9167 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
9168 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
9169 CPU_CODE_PARAMETER_NAME);
9170 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
9171 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
9172 description->query_units_num);
9173 for (automaton = description->first_automaton;
9174 automaton != NULL;
9175 automaton = automaton->next_automaton)
9177 fprintf (output_file, " if ((");
9178 output_reserved_units_table_name (output_file, automaton);
9179 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
9180 output_chip_member_name (output_file, automaton);
9181 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
9182 (description->query_units_num + 7) / 8,
9183 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
9184 fprintf (output_file, " return 1;\n");
9186 fprintf (output_file, " return 0;\n}\n\n");
9189 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
9190 static void
9191 output_dfa_clean_insn_cache_func ()
9193 fprintf (output_file,
9194 "void\n%s ()\n{\n int %s;\n\n",
9195 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
9196 fprintf (output_file,
9197 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
9198 I_VARIABLE_NAME, I_VARIABLE_NAME,
9199 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
9200 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
9203 /* The function outputs PHR interface function `dfa_start'. */
9204 static void
9205 output_dfa_start_func ()
9207 fprintf (output_file,
9208 "void\n%s ()\n{\n %s = get_max_uid ();\n",
9209 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9210 fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
9211 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9212 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
9215 /* The function outputs PHR interface function `dfa_finish'. */
9216 static void
9217 output_dfa_finish_func ()
9219 fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
9220 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
9225 /* The page contains code for output description file (readable
9226 representation of original description and generated DFA(s). */
9228 /* The function outputs string representation of IR reservation. */
9229 static void
9230 output_regexp (regexp)
9231 regexp_t regexp;
9233 fprintf (output_description_file, "%s", regexp_representation (regexp));
9234 finish_regexp_representation ();
9237 /* Output names of units in LIST separated by comma. */
9238 static void
9239 output_unit_set_el_list (list)
9240 unit_set_el_t list;
9242 unit_set_el_t el;
9244 for (el = list; el != NULL; el = el->next_unit_set_el)
9246 if (el != list)
9247 fprintf (output_description_file, ", ");
9248 fprintf (output_description_file, "%s", el->unit_decl->name);
9252 /* Output patterns in LIST separated by comma. */
9253 static void
9254 output_pattern_set_el_list (list)
9255 pattern_set_el_t list;
9257 pattern_set_el_t el;
9258 int i;
9260 for (el = list; el != NULL; el = el->next_pattern_set_el)
9262 if (el != list)
9263 fprintf (output_description_file, ", ");
9264 for (i = 0; i < el->units_num; i++)
9265 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
9266 el->unit_decls [i]->name);
9270 /* The function outputs string representation of IR define_reservation
9271 and define_insn_reservation. */
9272 static void
9273 output_description ()
9275 decl_t decl;
9276 int i;
9278 for (i = 0; i < description->decls_num; i++)
9280 decl = description->decls [i];
9281 if (decl->mode == dm_unit)
9283 if (DECL_UNIT (decl)->excl_list != NULL)
9285 fprintf (output_description_file, "unit %s exlusion_set: ",
9286 DECL_UNIT (decl)->name);
9287 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
9288 fprintf (output_description_file, "\n");
9290 if (DECL_UNIT (decl)->presence_list != NULL)
9292 fprintf (output_description_file, "unit %s presence_set: ",
9293 DECL_UNIT (decl)->name);
9294 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
9295 fprintf (output_description_file, "\n");
9297 if (DECL_UNIT (decl)->final_presence_list != NULL)
9299 fprintf (output_description_file, "unit %s final_presence_set: ",
9300 DECL_UNIT (decl)->name);
9301 output_pattern_set_el_list
9302 (DECL_UNIT (decl)->final_presence_list);
9303 fprintf (output_description_file, "\n");
9305 if (DECL_UNIT (decl)->absence_list != NULL)
9307 fprintf (output_description_file, "unit %s absence_set: ",
9308 DECL_UNIT (decl)->name);
9309 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
9310 fprintf (output_description_file, "\n");
9312 if (DECL_UNIT (decl)->final_absence_list != NULL)
9314 fprintf (output_description_file, "unit %s final_absence_set: ",
9315 DECL_UNIT (decl)->name);
9316 output_pattern_set_el_list
9317 (DECL_UNIT (decl)->final_absence_list);
9318 fprintf (output_description_file, "\n");
9322 fprintf (output_description_file, "\n");
9323 for (i = 0; i < description->decls_num; i++)
9325 decl = description->decls [i];
9326 if (decl->mode == dm_reserv)
9328 fprintf (output_description_file, "reservation ");
9329 fprintf (output_description_file, DECL_RESERV (decl)->name);
9330 fprintf (output_description_file, ": ");
9331 output_regexp (DECL_RESERV (decl)->regexp);
9332 fprintf (output_description_file, "\n");
9334 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9336 fprintf (output_description_file, "insn reservation %s ",
9337 DECL_INSN_RESERV (decl)->name);
9338 print_rtl (output_description_file,
9339 DECL_INSN_RESERV (decl)->condexp);
9340 fprintf (output_description_file, ": ");
9341 output_regexp (DECL_INSN_RESERV (decl)->regexp);
9342 fprintf (output_description_file, "\n");
9344 else if (decl->mode == dm_bypass)
9345 fprintf (output_description_file, "bypass %d %s %s\n",
9346 DECL_BYPASS (decl)->latency,
9347 DECL_BYPASS (decl)->out_insn_name,
9348 DECL_BYPASS (decl)->in_insn_name);
9350 fprintf (output_description_file, "\n\f\n");
9353 /* The function outputs name of AUTOMATON. */
9354 static void
9355 output_automaton_name (f, automaton)
9356 FILE *f;
9357 automaton_t automaton;
9359 if (automaton->corresponding_automaton_decl == NULL)
9360 fprintf (f, "#%d", automaton->automaton_order_num);
9361 else
9362 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
9365 /* Maximal length of line for pretty printing into description
9366 file. */
9367 #define MAX_LINE_LENGTH 70
9369 /* The function outputs units name belonging to AUTOMATON. */
9370 static void
9371 output_automaton_units (automaton)
9372 automaton_t automaton;
9374 decl_t decl;
9375 char *name;
9376 int curr_line_length;
9377 int there_is_an_automaton_unit;
9378 int i;
9380 fprintf (output_description_file, "\n Coresponding units:\n");
9381 fprintf (output_description_file, " ");
9382 curr_line_length = 4;
9383 there_is_an_automaton_unit = 0;
9384 for (i = 0; i < description->decls_num; i++)
9386 decl = description->decls [i];
9387 if (decl->mode == dm_unit
9388 && (DECL_UNIT (decl)->corresponding_automaton_num
9389 == automaton->automaton_order_num))
9391 there_is_an_automaton_unit = 1;
9392 name = DECL_UNIT (decl)->name;
9393 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
9395 curr_line_length = strlen (name) + 4;
9396 fprintf (output_description_file, "\n ");
9398 else
9400 curr_line_length += strlen (name) + 1;
9401 fprintf (output_description_file, " ");
9403 fprintf (output_description_file, name);
9406 if (!there_is_an_automaton_unit)
9407 fprintf (output_description_file, "<None>");
9408 fprintf (output_description_file, "\n\n");
9411 /* The following variable is used for forming array of all possible cpu unit
9412 reservations described by the current DFA state. */
9413 static vla_ptr_t state_reservs;
9415 /* The function forms `state_reservs' for STATE. */
9416 static void
9417 add_state_reservs (state)
9418 state_t state;
9420 alt_state_t curr_alt_state;
9421 reserv_sets_t reservs;
9423 if (state->component_states != NULL)
9424 for (curr_alt_state = state->component_states;
9425 curr_alt_state != NULL;
9426 curr_alt_state = curr_alt_state->next_sorted_alt_state)
9427 add_state_reservs (curr_alt_state->state);
9428 else
9430 reservs = state->reservs;
9431 VLA_PTR_ADD (state_reservs, reservs);
9435 /* The function outputs readable representation of all out arcs of
9436 STATE. */
9437 static void
9438 output_state_arcs (state)
9439 state_t state;
9441 arc_t arc;
9442 ainsn_t ainsn;
9443 char *insn_name;
9444 int curr_line_length;
9446 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
9448 ainsn = arc->insn;
9449 if (!ainsn->first_insn_with_same_reservs)
9450 abort ();
9451 fprintf (output_description_file, " ");
9452 curr_line_length = 7;
9453 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
9456 insn_name = ainsn->insn_reserv_decl->name;
9457 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
9459 if (ainsn != arc->insn)
9461 fprintf (output_description_file, ",\n ");
9462 curr_line_length = strlen (insn_name) + 6;
9464 else
9465 curr_line_length += strlen (insn_name);
9467 else
9469 curr_line_length += strlen (insn_name);
9470 if (ainsn != arc->insn)
9472 curr_line_length += 2;
9473 fprintf (output_description_file, ", ");
9476 fprintf (output_description_file, insn_name);
9477 ainsn = ainsn->next_same_reservs_insn;
9479 while (ainsn != NULL);
9480 fprintf (output_description_file, " %d (%d)\n",
9481 arc->to_state->order_state_num, arc->state_alts);
9483 fprintf (output_description_file, "\n");
9486 /* The following function is used for sorting possible cpu unit
9487 reservation of a DFA state. */
9488 static int
9489 state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
9490 const void *reservs_ptr_1;
9491 const void *reservs_ptr_2;
9493 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9494 *(reserv_sets_t *) reservs_ptr_2);
9497 /* The following function is used for sorting possible cpu unit
9498 reservation of a DFA state. */
9499 static void
9500 remove_state_duplicate_reservs ()
9502 reserv_sets_t *reservs_ptr;
9503 reserv_sets_t *last_formed_reservs_ptr;
9505 last_formed_reservs_ptr = NULL;
9506 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9507 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9508 reservs_ptr++)
9509 if (last_formed_reservs_ptr == NULL)
9510 last_formed_reservs_ptr = reservs_ptr;
9511 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9513 ++last_formed_reservs_ptr;
9514 *last_formed_reservs_ptr = *reservs_ptr;
9516 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9519 /* The following function output readable representation of DFA(s)
9520 state used for fast recognition of pipeline hazards. State is
9521 described by possible (current and scheduled) cpu unit
9522 reservations. */
9523 static void
9524 output_state (state)
9525 state_t state;
9527 reserv_sets_t *reservs_ptr;
9529 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9530 fprintf (output_description_file, " State #%d", state->order_state_num);
9531 fprintf (output_description_file,
9532 state->new_cycle_p ? " (new cycle)\n" : "\n");
9533 add_state_reservs (state);
9534 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9535 sizeof (reserv_sets_t), state_reservs_cmp);
9536 remove_state_duplicate_reservs ();
9537 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9538 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9539 reservs_ptr++)
9541 fprintf (output_description_file, " ");
9542 output_reserv_sets (output_description_file, *reservs_ptr);
9543 fprintf (output_description_file, "\n");
9545 fprintf (output_description_file, "\n");
9546 output_state_arcs (state);
9547 VLA_PTR_DELETE (state_reservs);
9550 /* The following function output readable representation of
9551 DFAs used for fast recognition of pipeline hazards. */
9552 static void
9553 output_automaton_descriptions ()
9555 automaton_t automaton;
9557 for (automaton = description->first_automaton;
9558 automaton != NULL;
9559 automaton = automaton->next_automaton)
9561 fprintf (output_description_file, "\nAutomaton ");
9562 output_automaton_name (output_description_file, automaton);
9563 fprintf (output_description_file, "\n");
9564 output_automaton_units (automaton);
9565 pass_states (automaton, output_state);
9571 /* The page contains top level function for generation DFA(s) used for
9572 PHR. */
9574 /* The function outputs statistics about work of different phases of
9575 DFA generator. */
9576 static void
9577 output_statistics (f)
9578 FILE *f;
9580 automaton_t automaton;
9581 int states_num;
9582 #ifndef NDEBUG
9583 int transition_comb_vect_els = 0;
9584 int transition_full_vect_els = 0;
9585 int state_alts_comb_vect_els = 0;
9586 int state_alts_full_vect_els = 0;
9587 int min_issue_delay_vect_els = 0;
9588 #endif
9590 for (automaton = description->first_automaton;
9591 automaton != NULL;
9592 automaton = automaton->next_automaton)
9594 fprintf (f, "\nAutomaton ");
9595 output_automaton_name (f, automaton);
9596 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9597 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9598 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9599 automaton->DFA_states_num, automaton->DFA_arcs_num);
9600 states_num = automaton->DFA_states_num;
9601 if (!no_minimization_flag)
9603 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9604 automaton->minimal_DFA_states_num,
9605 automaton->minimal_DFA_arcs_num);
9606 states_num = automaton->minimal_DFA_states_num;
9608 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9609 description->insns_num, automaton->insn_equiv_classes_num);
9610 #ifndef NDEBUG
9611 fprintf
9612 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9613 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9614 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9615 (comb_vect_p (automaton->trans_table)
9616 ? "use comb vect" : "use simple vect"));
9617 fprintf
9618 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9619 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9620 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9621 (comb_vect_p (automaton->state_alts_table)
9622 ? "use comb vect" : "use simple vect"));
9623 fprintf
9624 (f, "%5ld min delay table els, compression factor %d\n",
9625 (long) states_num * automaton->insn_equiv_classes_num,
9626 automaton->min_issue_delay_table_compression_factor);
9627 transition_comb_vect_els
9628 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9629 transition_full_vect_els
9630 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9631 state_alts_comb_vect_els
9632 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9633 state_alts_full_vect_els
9634 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9635 min_issue_delay_vect_els
9636 += states_num * automaton->insn_equiv_classes_num;
9637 #endif
9639 #ifndef NDEBUG
9640 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9641 allocated_states_num, allocated_arcs_num);
9642 fprintf (f, "%5d all allocated alternative states\n",
9643 allocated_alt_states_num);
9644 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9645 transition_comb_vect_els, transition_full_vect_els);
9646 fprintf
9647 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9648 state_alts_comb_vect_els, state_alts_full_vect_els);
9649 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9650 fprintf (f, "%5d locked states num\n", locked_states_num);
9651 #endif
9654 /* The function output times of work of different phases of DFA
9655 generator. */
9656 static void
9657 output_time_statistics (f)
9658 FILE *f;
9660 fprintf (f, "\n transformation: ");
9661 print_active_time (f, transform_time);
9662 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9663 print_active_time (f, NDFA_time);
9664 if (ndfa_flag)
9666 fprintf (f, ", NDFA -> DFA: ");
9667 print_active_time (f, NDFA_to_DFA_time);
9669 fprintf (f, "\n DFA minimization: ");
9670 print_active_time (f, minimize_time);
9671 fprintf (f, ", making insn equivalence: ");
9672 print_active_time (f, equiv_time);
9673 fprintf (f, "\n all automaton generation: ");
9674 print_active_time (f, automaton_generation_time);
9675 fprintf (f, ", output: ");
9676 print_active_time (f, output_time);
9677 fprintf (f, "\n");
9680 /* The function generates DFA (deterministic finite state automaton)
9681 for fast recognition of pipeline hazards. No errors during
9682 checking must be fixed before this function call. */
9683 static void
9684 generate ()
9686 automata_num = split_argument;
9687 if (description->units_num < automata_num)
9688 automata_num = description->units_num;
9689 initiate_states ();
9690 initiate_arcs ();
9691 initiate_automata_lists ();
9692 initiate_pass_states ();
9693 initiate_excl_sets ();
9694 initiate_presence_absence_pattern_sets ();
9695 automaton_generation_time = create_ticker ();
9696 create_automata ();
9697 ticker_off (&automaton_generation_time);
9702 /* The following function creates insn attribute whose values are
9703 number alternatives in insn reservations. */
9704 static void
9705 make_insn_alts_attr ()
9707 int i, insn_num;
9708 decl_t decl;
9709 rtx condexp;
9711 condexp = rtx_alloc (COND);
9712 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9713 XEXP (condexp, 1) = make_numeric_value (0);
9714 for (i = insn_num = 0; i < description->decls_num; i++)
9716 decl = description->decls [i];
9717 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9719 XVECEXP (condexp, 0, 2 * insn_num)
9720 = DECL_INSN_RESERV (decl)->condexp;
9721 XVECEXP (condexp, 0, 2 * insn_num + 1)
9722 = make_numeric_value
9723 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9724 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9725 ->transformed_regexp)->regexps_num);
9726 insn_num++;
9729 if (description->insns_num != insn_num + 1)
9730 abort ();
9731 make_internal_attr (attr_printf (sizeof ("*")
9732 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9733 "*%s", INSN_ALTS_FUNC_NAME),
9734 condexp, 0);
9739 /* The following function creates attribute which is order number of
9740 insn in pipeline hazard description translator. */
9741 static void
9742 make_internal_dfa_insn_code_attr ()
9744 int i, insn_num;
9745 decl_t decl;
9746 rtx condexp;
9748 condexp = rtx_alloc (COND);
9749 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9750 XEXP (condexp, 1)
9751 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9752 ->insn_num + 1);
9753 for (i = insn_num = 0; i < description->decls_num; i++)
9755 decl = description->decls [i];
9756 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9758 XVECEXP (condexp, 0, 2 * insn_num)
9759 = DECL_INSN_RESERV (decl)->condexp;
9760 XVECEXP (condexp, 0, 2 * insn_num + 1)
9761 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9762 insn_num++;
9765 if (description->insns_num != insn_num + 1)
9766 abort ();
9767 make_internal_attr
9768 (attr_printf (sizeof ("*")
9769 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9770 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9771 condexp, 0);
9776 /* The following function creates attribute which order number of insn
9777 in pipeline hazard description translator. */
9778 static void
9779 make_default_insn_latency_attr ()
9781 int i, insn_num;
9782 decl_t decl;
9783 rtx condexp;
9785 condexp = rtx_alloc (COND);
9786 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9787 XEXP (condexp, 1) = make_numeric_value (0);
9788 for (i = insn_num = 0; i < description->decls_num; i++)
9790 decl = description->decls [i];
9791 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9793 XVECEXP (condexp, 0, 2 * insn_num)
9794 = DECL_INSN_RESERV (decl)->condexp;
9795 XVECEXP (condexp, 0, 2 * insn_num + 1)
9796 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9797 insn_num++;
9800 if (description->insns_num != insn_num + 1)
9801 abort ();
9802 make_internal_attr (attr_printf (sizeof ("*")
9803 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9804 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9805 condexp, 0);
9810 /* The following function creates attribute which returns 1 if given
9811 output insn has bypassing and 0 otherwise. */
9812 static void
9813 make_bypass_attr ()
9815 int i, bypass_insn;
9816 int bypass_insns_num = 0;
9817 decl_t decl;
9818 rtx result_rtx;
9820 for (i = 0; i < description->decls_num; i++)
9822 decl = description->decls [i];
9823 if (decl->mode == dm_insn_reserv
9824 && DECL_INSN_RESERV (decl)->condexp != NULL
9825 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9826 bypass_insns_num++;
9828 if (bypass_insns_num == 0)
9829 result_rtx = make_numeric_value (0);
9830 else
9832 result_rtx = rtx_alloc (COND);
9833 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9834 XEXP (result_rtx, 1) = make_numeric_value (0);
9836 for (i = bypass_insn = 0; i < description->decls_num; i++)
9838 decl = description->decls [i];
9839 if (decl->mode == dm_insn_reserv
9840 && DECL_INSN_RESERV (decl)->condexp != NULL
9841 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9843 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9844 = DECL_INSN_RESERV (decl)->condexp;
9845 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9846 = make_numeric_value (1);
9847 bypass_insn++;
9851 make_internal_attr (attr_printf (sizeof ("*")
9852 + strlen (BYPASS_P_FUNC_NAME) + 1,
9853 "*%s", BYPASS_P_FUNC_NAME),
9854 result_rtx, 0);
9859 /* This page mainly contains top level functions of pipeline hazards
9860 description translator. */
9862 /* The following macro value is suffix of name of description file of
9863 pipeline hazards description translator. */
9864 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9866 /* The function returns suffix of given file name. The returned
9867 string can not be changed. */
9868 static const char *
9869 file_name_suffix (file_name)
9870 const char *file_name;
9872 const char *last_period;
9874 for (last_period = NULL; *file_name != '\0'; file_name++)
9875 if (*file_name == '.')
9876 last_period = file_name;
9877 return (last_period == NULL ? file_name : last_period);
9880 /* The function returns base name of given file name, i.e. pointer to
9881 first char after last `/' (or `\' for WIN32) in given file name,
9882 given file name itself if the directory name is absent. The
9883 returned string can not be changed. */
9884 static const char *
9885 base_file_name (file_name)
9886 const char *file_name;
9888 int directory_name_length;
9890 directory_name_length = strlen (file_name);
9891 #ifdef WIN32
9892 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9893 && file_name[directory_name_length] != '\\')
9894 #else
9895 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9896 #endif
9897 directory_name_length--;
9898 return file_name + directory_name_length + 1;
9901 /* The following is top level function to initialize the work of
9902 pipeline hazards description translator. */
9903 void
9904 initiate_automaton_gen (argc, argv)
9905 int argc;
9906 char **argv;
9908 const char *base_name;
9909 int i;
9911 ndfa_flag = 0;
9912 split_argument = 0; /* default value */
9913 no_minimization_flag = 0;
9914 time_flag = 0;
9915 v_flag = 0;
9916 w_flag = 0;
9917 for (i = 2; i < argc; i++)
9918 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9919 no_minimization_flag = 1;
9920 else if (strcmp (argv [i], TIME_OPTION) == 0)
9921 time_flag = 1;
9922 else if (strcmp (argv [i], V_OPTION) == 0)
9923 v_flag = 1;
9924 else if (strcmp (argv [i], W_OPTION) == 0)
9925 w_flag = 1;
9926 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9927 ndfa_flag = 1;
9928 else if (strcmp (argv [i], "-split") == 0)
9930 if (i + 1 >= argc)
9931 fatal ("-split has no argument.");
9932 fatal ("option `-split' has not been implemented yet\n");
9933 /* split_argument = atoi (argument_vect [i + 1]); */
9935 VLA_PTR_CREATE (decls, 150, "decls");
9936 /* Initialize IR storage. */
9937 obstack_init (&irp);
9938 initiate_automaton_decl_table ();
9939 initiate_insn_decl_table ();
9940 initiate_decl_table ();
9941 output_file = stdout;
9942 output_description_file = NULL;
9943 base_name = base_file_name (argv[1]);
9944 obstack_grow (&irp, base_name,
9945 strlen (base_name) - strlen (file_name_suffix (base_name)));
9946 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9947 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9948 obstack_1grow (&irp, '\0');
9949 output_description_file_name = obstack_base (&irp);
9950 obstack_finish (&irp);
9953 /* The following function checks existence at least one arc marked by
9954 each insn. */
9955 static void
9956 check_automata_insn_issues ()
9958 automaton_t automaton;
9959 ainsn_t ainsn, reserv_ainsn;
9961 for (automaton = description->first_automaton;
9962 automaton != NULL;
9963 automaton = automaton->next_automaton)
9965 for (ainsn = automaton->ainsn_list;
9966 ainsn != NULL;
9967 ainsn = ainsn->next_ainsn)
9968 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9970 for (reserv_ainsn = ainsn;
9971 reserv_ainsn != NULL;
9972 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9973 if (automaton->corresponding_automaton_decl != NULL)
9975 if (!w_flag)
9976 error ("Automaton `%s': Insn `%s' will never be issued",
9977 automaton->corresponding_automaton_decl->name,
9978 reserv_ainsn->insn_reserv_decl->name);
9979 else
9980 warning
9981 ("Automaton `%s': Insn `%s' will never be issued",
9982 automaton->corresponding_automaton_decl->name,
9983 reserv_ainsn->insn_reserv_decl->name);
9985 else
9987 if (!w_flag)
9988 error ("Insn `%s' will never be issued",
9989 reserv_ainsn->insn_reserv_decl->name);
9990 else
9991 warning ("Insn `%s' will never be issued",
9992 reserv_ainsn->insn_reserv_decl->name);
9998 /* The following vla is used for storing pointers to all achieved
9999 states. */
10000 static vla_ptr_t automaton_states;
10002 /* This function is called by function pass_states to add an achieved
10003 STATE. */
10004 static void
10005 add_automaton_state (state)
10006 state_t state;
10008 VLA_PTR_ADD (automaton_states, state);
10011 /* The following function forms list of important automata (whose
10012 states may be changed after the insn issue) for each insn. */
10013 static void
10014 form_important_insn_automata_lists ()
10016 automaton_t automaton;
10017 state_t *state_ptr;
10018 decl_t decl;
10019 ainsn_t ainsn;
10020 arc_t arc;
10021 int i;
10023 VLA_PTR_CREATE (automaton_states, 1500,
10024 "automaton states for forming important insn automata sets");
10025 /* Mark important ainsns. */
10026 for (automaton = description->first_automaton;
10027 automaton != NULL;
10028 automaton = automaton->next_automaton)
10030 VLA_PTR_NULLIFY (automaton_states);
10031 pass_states (automaton, add_automaton_state);
10032 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
10033 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
10034 state_ptr++)
10036 for (arc = first_out_arc (*state_ptr);
10037 arc != NULL;
10038 arc = next_out_arc (arc))
10039 if (arc->to_state != *state_ptr)
10041 if (!arc->insn->first_insn_with_same_reservs)
10042 abort ();
10043 for (ainsn = arc->insn;
10044 ainsn != NULL;
10045 ainsn = ainsn->next_same_reservs_insn)
10046 ainsn->important_p = TRUE;
10050 VLA_PTR_DELETE (automaton_states);
10051 /* Create automata sets for the insns. */
10052 for (i = 0; i < description->decls_num; i++)
10054 decl = description->decls [i];
10055 if (decl->mode == dm_insn_reserv)
10057 automata_list_start ();
10058 for (automaton = description->first_automaton;
10059 automaton != NULL;
10060 automaton = automaton->next_automaton)
10061 for (ainsn = automaton->ainsn_list;
10062 ainsn != NULL;
10063 ainsn = ainsn->next_ainsn)
10064 if (ainsn->important_p
10065 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
10067 automata_list_add (automaton);
10068 break;
10070 DECL_INSN_RESERV (decl)->important_automata_list
10071 = automata_list_finish ();
10077 /* The following is top level function to generate automat(a,on) for
10078 fast recognition of pipeline hazards. */
10079 void
10080 expand_automata ()
10082 int i;
10084 description = create_node (sizeof (struct description)
10085 /* One entry for cycle advancing insn. */
10086 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
10087 description->decls_num = VLA_PTR_LENGTH (decls);
10088 description->query_units_num = 0;
10089 for (i = 0; i < description->decls_num; i++)
10091 description->decls [i] = VLA_PTR (decls, i);
10092 if (description->decls [i]->mode == dm_unit
10093 && DECL_UNIT (description->decls [i])->query_p)
10094 DECL_UNIT (description->decls [i])->query_num
10095 = description->query_units_num++;
10097 all_time = create_ticker ();
10098 check_time = create_ticker ();
10099 fprintf (stderr, "Check description...");
10100 fflush (stderr);
10101 check_all_description ();
10102 fprintf (stderr, "done\n");
10103 ticker_off (&check_time);
10104 generation_time = create_ticker ();
10105 if (!have_error)
10107 transform_insn_regexps ();
10108 check_unit_distributions_to_automata ();
10110 if (!have_error)
10112 generate ();
10113 check_automata_insn_issues ();
10115 if (!have_error)
10117 form_important_insn_automata_lists ();
10118 fprintf (stderr, "Generation of attributes...");
10119 fflush (stderr);
10120 make_internal_dfa_insn_code_attr ();
10121 make_insn_alts_attr ();
10122 make_default_insn_latency_attr ();
10123 make_bypass_attr ();
10124 fprintf (stderr, "done\n");
10126 ticker_off (&generation_time);
10127 ticker_off (&all_time);
10128 fprintf (stderr, "All other genattrtab stuff...");
10129 fflush (stderr);
10132 /* The following is top level function to output PHR and to finish
10133 work with pipeline description translator. */
10134 void
10135 write_automata ()
10137 fprintf (stderr, "done\n");
10138 if (have_error)
10139 fatal ("Errors in DFA description");
10140 ticker_on (&all_time);
10141 output_time = create_ticker ();
10142 fprintf (stderr, "Forming and outputing automata tables...");
10143 fflush (stderr);
10144 output_dfa_max_issue_rate ();
10145 output_tables ();
10146 fprintf (stderr, "done\n");
10147 fprintf (stderr, "Output functions to work with automata...");
10148 fflush (stderr);
10149 output_chip_definitions ();
10150 output_max_insn_queue_index_def ();
10151 output_internal_min_issue_delay_func ();
10152 output_internal_trans_func ();
10153 /* Cache of insn dfa codes: */
10154 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
10155 fprintf (output_file, "\nstatic int %s;\n\n",
10156 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
10157 output_dfa_insn_code_func ();
10158 output_trans_func ();
10159 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
10160 output_internal_state_alts_func ();
10161 output_state_alts_func ();
10162 fprintf (output_file, "\n#endif /* #if %s */\n\n",
10163 AUTOMATON_STATE_ALTS_MACRO_NAME);
10164 output_min_issue_delay_func ();
10165 output_internal_dead_lock_func ();
10166 output_dead_lock_func ();
10167 output_size_func ();
10168 output_internal_reset_func ();
10169 output_reset_func ();
10170 output_min_insn_conflict_delay_func ();
10171 output_internal_insn_latency_func ();
10172 output_insn_latency_func ();
10173 output_print_reservation_func ();
10174 /* Output function get_cpu_unit_code. */
10175 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
10176 output_get_cpu_unit_code_func ();
10177 output_cpu_unit_reservation_p ();
10178 fprintf (output_file, "\n#endif /* #if %s */\n\n",
10179 CPU_UNITS_QUERY_MACRO_NAME);
10180 output_dfa_clean_insn_cache_func ();
10181 output_dfa_start_func ();
10182 output_dfa_finish_func ();
10183 fprintf (stderr, "done\n");
10184 if (v_flag)
10186 output_description_file = fopen (output_description_file_name, "w");
10187 if (output_description_file == NULL)
10189 perror (output_description_file_name);
10190 exit (FATAL_EXIT_CODE);
10192 fprintf (stderr, "Output automata description...");
10193 fflush (stderr);
10194 output_description ();
10195 output_automaton_descriptions ();
10196 fprintf (stderr, "done\n");
10197 output_statistics (output_description_file);
10199 output_statistics (stderr);
10200 ticker_off (&output_time);
10201 output_time_statistics (stderr);
10202 finish_states ();
10203 finish_arcs ();
10204 finish_automata_lists ();
10205 if (time_flag)
10207 fprintf (stderr, "Summary:\n");
10208 fprintf (stderr, " check time ");
10209 print_active_time (stderr, check_time);
10210 fprintf (stderr, ", generation time ");
10211 print_active_time (stderr, generation_time);
10212 fprintf (stderr, ", all time ");
10213 print_active_time (stderr, all_time);
10214 fprintf (stderr, "\n");
10216 /* Finish all work. */
10217 if (output_description_file != NULL)
10219 fflush (output_description_file);
10220 if (ferror (stdout) != 0)
10221 fatal ("Error in writing DFA description file %s",
10222 output_description_file_name);
10223 fclose (output_description_file);
10225 finish_automaton_decl_table ();
10226 finish_insn_decl_table ();
10227 finish_decl_table ();
10228 obstack_free (&irp, NULL);
10229 if (have_error && output_description_file != NULL)
10230 remove (output_description_file_name);