* config/arm/elf.h (ASM_OUTPUT_ALIGNED_COMMON): Remove definition.
[official-gcc.git] / gcc / genautomata.c
blob438bdefaa27b30721b3e16bf8aa6d258ba8d9e2a
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 GCC.
8 GCC 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 GCC 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 GCC; 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 store_alt_unit_usage PARAMS ((regexp_t, regexp_t, int, int));
371 static void check_regexp_units_distribution PARAMS ((const char *, regexp_t));
372 static void check_unit_distributions_to_automata PARAMS ((void));
374 static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t,
375 int));
376 static void finish_forming_alt_state PARAMS ((alt_state_t,
377 automaton_t));
378 static void process_alts_for_forming_states PARAMS ((regexp_t,
379 automaton_t, int));
380 static void create_alt_states PARAMS ((automaton_t));
382 static void form_ainsn_with_same_reservs PARAMS ((automaton_t));
384 static reserv_sets_t form_reservs_matter PARAMS ((automaton_t));
385 static void make_automaton PARAMS ((automaton_t));
386 static void form_arcs_marked_by_insn PARAMS ((state_t));
387 static int create_composed_state PARAMS ((state_t, arc_t, vla_ptr_t *));
388 static void NDFA_to_DFA PARAMS ((automaton_t));
389 static void pass_state_graph PARAMS ((state_t, void (*) (state_t)));
390 static void pass_states PARAMS ((automaton_t,
391 void (*) (state_t)));
392 static void initiate_pass_states PARAMS ((void));
393 static void add_achieved_state PARAMS ((state_t));
394 static int set_out_arc_insns_equiv_num PARAMS ((state_t, int));
395 static void clear_arc_insns_equiv_num PARAMS ((state_t));
396 static void copy_equiv_class PARAMS ((vla_ptr_t *to,
397 const vla_ptr_t *from));
398 static int first_cycle_unit_presence PARAMS ((state_t, int));
399 static int state_is_differed PARAMS ((state_t, state_t, int, int));
400 static state_t init_equiv_class PARAMS ((state_t *states, int));
401 static int partition_equiv_class PARAMS ((state_t *, int,
402 vla_ptr_t *, int *));
403 static void evaluate_equiv_classes PARAMS ((automaton_t, vla_ptr_t *));
404 static void merge_states PARAMS ((automaton_t, vla_ptr_t *));
405 static void set_new_cycle_flags PARAMS ((state_t));
406 static void minimize_DFA PARAMS ((automaton_t));
407 static void incr_states_and_arcs_nums PARAMS ((state_t));
408 static void count_states_and_arcs PARAMS ((automaton_t, int *, int *));
409 static void build_automaton PARAMS ((automaton_t));
411 static void set_order_state_num PARAMS ((state_t));
412 static void enumerate_states PARAMS ((automaton_t));
414 static ainsn_t insert_ainsn_into_equiv_class PARAMS ((ainsn_t, ainsn_t));
415 static void delete_ainsn_from_equiv_class PARAMS ((ainsn_t));
416 static void process_insn_equiv_class PARAMS ((ainsn_t, arc_t *));
417 static void process_state_for_insn_equiv_partition PARAMS ((state_t));
418 static void set_insn_equiv_classes PARAMS ((automaton_t));
420 static double estimate_one_automaton_bound PARAMS ((void));
421 static int compare_max_occ_cycle_nums PARAMS ((const void *,
422 const void *));
423 static void units_to_automata_heuristic_distr PARAMS ((void));
424 static ainsn_t create_ainsns PARAMS ((void));
425 static void units_to_automata_distr PARAMS ((void));
426 static void create_automata PARAMS ((void));
428 static void form_regexp PARAMS ((regexp_t));
429 static const char *regexp_representation PARAMS ((regexp_t));
430 static void finish_regexp_representation PARAMS ((void));
432 static void output_range_type PARAMS ((FILE *, long int, long int));
433 static int longest_path_length PARAMS ((state_t));
434 static void process_state_longest_path_length PARAMS ((state_t));
435 static void output_dfa_max_issue_rate PARAMS ((void));
436 static void output_vect PARAMS ((vect_el_t *, int));
437 static void output_chip_member_name PARAMS ((FILE *, automaton_t));
438 static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t));
439 static void output_translate_vect_name PARAMS ((FILE *, automaton_t));
440 static void output_trans_full_vect_name PARAMS ((FILE *, automaton_t));
441 static void output_trans_comb_vect_name PARAMS ((FILE *, automaton_t));
442 static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t));
443 static void output_trans_base_vect_name PARAMS ((FILE *, automaton_t));
444 static void output_state_alts_full_vect_name PARAMS ((FILE *, automaton_t));
445 static void output_state_alts_comb_vect_name PARAMS ((FILE *, automaton_t));
446 static void output_state_alts_check_vect_name PARAMS ((FILE *, automaton_t));
447 static void output_state_alts_base_vect_name PARAMS ((FILE *, automaton_t));
448 static void output_min_issue_delay_vect_name PARAMS ((FILE *, automaton_t));
449 static void output_dead_lock_vect_name PARAMS ((FILE *, automaton_t));
450 static void output_reserved_units_table_name PARAMS ((FILE *, automaton_t));
451 static void output_state_member_type PARAMS ((FILE *, automaton_t));
452 static void output_chip_definitions PARAMS ((void));
453 static void output_translate_vect PARAMS ((automaton_t));
454 static int comb_vect_p PARAMS ((state_ainsn_table_t));
455 static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t));
456 static void output_state_ainsn_table
457 PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
458 void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
459 void (*) (FILE *, automaton_t)));
460 static void add_vect PARAMS ((state_ainsn_table_t,
461 int, vect_el_t *, int));
462 static int out_state_arcs_num PARAMS ((state_t));
463 static int compare_transition_els_num PARAMS ((const void *, const void *));
464 static void add_vect_el PARAMS ((vla_hwint_t *,
465 ainsn_t, int));
466 static void add_states_vect_el PARAMS ((state_t));
467 static void output_trans_table PARAMS ((automaton_t));
468 static void output_state_alts_table PARAMS ((automaton_t));
469 static int min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
470 static int min_issue_delay PARAMS ((state_t, ainsn_t));
471 static void initiate_min_issue_delay_pass_states PARAMS ((void));
472 static void output_min_issue_delay_table PARAMS ((automaton_t));
473 static void output_dead_lock_vect PARAMS ((automaton_t));
474 static void output_reserved_units_table PARAMS ((automaton_t));
475 static void output_tables PARAMS ((void));
476 static void output_max_insn_queue_index_def PARAMS ((void));
477 static void output_insn_code_cases PARAMS ((void (*) (automata_list_el_t)));
478 static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
479 static void output_internal_min_issue_delay_func PARAMS ((void));
480 static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
481 static void output_internal_trans_func PARAMS ((void));
482 static void output_internal_insn_code_evaluation PARAMS ((const char *,
483 const char *, int));
484 static void output_dfa_insn_code_func PARAMS ((void));
485 static void output_trans_func PARAMS ((void));
486 static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
487 static void output_internal_state_alts_func PARAMS ((void));
488 static void output_state_alts_func PARAMS ((void));
489 static void output_min_issue_delay_func PARAMS ((void));
490 static void output_internal_dead_lock_func PARAMS ((void));
491 static void output_dead_lock_func PARAMS ((void));
492 static void output_internal_reset_func PARAMS ((void));
493 static void output_size_func PARAMS ((void));
494 static void output_reset_func PARAMS ((void));
495 static void output_min_insn_conflict_delay_func PARAMS ((void));
496 static void output_internal_insn_latency_func PARAMS ((void));
497 static void output_insn_latency_func PARAMS ((void));
498 static void output_print_reservation_func PARAMS ((void));
499 static int units_cmp PARAMS ((const void *,
500 const void *));
501 static void output_get_cpu_unit_code_func PARAMS ((void));
502 static void output_cpu_unit_reservation_p PARAMS ((void));
503 static void output_dfa_clean_insn_cache_func PARAMS ((void));
504 static void output_dfa_start_func PARAMS ((void));
505 static void output_dfa_finish_func PARAMS ((void));
507 static void output_regexp PARAMS ((regexp_t ));
508 static void output_unit_set_el_list PARAMS ((unit_set_el_t));
509 static void output_pattern_set_el_list PARAMS ((pattern_set_el_t));
510 static void output_description PARAMS ((void));
511 static void output_automaton_name PARAMS ((FILE *, automaton_t));
512 static void output_automaton_units PARAMS ((automaton_t));
513 static void add_state_reservs PARAMS ((state_t));
514 static void output_state_arcs PARAMS ((state_t));
515 static int state_reservs_cmp PARAMS ((const void *,
516 const void *));
517 static void remove_state_duplicate_reservs PARAMS ((void));
518 static void output_state PARAMS ((state_t));
519 static void output_automaton_descriptions PARAMS ((void));
520 static void output_statistics PARAMS ((FILE *));
521 static void output_time_statistics PARAMS ((FILE *));
522 static void generate PARAMS ((void));
524 static void make_insn_alts_attr PARAMS ((void));
525 static void make_internal_dfa_insn_code_attr PARAMS ((void));
526 static void make_default_insn_latency_attr PARAMS ((void));
527 static void make_bypass_attr PARAMS ((void));
528 static const char *file_name_suffix PARAMS ((const char *));
529 static const char *base_file_name PARAMS ((const char *));
530 static void check_automata_insn_issues PARAMS ((void));
531 static void add_automaton_state PARAMS ((state_t));
532 static void form_important_insn_automata_lists PARAMS ((void));
534 /* Undefined position. */
535 static pos_t no_pos = 0;
537 /* All IR is stored in the following obstack. */
538 static struct obstack irp;
542 /* This page contains code for work with variable length array (vla)
543 of pointers. We could be use only varray. But we add new lay
544 because we add elements very frequently and this could stress OS
545 allocator when varray is used only. */
547 /* Start work with vla. */
548 #define VLA_PTR_CREATE(vla, allocated_length, name) \
549 do \
551 vla_ptr_t *const _vla_ptr = &(vla); \
553 VARRAY_GENERIC_PTR_INIT (_vla_ptr->varray, allocated_length, name);\
554 _vla_ptr->length = 0; \
556 while (0)
558 /* Finish work with the vla. */
559 #define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
561 /* Return start address of the vla. */
562 #define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
564 /* Address of the last element of the vla. Do not use side effects in
565 the macro argument. */
566 #define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \
567 (vla).length - 1))
568 /* Nullify the vla. */
569 #define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
571 /* Shorten the vla on given number bytes. */
572 #define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
574 /* Expand the vla on N elements. The values of new elements are
575 undefined. */
576 #define VLA_PTR_EXPAND(vla, n) \
577 do { \
578 vla_ptr_t *const _expand_vla_ptr = &(vla); \
579 const size_t _new_length = (n) + _expand_vla_ptr->length; \
581 if (VARRAY_SIZE (_expand_vla_ptr->varray) < _new_length) \
582 VARRAY_GROW (_expand_vla_ptr->varray, \
583 (_new_length - _expand_vla_ptr->length < 128 \
584 ? _expand_vla_ptr->length + 128 : _new_length)); \
585 _expand_vla_ptr->length = _new_length; \
586 } while (0)
588 /* Add element to the end of the vla. */
589 #define VLA_PTR_ADD(vla, ptr) \
590 do { \
591 vla_ptr_t *const _vla_ptr = &(vla); \
593 VLA_PTR_EXPAND (*_vla_ptr, 1); \
594 VARRAY_GENERIC_PTR (_vla_ptr->varray, _vla_ptr->length - 1) = (ptr);\
595 } while (0)
597 /* Length of the vla in elements. */
598 #define VLA_PTR_LENGTH(vla) ((vla).length)
600 /* N-th element of the vla. */
601 #define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
604 /* The following macros are analogous to the previous ones but for
605 VLAs of HOST WIDE INTs. */
607 #define VLA_HWINT_CREATE(vla, allocated_length, name) \
608 do { \
609 vla_hwint_t *const _vla_ptr = &(vla); \
611 VARRAY_WIDE_INT_INIT (_vla_ptr->varray, allocated_length, name); \
612 _vla_ptr->length = 0; \
613 } while (0)
615 #define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
617 #define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
619 #define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
621 #define VLA_HWINT_EXPAND(vla, n) \
622 do { \
623 vla_hwint_t *const _expand_vla_ptr = &(vla); \
624 const size_t _new_length = (n) + _expand_vla_ptr->length; \
626 if (VARRAY_SIZE (_expand_vla_ptr->varray) < _new_length) \
627 VARRAY_GROW (_expand_vla_ptr->varray, \
628 (_new_length - _expand_vla_ptr->length < 128 \
629 ? _expand_vla_ptr->length + 128 : _new_length)); \
630 _expand_vla_ptr->length = _new_length; \
631 } while (0)
633 #define VLA_HWINT_ADD(vla, ptr) \
634 do { \
635 vla_hwint_t *const _vla_ptr = &(vla); \
637 VLA_HWINT_EXPAND (*_vla_ptr, 1); \
638 VARRAY_WIDE_INT (_vla_ptr->varray, _vla_ptr->length - 1) = (ptr); \
639 } while (0)
641 #define VLA_HWINT_LENGTH(vla) ((vla).length)
643 #define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
647 /* Options with the following names can be set up in automata_option
648 construction. Because the strings occur more one time we use the
649 macros. */
651 #define NO_MINIMIZATION_OPTION "-no-minimization"
653 #define TIME_OPTION "-time"
655 #define V_OPTION "-v"
657 #define W_OPTION "-w"
659 #define NDFA_OPTION "-ndfa"
661 /* The following flags are set up by function `initiate_automaton_gen'. */
663 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
664 static int ndfa_flag;
666 /* Do not make minimization of DFA (`-no-minimization'). */
667 static int no_minimization_flag;
669 /* Value of this variable is number of automata being generated. The
670 actual number of automata may be less this value if there is not
671 sufficient number of units. This value is defined by argument of
672 option `-split' or by constructions automaton if the value is zero
673 (it is default value of the argument). */
674 static int split_argument;
676 /* Flag of output time statistics (`-time'). */
677 static int time_flag;
679 /* Flag of creation of description file which contains description of
680 result automaton and statistics information (`-v'). */
681 static int v_flag;
683 /* Flag of generating warning instead of error for non-critical errors
684 (`-w'). */
685 static int w_flag;
688 /* Output file for pipeline hazard recognizer (PHR) being generated.
689 The value is NULL if the file is not defined. */
690 static FILE *output_file;
692 /* Description file of PHR. The value is NULL if the file is not
693 created. */
694 static FILE *output_description_file;
696 /* PHR description file name. */
697 static char *output_description_file_name;
699 /* Value of the following variable is node representing description
700 being processed. This is start point of IR. */
701 static struct description *description;
705 /* This page contains description of IR structure (nodes). */
707 enum decl_mode
709 dm_unit,
710 dm_bypass,
711 dm_automaton,
712 dm_excl,
713 dm_presence,
714 dm_absence,
715 dm_reserv,
716 dm_insn_reserv
719 /* This describes define_cpu_unit and define_query_cpu_unit (see file
720 rtl.def). */
721 struct unit_decl
723 char *name;
724 /* NULL if the automaton name is absent. */
725 char *automaton_name;
726 /* If the following value is not zero, the cpu unit reservation is
727 described in define_query_cpu_unit. */
728 char query_p;
730 /* The following fields are defined by checker. */
732 /* The following field value is nonzero if the unit is used in an
733 regexp. */
734 char unit_is_used;
736 /* The following field value is order number (0, 1, ...) of given
737 unit. */
738 int unit_num;
739 /* The following field value is corresponding declaration of
740 automaton which was given in description. If the field value is
741 NULL then automaton in the unit declaration was absent. */
742 struct automaton_decl *automaton_decl;
743 /* The following field value is maximal cycle number (1, ...) on
744 which given unit occurs in insns. Zero value means that given
745 unit is not used in insns. */
746 int max_occ_cycle_num;
747 /* The following field value is minimal cycle number (0, ...) on
748 which given unit occurs in insns. -1 value means that given
749 unit is not used in insns. */
750 int min_occ_cycle_num;
751 /* The following list contains units which conflict with given
752 unit. */
753 unit_set_el_t excl_list;
754 /* The following list contains patterns which are required to
755 reservation of given unit. */
756 pattern_set_el_t presence_list;
757 pattern_set_el_t final_presence_list;
758 /* The following list contains patterns which should be not present
759 in reservation for given unit. */
760 pattern_set_el_t absence_list;
761 pattern_set_el_t final_absence_list;
762 /* The following is used only when `query_p' has nonzero value.
763 This is query number for the unit. */
764 int query_num;
765 /* The following is the last cycle on which the unit was checked for
766 correct distributions of units to automata in a regexp. */
767 int last_distribution_check_cycle;
769 /* The following fields are defined by automaton generator. */
771 /* The following field value is number of the automaton to which
772 given unit belongs. */
773 int corresponding_automaton_num;
774 /* If the following value is not zero, the cpu unit is present in a
775 `exclusion_set' or in right part of a `presence_set',
776 `final_presence_set', `absence_set', and
777 `final_absence_set'define_query_cpu_unit. */
778 char in_set_p;
781 /* This describes define_bypass (see file rtl.def). */
782 struct bypass_decl
784 int latency;
785 char *out_insn_name;
786 char *in_insn_name;
787 char *bypass_guard_name;
789 /* The following fields are defined by checker. */
791 /* output and input insns of given bypass. */
792 struct insn_reserv_decl *out_insn_reserv;
793 struct insn_reserv_decl *in_insn_reserv;
794 /* The next bypass for given output insn. */
795 struct bypass_decl *next;
798 /* This describes define_automaton (see file rtl.def). */
799 struct automaton_decl
801 char *name;
803 /* The following fields are defined by automaton generator. */
805 /* The following field value is nonzero if the automaton is used in
806 an regexp definition. */
807 char automaton_is_used;
809 /* The following fields are defined by checker. */
811 /* The following field value is the corresponding automaton. This
812 field is not NULL only if the automaton is present in unit
813 declarations and the automatic partition on automata is not
814 used. */
815 automaton_t corresponding_automaton;
818 /* This describes exclusion relations: exclusion_set (see file
819 rtl.def). */
820 struct excl_rel_decl
822 int all_names_num;
823 int first_list_length;
824 char *names [1];
827 /* This describes unit relations: [final_]presence_set or
828 [final_]absence_set (see file rtl.def). */
829 struct unit_pattern_rel_decl
831 int final_p;
832 int names_num;
833 int patterns_num;
834 char **names;
835 char ***patterns;
838 /* This describes define_reservation (see file rtl.def). */
839 struct reserv_decl
841 char *name;
842 regexp_t regexp;
844 /* The following fields are defined by checker. */
846 /* The following field value is nonzero if the unit is used in an
847 regexp. */
848 char reserv_is_used;
849 /* The following field is used to check up cycle in expression
850 definition. */
851 int loop_pass_num;
854 /* This describes define_insn_reservation (see file rtl.def). */
855 struct insn_reserv_decl
857 rtx condexp;
858 int default_latency;
859 regexp_t regexp;
860 char *name;
862 /* The following fields are defined by checker. */
864 /* The following field value is order number (0, 1, ...) of given
865 insn. */
866 int insn_num;
867 /* The following field value is list of bypasses in which given insn
868 is output insn. */
869 struct bypass_decl *bypass_list;
871 /* The following fields are defined by automaton generator. */
873 /* The following field is the insn regexp transformed that
874 the regexp has not optional regexp, repetition regexp, and an
875 reservation name (i.e. reservation identifiers are changed by the
876 corresponding regexp) and all alternations are the topest level
877 of the regexp. The value can be NULL only if it is special
878 insn `cycle advancing'. */
879 regexp_t transformed_regexp;
880 /* The following field value is list of arcs marked given
881 insn. The field is used in transformation NDFA -> DFA. */
882 arc_t arcs_marked_by_insn;
883 /* The two following fields are used during minimization of a finite state
884 automaton. */
885 /* The field value is number of equivalence class of state into
886 which arc marked by given insn enters from a state (fixed during
887 an automaton minimization). */
888 int equiv_class_num;
889 /* The field value is state_alts of arc leaving a state (fixed
890 during an automaton minimization) and marked by given insn
891 enters. */
892 int state_alts;
893 /* The following member value is the list to automata which can be
894 changed by the insn issue. */
895 automata_list_el_t important_automata_list;
896 /* The following member is used to process insn once for output. */
897 int processed_p;
900 /* This contains a declaration mentioned above. */
901 struct decl
903 /* What node in the union? */
904 enum decl_mode mode;
905 pos_t pos;
906 union
908 struct unit_decl unit;
909 struct bypass_decl bypass;
910 struct automaton_decl automaton;
911 struct excl_rel_decl excl;
912 struct unit_pattern_rel_decl presence;
913 struct unit_pattern_rel_decl absence;
914 struct reserv_decl reserv;
915 struct insn_reserv_decl insn_reserv;
916 } decl;
919 /* The following structures represent parsed reservation strings. */
920 enum regexp_mode
922 rm_unit,
923 rm_reserv,
924 rm_nothing,
925 rm_sequence,
926 rm_repeat,
927 rm_allof,
928 rm_oneof
931 /* Cpu unit in reservation. */
932 struct unit_regexp
934 char *name;
935 unit_decl_t unit_decl;
938 /* Define_reservation in a reservation. */
939 struct reserv_regexp
941 char *name;
942 struct reserv_decl *reserv_decl;
945 /* Absence of reservation (represented by string `nothing'). */
946 struct nothing_regexp
948 /* This used to be empty but ISO C doesn't allow that. */
949 char unused;
952 /* Representation of reservations separated by ',' (see file
953 rtl.def). */
954 struct sequence_regexp
956 int regexps_num;
957 regexp_t regexps [1];
960 /* Representation of construction `repeat' (see file rtl.def). */
961 struct repeat_regexp
963 int repeat_num;
964 regexp_t regexp;
967 /* Representation of reservations separated by '+' (see file
968 rtl.def). */
969 struct allof_regexp
971 int regexps_num;
972 regexp_t regexps [1];
975 /* Representation of reservations separated by '|' (see file
976 rtl.def). */
977 struct oneof_regexp
979 int regexps_num;
980 regexp_t regexps [1];
983 /* Representation of a reservation string. */
984 struct regexp
986 /* What node in the union? */
987 enum regexp_mode mode;
988 pos_t pos;
989 union
991 struct unit_regexp unit;
992 struct reserv_regexp reserv;
993 struct nothing_regexp nothing;
994 struct sequence_regexp sequence;
995 struct repeat_regexp repeat;
996 struct allof_regexp allof;
997 struct oneof_regexp oneof;
998 } regexp;
1001 /* Represents description of pipeline hazard description based on
1002 NDFA. */
1003 struct description
1005 int decls_num;
1007 /* The following fields are defined by checker. */
1009 /* The following fields values are correspondingly number of all
1010 units, query units, and insns in the description. */
1011 int units_num;
1012 int query_units_num;
1013 int insns_num;
1014 /* The following field value is max length (in cycles) of
1015 reservations of insns. The field value is defined only for
1016 correct programs. */
1017 int max_insn_reserv_cycles;
1019 /* The following fields are defined by automaton generator. */
1021 /* The following field value is the first automaton. */
1022 automaton_t first_automaton;
1024 /* The following field is created by pipeline hazard parser and
1025 contains all declarations. We allocate additional entry for
1026 special insn "cycle advancing" which is added by the automaton
1027 generator. */
1028 decl_t decls [1];
1032 /* The following nodes are created in automaton checker. */
1034 /* The following nodes represent exclusion set for cpu units. Each
1035 element is accessed through only one excl_list. */
1036 struct unit_set_el
1038 unit_decl_t unit_decl;
1039 unit_set_el_t next_unit_set_el;
1042 /* The following nodes represent presence or absence pattern for cpu
1043 units. Each element is accessed through only one presence_list or
1044 absence_list. */
1045 struct pattern_set_el
1047 /* The number of units in unit_decls. */
1048 int units_num;
1049 /* The units forming the pattern. */
1050 struct unit_decl **unit_decls;
1051 pattern_set_el_t next_pattern_set_el;
1055 /* The following nodes are created in automaton generator. */
1058 /* The following nodes represent presence or absence pattern for cpu
1059 units. Each element is accessed through only one element of
1060 unit_presence_set_table or unit_absence_set_table. */
1061 struct pattern_reserv
1063 reserv_sets_t reserv;
1064 pattern_reserv_t next_pattern_reserv;
1067 /* The following node type describes state automaton. The state may
1068 be deterministic or non-deterministic. Non-deterministic state has
1069 several component states which represent alternative cpu units
1070 reservations. The state also is used for describing a
1071 deterministic reservation of automaton insn. */
1072 struct state
1074 /* The following member value is nonzero if there is a transition by
1075 cycle advancing. */
1076 int new_cycle_p;
1077 /* The following field is list of processor unit reservations on
1078 each cycle. */
1079 reserv_sets_t reservs;
1080 /* The following field is unique number of given state between other
1081 states. */
1082 int unique_num;
1083 /* The following field value is automaton to which given state
1084 belongs. */
1085 automaton_t automaton;
1086 /* The following field value is the first arc output from given
1087 state. */
1088 arc_t first_out_arc;
1089 /* The following field is used to form NDFA. */
1090 char it_was_placed_in_stack_for_NDFA_forming;
1091 /* The following field is used to form DFA. */
1092 char it_was_placed_in_stack_for_DFA_forming;
1093 /* The following field is used to transform NDFA to DFA and DFA
1094 minimization. The field value is not NULL if the state is a
1095 compound state. In this case the value of field `unit_sets_list'
1096 is NULL. All states in the list are in the hash table. The list
1097 is formed through field `next_sorted_alt_state'. We should
1098 support only one level of nesting state. */
1099 alt_state_t component_states;
1100 /* The following field is used for passing graph of states. */
1101 int pass_num;
1102 /* The list of states belonging to one equivalence class is formed
1103 with the aid of the following field. */
1104 state_t next_equiv_class_state;
1105 /* The two following fields are used during minimization of a finite
1106 state automaton. */
1107 int equiv_class_num_1, equiv_class_num_2;
1108 /* The following field is used during minimization of a finite state
1109 automaton. The field value is state corresponding to equivalence
1110 class to which given state belongs. */
1111 state_t equiv_class_state;
1112 /* The following field value is the order number of given state.
1113 The states in final DFA is enumerated with the aid of the
1114 following field. */
1115 int order_state_num;
1116 /* This member is used for passing states for searching minimal
1117 delay time. */
1118 int state_pass_num;
1119 /* The following member is used to evaluate min issue delay of insn
1120 for a state. */
1121 int min_insn_issue_delay;
1122 /* The following member is used to evaluate max issue rate of the
1123 processor. The value of the member is maximal length of the path
1124 from given state no containing arcs marked by special insn `cycle
1125 advancing'. */
1126 int longest_path_length;
1129 /* The following macro is an initial value of member
1130 `longest_path_length' of a state. */
1131 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1133 /* Automaton arc. */
1134 struct arc
1136 /* The following field refers for the state into which given arc
1137 enters. */
1138 state_t to_state;
1139 /* The following field describes that the insn issue (with cycle
1140 advancing for special insn `cycle advancing' and without cycle
1141 advancing for others) makes transition from given state to
1142 another given state. */
1143 ainsn_t insn;
1144 /* The following field value is the next arc output from the same
1145 state. */
1146 arc_t next_out_arc;
1147 /* List of arcs marked given insn is formed with the following
1148 field. The field is used in transformation NDFA -> DFA. */
1149 arc_t next_arc_marked_by_insn;
1150 /* The following field is defined if NDFA_FLAG is zero. The member
1151 value is number of alternative reservations which can be used for
1152 transition for given state by given insn. */
1153 int state_alts;
1156 /* The following node type describes a deterministic alternative in
1157 non-deterministic state which characterizes cpu unit reservations
1158 of automaton insn or which is part of NDFA. */
1159 struct alt_state
1161 /* The following field is a deterministic state which characterizes
1162 unit reservations of the instruction. */
1163 state_t state;
1164 /* The following field refers to the next state which characterizes
1165 unit reservations of the instruction. */
1166 alt_state_t next_alt_state;
1167 /* The following field refers to the next state in sorted list. */
1168 alt_state_t next_sorted_alt_state;
1171 /* The following node type describes insn of automaton. They are
1172 labels of FA arcs. */
1173 struct ainsn
1175 /* The following field value is the corresponding insn declaration
1176 of description. */
1177 struct insn_reserv_decl *insn_reserv_decl;
1178 /* The following field value is the next insn declaration for an
1179 automaton. */
1180 ainsn_t next_ainsn;
1181 /* The following field is states which characterize automaton unit
1182 reservations of the instruction. The value can be NULL only if it
1183 is special insn `cycle advancing'. */
1184 alt_state_t alt_states;
1185 /* The following field is sorted list of states which characterize
1186 automaton unit reservations of the instruction. The value can be
1187 NULL only if it is special insn `cycle advancing'. */
1188 alt_state_t sorted_alt_states;
1189 /* The following field refers the next automaton insn with
1190 the same reservations. */
1191 ainsn_t next_same_reservs_insn;
1192 /* The following field is flag of the first automaton insn with the
1193 same reservations in the declaration list. Only arcs marked such
1194 insn is present in the automaton. This significantly decreases
1195 memory requirements especially when several automata are
1196 formed. */
1197 char first_insn_with_same_reservs;
1198 /* The following member has nonzero value if there is arc from state of
1199 the automaton marked by the ainsn. */
1200 char arc_exists_p;
1201 /* Cyclic list of insns of an equivalence class is formed with the
1202 aid of the following field. */
1203 ainsn_t next_equiv_class_insn;
1204 /* The following field value is nonzero if the insn declaration is
1205 the first insn declaration with given equivalence number. */
1206 char first_ainsn_with_given_equialence_num;
1207 /* The following field is number of class of equivalence of insns.
1208 It is necessary because many insns may be equivalent with the
1209 point of view of pipeline hazards. */
1210 int insn_equiv_class_num;
1211 /* The following member value is TRUE if there is an arc in the
1212 automaton marked by the insn into another state. In other
1213 words, the insn can change the state of the automaton. */
1214 int important_p;
1217 /* The following describes an automaton for PHR. */
1218 struct automaton
1220 /* The following field value is the list of insn declarations for
1221 given automaton. */
1222 ainsn_t ainsn_list;
1223 /* The following field value is the corresponding automaton
1224 declaration. This field is not NULL only if the automatic
1225 partition on automata is not used. */
1226 struct automaton_decl *corresponding_automaton_decl;
1227 /* The following field value is the next automaton. */
1228 automaton_t next_automaton;
1229 /* The following field is start state of FA. There are not unit
1230 reservations in the state. */
1231 state_t start_state;
1232 /* The following field value is number of equivalence classes of
1233 insns (see field `insn_equiv_class_num' in
1234 `insn_reserv_decl'). */
1235 int insn_equiv_classes_num;
1236 /* The following field value is number of states of final DFA. */
1237 int achieved_states_num;
1238 /* The following field value is the order number (0, 1, ...) of
1239 given automaton. */
1240 int automaton_order_num;
1241 /* The following fields contain statistics information about
1242 building automaton. */
1243 int NDFA_states_num, DFA_states_num;
1244 /* The following field value is defined only if minimization of DFA
1245 is used. */
1246 int minimal_DFA_states_num;
1247 int NDFA_arcs_num, DFA_arcs_num;
1248 /* The following field value is defined only if minimization of DFA
1249 is used. */
1250 int minimal_DFA_arcs_num;
1251 /* The following two members refer for two table state x ainsn ->
1252 int. */
1253 state_ainsn_table_t trans_table;
1254 state_ainsn_table_t state_alts_table;
1255 /* The following member value is maximal value of min issue delay
1256 for insns of the automaton. */
1257 int max_min_delay;
1258 /* Usually min issue delay is small and we can place several (2, 4,
1259 8) elements in one vector element. So the compression factor can
1260 be 1 (no compression), 2, 4, 8. */
1261 int min_issue_delay_table_compression_factor;
1264 /* The following is the element of the list of automata. */
1265 struct automata_list_el
1267 /* The automaton itself. */
1268 automaton_t automaton;
1269 /* The next automata set element. */
1270 automata_list_el_t next_automata_list_el;
1273 /* The following structure describes a table state X ainsn -> int(>= 0). */
1274 struct state_ainsn_table
1276 /* Automaton to which given table belongs. */
1277 automaton_t automaton;
1278 /* The following tree vectors for comb vector implementation of the
1279 table. */
1280 vla_hwint_t comb_vect;
1281 vla_hwint_t check_vect;
1282 vla_hwint_t base_vect;
1283 /* This is simple implementation of the table. */
1284 vla_hwint_t full_vect;
1285 /* Minimal and maximal values of the previous vectors. */
1286 int min_comb_vect_el_value, max_comb_vect_el_value;
1287 int min_base_vect_el_value, max_base_vect_el_value;
1290 /* Macros to access members of unions. Use only them for access to
1291 union members of declarations and regexps. */
1293 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1295 #define DECL_UNIT(d) __extension__ \
1296 (({ struct decl *const _decl = (d); \
1297 if (_decl->mode != dm_unit) \
1298 decl_mode_check_failed (_decl->mode, "dm_unit", \
1299 __FILE__, __LINE__, __FUNCTION__); \
1300 &(_decl)->decl.unit; }))
1302 #define DECL_BYPASS(d) __extension__ \
1303 (({ struct decl *const _decl = (d); \
1304 if (_decl->mode != dm_bypass) \
1305 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1306 __FILE__, __LINE__, __FUNCTION__); \
1307 &(_decl)->decl.bypass; }))
1309 #define DECL_AUTOMATON(d) __extension__ \
1310 (({ struct decl *const _decl = (d); \
1311 if (_decl->mode != dm_automaton) \
1312 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1313 __FILE__, __LINE__, __FUNCTION__); \
1314 &(_decl)->decl.automaton; }))
1316 #define DECL_EXCL(d) __extension__ \
1317 (({ struct decl *const _decl = (d); \
1318 if (_decl->mode != dm_excl) \
1319 decl_mode_check_failed (_decl->mode, "dm_excl", \
1320 __FILE__, __LINE__, __FUNCTION__); \
1321 &(_decl)->decl.excl; }))
1323 #define DECL_PRESENCE(d) __extension__ \
1324 (({ struct decl *const _decl = (d); \
1325 if (_decl->mode != dm_presence) \
1326 decl_mode_check_failed (_decl->mode, "dm_presence", \
1327 __FILE__, __LINE__, __FUNCTION__); \
1328 &(_decl)->decl.presence; }))
1330 #define DECL_ABSENCE(d) __extension__ \
1331 (({ struct decl *const _decl = (d); \
1332 if (_decl->mode != dm_absence) \
1333 decl_mode_check_failed (_decl->mode, "dm_absence", \
1334 __FILE__, __LINE__, __FUNCTION__); \
1335 &(_decl)->decl.absence; }))
1337 #define DECL_RESERV(d) __extension__ \
1338 (({ struct decl *const _decl = (d); \
1339 if (_decl->mode != dm_reserv) \
1340 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1341 __FILE__, __LINE__, __FUNCTION__); \
1342 &(_decl)->decl.reserv; }))
1344 #define DECL_INSN_RESERV(d) __extension__ \
1345 (({ struct decl *const _decl = (d); \
1346 if (_decl->mode != dm_insn_reserv) \
1347 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1348 __FILE__, __LINE__, __FUNCTION__); \
1349 &(_decl)->decl.insn_reserv; }))
1351 static const char *decl_name PARAMS ((enum decl_mode));
1352 static void decl_mode_check_failed PARAMS ((enum decl_mode, const char *,
1353 const char *, int, const char *));
1355 /* Return string representation of declaration mode MODE. */
1356 static const char *
1357 decl_name (mode)
1358 enum decl_mode mode;
1360 static char str [100];
1362 if (mode == dm_unit)
1363 return "dm_unit";
1364 else if (mode == dm_bypass)
1365 return "dm_bypass";
1366 else if (mode == dm_automaton)
1367 return "dm_automaton";
1368 else if (mode == dm_excl)
1369 return "dm_excl";
1370 else if (mode == dm_presence)
1371 return "dm_presence";
1372 else if (mode == dm_absence)
1373 return "dm_absence";
1374 else if (mode == dm_reserv)
1375 return "dm_reserv";
1376 else if (mode == dm_insn_reserv)
1377 return "dm_insn_reserv";
1378 else
1379 sprintf (str, "unknown (%d)", (int) mode);
1380 return str;
1383 /* The function prints message about unexpected declaration and finish
1384 the program. */
1385 static void
1386 decl_mode_check_failed (mode, expected_mode_str, file, line, func)
1387 enum decl_mode mode;
1388 const char *expected_mode_str;
1389 const char *file;
1390 int line;
1391 const char *func;
1393 fprintf
1394 (stderr,
1395 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1396 file, line, func, expected_mode_str, decl_name (mode));
1397 exit (1);
1401 #define REGEXP_UNIT(r) __extension__ \
1402 (({ struct regexp *const _regexp = (r); \
1403 if (_regexp->mode != rm_unit) \
1404 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1405 __FILE__, __LINE__, __FUNCTION__); \
1406 &(_regexp)->regexp.unit; }))
1408 #define REGEXP_RESERV(r) __extension__ \
1409 (({ struct regexp *const _regexp = (r); \
1410 if (_regexp->mode != rm_reserv) \
1411 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1412 __FILE__, __LINE__, __FUNCTION__); \
1413 &(_regexp)->regexp.reserv; }))
1415 #define REGEXP_SEQUENCE(r) __extension__ \
1416 (({ struct regexp *const _regexp = (r); \
1417 if (_regexp->mode != rm_sequence) \
1418 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1419 __FILE__, __LINE__, __FUNCTION__); \
1420 &(_regexp)->regexp.sequence; }))
1422 #define REGEXP_REPEAT(r) __extension__ \
1423 (({ struct regexp *const _regexp = (r); \
1424 if (_regexp->mode != rm_repeat) \
1425 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1426 __FILE__, __LINE__, __FUNCTION__); \
1427 &(_regexp)->regexp.repeat; }))
1429 #define REGEXP_ALLOF(r) __extension__ \
1430 (({ struct regexp *const _regexp = (r); \
1431 if (_regexp->mode != rm_allof) \
1432 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1433 __FILE__, __LINE__, __FUNCTION__); \
1434 &(_regexp)->regexp.allof; }))
1436 #define REGEXP_ONEOF(r) __extension__ \
1437 (({ struct regexp *const _regexp = (r); \
1438 if (_regexp->mode != rm_oneof) \
1439 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1440 __FILE__, __LINE__, __FUNCTION__); \
1441 &(_regexp)->regexp.oneof; }))
1443 static const char *regexp_name PARAMS ((enum regexp_mode));
1444 static void regexp_mode_check_failed PARAMS ((enum regexp_mode, const char *,
1445 const char *, int,
1446 const char *));
1449 /* Return string representation of regexp mode MODE. */
1450 static const char *
1451 regexp_name (mode)
1452 enum regexp_mode mode;
1454 static char str [100];
1456 if (mode == rm_unit)
1457 return "rm_unit";
1458 else if (mode == rm_reserv)
1459 return "rm_reserv";
1460 else if (mode == rm_nothing)
1461 return "rm_nothing";
1462 else if (mode == rm_sequence)
1463 return "rm_sequence";
1464 else if (mode == rm_repeat)
1465 return "rm_repeat";
1466 else if (mode == rm_allof)
1467 return "rm_allof";
1468 else if (mode == rm_oneof)
1469 return "rm_oneof";
1470 else
1471 sprintf (str, "unknown (%d)", (int) mode);
1472 return str;
1475 /* The function prints message about unexpected regexp and finish the
1476 program. */
1477 static void
1478 regexp_mode_check_failed (mode, expected_mode_str, file, line, func)
1479 enum regexp_mode mode;
1480 const char *expected_mode_str;
1481 const char *file;
1482 int line;
1483 const char *func;
1485 fprintf
1486 (stderr,
1487 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1488 file, line, func, expected_mode_str, regexp_name (mode));
1489 exit (1);
1492 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1494 #define DECL_UNIT(d) (&(d)->decl.unit)
1495 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1496 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1497 #define DECL_EXCL(d) (&(d)->decl.excl)
1498 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1499 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1500 #define DECL_RESERV(d) (&(d)->decl.reserv)
1501 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1503 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1504 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1505 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1506 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1507 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1508 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1510 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1512 /* Create IR structure (node). */
1513 static void *
1514 create_node (size)
1515 size_t size;
1517 void *result;
1519 obstack_blank (&irp, size);
1520 result = obstack_base (&irp);
1521 obstack_finish (&irp);
1522 /* Default values of members are NULL and zero. */
1523 memset (result, 0, size);
1524 return result;
1527 /* Copy IR structure (node). */
1528 static void *
1529 copy_node (from, size)
1530 const void *from;
1531 size_t size;
1533 void *const result = create_node (size);
1534 memcpy (result, from, size);
1535 return result;
1538 /* The function checks that NAME does not contain quotes (`"'). */
1539 static char *
1540 check_name (name, pos)
1541 char * name;
1542 pos_t pos ATTRIBUTE_UNUSED;
1544 const char *str;
1546 for (str = name; *str != '\0'; str++)
1547 if (*str == '\"')
1548 error ("Name `%s' contains quotes", name);
1549 return name;
1552 /* Pointers to all declarations during IR generation are stored in the
1553 following. */
1554 static vla_ptr_t decls;
1556 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1557 string containing the next separated element, taking parentheses
1558 into account if PAR_FLAG has nonzero value. Advance the pointer to
1559 after the string scanned, or the end-of-string. Return NULL if at
1560 end of string. */
1561 static char *
1562 next_sep_el (pstr, sep, par_flag)
1563 char **pstr;
1564 int sep;
1565 int par_flag;
1567 char *out_str;
1568 char *p;
1569 int pars_num;
1570 int n_spaces;
1572 /* Remove leading whitespaces. */
1573 while (ISSPACE ((int) **pstr))
1574 (*pstr)++;
1576 if (**pstr == '\0')
1577 return NULL;
1579 n_spaces = 0;
1580 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1582 if (par_flag && *p == '(')
1583 pars_num++;
1584 else if (par_flag && *p == ')')
1585 pars_num--;
1586 else if (pars_num == 0 && *p == sep)
1587 break;
1588 if (pars_num == 0 && ISSPACE ((int) *p))
1589 n_spaces++;
1590 else
1592 for (; n_spaces != 0; n_spaces--)
1593 obstack_1grow (&irp, p [-n_spaces]);
1594 obstack_1grow (&irp, *p);
1597 obstack_1grow (&irp, '\0');
1598 out_str = obstack_base (&irp);
1599 obstack_finish (&irp);
1601 *pstr = p;
1602 if (**pstr == sep)
1603 (*pstr)++;
1605 return out_str;
1608 /* Given a string and a separator, return the number of separated
1609 elements in it, taking parentheses into account if PAR_FLAG has
1610 nonzero value. Return 0 for the null string, -1 if parentheses is
1611 not balanced. */
1612 static int
1613 n_sep_els (s, sep, par_flag)
1614 char *s;
1615 int sep;
1616 int par_flag;
1618 int n;
1619 int pars_num;
1621 if (*s == '\0')
1622 return 0;
1624 for (pars_num = 0, n = 1; *s; s++)
1625 if (par_flag && *s == '(')
1626 pars_num++;
1627 else if (par_flag && *s == ')')
1628 pars_num--;
1629 else if (pars_num == 0 && *s == sep)
1630 n++;
1632 return (pars_num != 0 ? -1 : n);
1635 /* Given a string and a separator, return vector of strings which are
1636 elements in the string and number of elements through els_num.
1637 Take parentheses into account if PAREN_P has nonzero value. The
1638 function also inserts the end marker NULL at the end of vector.
1639 Return 0 for the null string, -1 if parantheses are not balanced. */
1640 static char **
1641 get_str_vect (str, els_num, sep, paren_p)
1642 char *str;
1643 int *els_num;
1644 int sep;
1645 int paren_p;
1647 int i;
1648 char **vect;
1649 char **pstr;
1651 *els_num = n_sep_els (str, sep, paren_p);
1652 if (*els_num <= 0)
1653 return NULL;
1654 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1655 vect = (char **) obstack_base (&irp);
1656 obstack_finish (&irp);
1657 pstr = &str;
1658 for (i = 0; i < *els_num; i++)
1659 vect [i] = next_sep_el (pstr, sep, paren_p);
1660 if (next_sep_el (pstr, sep, paren_p) != NULL)
1661 abort ();
1662 vect [i] = NULL;
1663 return vect;
1666 /* Process a DEFINE_CPU_UNIT.
1668 This gives information about a unit contained in CPU. We fill a
1669 struct unit_decl with information used later by `expand_automata'. */
1670 void
1671 gen_cpu_unit (def)
1672 rtx def;
1674 decl_t decl;
1675 char **str_cpu_units;
1676 int vect_length;
1677 int i;
1679 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1680 FALSE);
1681 if (str_cpu_units == NULL)
1682 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1683 for (i = 0; i < vect_length; i++)
1685 decl = create_node (sizeof (struct decl));
1686 decl->mode = dm_unit;
1687 decl->pos = 0;
1688 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1689 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1690 DECL_UNIT (decl)->query_p = 0;
1691 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1692 DECL_UNIT (decl)->in_set_p = 0;
1693 VLA_PTR_ADD (decls, decl);
1694 num_dfa_decls++;
1698 /* Process a DEFINE_QUERY_CPU_UNIT.
1700 This gives information about a unit contained in CPU. We fill a
1701 struct unit_decl with information used later by `expand_automata'. */
1702 void
1703 gen_query_cpu_unit (def)
1704 rtx def;
1706 decl_t decl;
1707 char **str_cpu_units;
1708 int vect_length;
1709 int i;
1711 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1712 FALSE);
1713 if (str_cpu_units == NULL)
1714 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1715 for (i = 0; i < vect_length; i++)
1717 decl = create_node (sizeof (struct decl));
1718 decl->mode = dm_unit;
1719 decl->pos = 0;
1720 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1721 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1722 DECL_UNIT (decl)->query_p = 1;
1723 VLA_PTR_ADD (decls, decl);
1724 num_dfa_decls++;
1728 /* Process a DEFINE_BYPASS.
1730 This gives information about a unit contained in the CPU. We fill
1731 in a struct bypass_decl with information used later by
1732 `expand_automata'. */
1733 void
1734 gen_bypass (def)
1735 rtx def;
1737 decl_t decl;
1738 char **out_insns;
1739 int out_length;
1740 char **in_insns;
1741 int in_length;
1742 int i, j;
1744 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', FALSE);
1745 if (out_insns == NULL)
1746 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1747 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', FALSE);
1748 if (in_insns == NULL)
1749 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1750 for (i = 0; i < out_length; i++)
1751 for (j = 0; j < in_length; j++)
1753 decl = create_node (sizeof (struct decl));
1754 decl->mode = dm_bypass;
1755 decl->pos = 0;
1756 DECL_BYPASS (decl)->latency = XINT (def, 0);
1757 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1758 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1759 DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
1760 VLA_PTR_ADD (decls, decl);
1761 num_dfa_decls++;
1765 /* Process an EXCLUSION_SET.
1767 This gives information about a cpu unit conflicts. We fill a
1768 struct excl_rel_decl (excl) with information used later by
1769 `expand_automata'. */
1770 void
1771 gen_excl_set (def)
1772 rtx def;
1774 decl_t decl;
1775 char **first_str_cpu_units;
1776 char **second_str_cpu_units;
1777 int first_vect_length;
1778 int length;
1779 int i;
1781 first_str_cpu_units
1782 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', FALSE);
1783 if (first_str_cpu_units == NULL)
1784 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1785 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1786 FALSE);
1787 if (second_str_cpu_units == NULL)
1788 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1789 length += first_vect_length;
1790 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1791 decl->mode = dm_excl;
1792 decl->pos = 0;
1793 DECL_EXCL (decl)->all_names_num = length;
1794 DECL_EXCL (decl)->first_list_length = first_vect_length;
1795 for (i = 0; i < length; i++)
1796 if (i < first_vect_length)
1797 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1798 else
1799 DECL_EXCL (decl)->names [i]
1800 = second_str_cpu_units [i - first_vect_length];
1801 VLA_PTR_ADD (decls, decl);
1802 num_dfa_decls++;
1805 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1806 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1808 This gives information about a cpu unit reservation requirements.
1809 We fill a struct unit_pattern_rel_decl with information used later
1810 by `expand_automata'. */
1811 static void
1812 gen_presence_absence_set (def, presence_p, final_p)
1813 rtx def;
1814 int presence_p;
1815 int final_p;
1817 decl_t decl;
1818 char **str_cpu_units;
1819 char ***str_patterns;
1820 int cpu_units_length;
1821 int length;
1822 int patterns_length;
1823 int i;
1825 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &cpu_units_length, ',',
1826 FALSE);
1827 if (str_cpu_units == NULL)
1828 fatal ((presence_p
1829 ? (final_p
1830 ? "invalid first string `%s' in final_presence_set"
1831 : "invalid first string `%s' in presence_set")
1832 : (final_p
1833 ? "invalid first string `%s' in final_absence_set"
1834 : "invalid first string `%s' in absence_set")),
1835 XSTR (def, 0));
1836 str_patterns = (char ***) get_str_vect ((char *) XSTR (def, 1),
1837 &patterns_length, ',', FALSE);
1838 if (str_patterns == NULL)
1839 fatal ((presence_p
1840 ? (final_p
1841 ? "invalid second string `%s' in final_presence_set"
1842 : "invalid second string `%s' in presence_set")
1843 : (final_p
1844 ? "invalid second string `%s' in final_absence_set"
1845 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1846 for (i = 0; i < patterns_length; i++)
1848 str_patterns [i] = get_str_vect ((char *) str_patterns [i], &length, ' ',
1849 FALSE);
1850 if (str_patterns [i] == NULL)
1851 abort ();
1853 decl = create_node (sizeof (struct decl));
1854 decl->pos = 0;
1855 if (presence_p)
1857 decl->mode = dm_presence;
1858 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1859 DECL_PRESENCE (decl)->names = str_cpu_units;
1860 DECL_PRESENCE (decl)->patterns = str_patterns;
1861 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1862 DECL_PRESENCE (decl)->final_p = final_p;
1864 else
1866 decl->mode = dm_absence;
1867 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1868 DECL_ABSENCE (decl)->names = str_cpu_units;
1869 DECL_ABSENCE (decl)->patterns = str_patterns;
1870 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1871 DECL_ABSENCE (decl)->final_p = final_p;
1873 VLA_PTR_ADD (decls, decl);
1874 num_dfa_decls++;
1877 /* Process a PRESENCE_SET.
1879 This gives information about a cpu unit reservation requirements.
1880 We fill a struct unit_pattern_rel_decl (presence) with information
1881 used later by `expand_automata'. */
1882 void
1883 gen_presence_set (def)
1884 rtx def;
1886 gen_presence_absence_set (def, TRUE, FALSE);
1889 /* Process a FINAL_PRESENCE_SET.
1891 This gives information about a cpu unit reservation requirements.
1892 We fill a struct unit_pattern_rel_decl (presence) with information
1893 used later by `expand_automata'. */
1894 void
1895 gen_final_presence_set (def)
1896 rtx def;
1898 gen_presence_absence_set (def, TRUE, TRUE);
1901 /* Process an ABSENCE_SET.
1903 This gives information about a cpu unit reservation requirements.
1904 We fill a struct unit_pattern_rel_decl (absence) with information
1905 used later by `expand_automata'. */
1906 void
1907 gen_absence_set (def)
1908 rtx def;
1910 gen_presence_absence_set (def, FALSE, FALSE);
1913 /* Process a FINAL_ABSENCE_SET.
1915 This gives information about a cpu unit reservation requirements.
1916 We fill a struct unit_pattern_rel_decl (absence) with information
1917 used later by `expand_automata'. */
1918 void
1919 gen_final_absence_set (def)
1920 rtx def;
1922 gen_presence_absence_set (def, FALSE, TRUE);
1925 /* Process a DEFINE_AUTOMATON.
1927 This gives information about a finite state automaton used for
1928 recognizing pipeline hazards. We fill a struct automaton_decl
1929 with information used later by `expand_automata'. */
1930 void
1931 gen_automaton (def)
1932 rtx def;
1934 decl_t decl;
1935 char **str_automata;
1936 int vect_length;
1937 int i;
1939 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1940 FALSE);
1941 if (str_automata == NULL)
1942 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1943 for (i = 0; i < vect_length; i++)
1945 decl = create_node (sizeof (struct decl));
1946 decl->mode = dm_automaton;
1947 decl->pos = 0;
1948 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1949 VLA_PTR_ADD (decls, decl);
1950 num_dfa_decls++;
1954 /* Process an AUTOMATA_OPTION.
1956 This gives information how to generate finite state automaton used
1957 for recognizing pipeline hazards. */
1958 void
1959 gen_automata_option (def)
1960 rtx def;
1962 if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1963 no_minimization_flag = 1;
1964 else if (strcmp ((char *) XSTR (def, 0), TIME_OPTION + 1) == 0)
1965 time_flag = 1;
1966 else if (strcmp ((char *) XSTR (def, 0), V_OPTION + 1) == 0)
1967 v_flag = 1;
1968 else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
1969 w_flag = 1;
1970 else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
1971 ndfa_flag = 1;
1972 else
1973 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1976 /* Name in reservation to denote absence reservation. */
1977 #define NOTHING_NAME "nothing"
1979 /* The following string contains original reservation string being
1980 parsed. */
1981 static char *reserv_str;
1983 /* Parse an element in STR. */
1984 static regexp_t
1985 gen_regexp_el (str)
1986 char *str;
1988 regexp_t regexp;
1989 int len;
1991 if (*str == '(')
1993 len = strlen (str);
1994 if (str [len - 1] != ')')
1995 fatal ("garbage after ) in reservation `%s'", reserv_str);
1996 str [len - 1] = '\0';
1997 regexp = gen_regexp_sequence (str + 1);
1999 else if (strcmp (str, NOTHING_NAME) == 0)
2001 regexp = create_node (sizeof (struct decl));
2002 regexp->mode = rm_nothing;
2004 else
2006 regexp = create_node (sizeof (struct decl));
2007 regexp->mode = rm_unit;
2008 REGEXP_UNIT (regexp)->name = str;
2010 return regexp;
2013 /* Parse construction `repeat' in STR. */
2014 static regexp_t
2015 gen_regexp_repeat (str)
2016 char *str;
2018 regexp_t regexp;
2019 regexp_t repeat;
2020 char **repeat_vect;
2021 int els_num;
2022 int i;
2024 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
2025 if (repeat_vect == NULL)
2026 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2027 if (els_num > 1)
2029 regexp = gen_regexp_el (repeat_vect [0]);
2030 for (i = 1; i < els_num; i++)
2032 repeat = create_node (sizeof (struct regexp));
2033 repeat->mode = rm_repeat;
2034 REGEXP_REPEAT (repeat)->regexp = regexp;
2035 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
2036 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
2037 fatal ("repetition `%s' <= 1 in reservation `%s'",
2038 str, reserv_str);
2039 regexp = repeat;
2041 return regexp;
2043 else
2044 return gen_regexp_el (str);
2047 /* Parse reservation STR which possibly contains separator '+'. */
2048 static regexp_t
2049 gen_regexp_allof (str)
2050 char *str;
2052 regexp_t allof;
2053 char **allof_vect;
2054 int els_num;
2055 int i;
2057 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
2058 if (allof_vect == NULL)
2059 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2060 if (els_num > 1)
2062 allof = create_node (sizeof (struct regexp)
2063 + sizeof (regexp_t) * (els_num - 1));
2064 allof->mode = rm_allof;
2065 REGEXP_ALLOF (allof)->regexps_num = els_num;
2066 for (i = 0; i < els_num; i++)
2067 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
2068 return allof;
2070 else
2071 return gen_regexp_repeat (str);
2074 /* Parse reservation STR which possibly contains separator '|'. */
2075 static regexp_t
2076 gen_regexp_oneof (str)
2077 char *str;
2079 regexp_t oneof;
2080 char **oneof_vect;
2081 int els_num;
2082 int i;
2084 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
2085 if (oneof_vect == NULL)
2086 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2087 if (els_num > 1)
2089 oneof = create_node (sizeof (struct regexp)
2090 + sizeof (regexp_t) * (els_num - 1));
2091 oneof->mode = rm_oneof;
2092 REGEXP_ONEOF (oneof)->regexps_num = els_num;
2093 for (i = 0; i < els_num; i++)
2094 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
2095 return oneof;
2097 else
2098 return gen_regexp_allof (str);
2101 /* Parse reservation STR which possibly contains separator ','. */
2102 static regexp_t
2103 gen_regexp_sequence (str)
2104 char *str;
2106 regexp_t sequence;
2107 char **sequence_vect;
2108 int els_num;
2109 int i;
2111 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
2112 if (els_num > 1)
2114 sequence = create_node (sizeof (struct regexp)
2115 + sizeof (regexp_t) * (els_num - 1));
2116 sequence->mode = rm_sequence;
2117 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2118 for (i = 0; i < els_num; i++)
2119 REGEXP_SEQUENCE (sequence)->regexps [i]
2120 = gen_regexp_oneof (sequence_vect [i]);
2121 return sequence;
2123 else
2124 return gen_regexp_oneof (str);
2127 /* Parse construction reservation STR. */
2128 static regexp_t
2129 gen_regexp (str)
2130 char *str;
2132 reserv_str = str;
2133 return gen_regexp_sequence (str);;
2136 /* Process a DEFINE_RESERVATION.
2138 This gives information about a reservation of cpu units. We fill
2139 in a struct reserv_decl with information used later by
2140 `expand_automata'. */
2141 void
2142 gen_reserv (def)
2143 rtx def;
2145 decl_t decl;
2147 decl = create_node (sizeof (struct decl));
2148 decl->mode = dm_reserv;
2149 decl->pos = 0;
2150 DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2151 DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2152 VLA_PTR_ADD (decls, decl);
2153 num_dfa_decls++;
2156 /* Process a DEFINE_INSN_RESERVATION.
2158 This gives information about the reservation of cpu units by an
2159 insn. We fill a struct insn_reserv_decl with information used
2160 later by `expand_automata'. */
2161 void
2162 gen_insn_reserv (def)
2163 rtx def;
2165 decl_t decl;
2167 decl = create_node (sizeof (struct decl));
2168 decl->mode = dm_insn_reserv;
2169 decl->pos = 0;
2170 DECL_INSN_RESERV (decl)->name
2171 = check_name ((char *) XSTR (def, 0), decl->pos);
2172 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2173 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2174 DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2175 VLA_PTR_ADD (decls, decl);
2176 num_dfa_decls++;
2181 /* The function evaluates hash value (0..UINT_MAX) of string. */
2182 static unsigned
2183 string_hash (string)
2184 const char *string;
2186 unsigned result, i;
2188 for (result = i = 0;*string++ != '\0'; i++)
2189 result += ((unsigned char) *string << (i % CHAR_BIT));
2190 return result;
2195 /* This page contains abstract data `table of automaton declarations'.
2196 Elements of the table is nodes representing automaton declarations.
2197 Key of the table elements is name of given automaton. Remember
2198 that automaton names have own space. */
2200 /* The function evaluates hash value of an automaton declaration. The
2201 function is used by abstract data `hashtab'. The function returns
2202 hash value (0..UINT_MAX) of given automaton declaration. */
2203 static hashval_t
2204 automaton_decl_hash (automaton_decl)
2205 const void *automaton_decl;
2207 const decl_t decl = (decl_t) automaton_decl;
2209 if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
2210 abort ();
2211 return string_hash (DECL_AUTOMATON (decl)->name);
2214 /* The function tests automaton declarations on equality of their
2215 keys. The function is used by abstract data `hashtab'. The
2216 function returns 1 if the declarations have the same key, 0
2217 otherwise. */
2218 static int
2219 automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
2220 const void* automaton_decl_1;
2221 const void* automaton_decl_2;
2223 const decl_t decl1 = (decl_t) automaton_decl_1;
2224 const decl_t decl2 = (decl_t) automaton_decl_2;
2226 if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
2227 || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
2228 abort ();
2229 return strcmp (DECL_AUTOMATON (decl1)->name,
2230 DECL_AUTOMATON (decl2)->name) == 0;
2233 /* The automaton declaration table itself is represented by the
2234 following variable. */
2235 static htab_t automaton_decl_table;
2237 /* The function inserts automaton declaration into the table. The
2238 function does nothing if an automaton declaration with the same key
2239 exists already in the table. The function returns automaton
2240 declaration node in the table with the same key as given automaton
2241 declaration node. */
2242 static decl_t
2243 insert_automaton_decl (automaton_decl)
2244 decl_t automaton_decl;
2246 void **entry_ptr;
2248 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
2249 if (*entry_ptr == NULL)
2250 *entry_ptr = (void *) automaton_decl;
2251 return (decl_t) *entry_ptr;
2254 /* The following variable value is node representing automaton
2255 declaration. The node used for searching automaton declaration
2256 with given name. */
2257 static struct decl work_automaton_decl;
2259 /* The function searches for automaton declaration in the table with
2260 the same key as node representing name of the automaton
2261 declaration. The function returns node found in the table, NULL if
2262 such node does not exist in the table. */
2263 static decl_t
2264 find_automaton_decl (name)
2265 char *name;
2267 void *entry;
2269 work_automaton_decl.mode = dm_automaton;
2270 DECL_AUTOMATON (&work_automaton_decl)->name = name;
2271 entry = htab_find (automaton_decl_table, &work_automaton_decl);
2272 return (decl_t) entry;
2275 /* The function creates empty automaton declaration table and node
2276 representing automaton declaration and used for searching automaton
2277 declaration with given name. The function must be called only once
2278 before any work with the automaton declaration table. */
2279 static void
2280 initiate_automaton_decl_table ()
2282 work_automaton_decl.mode = dm_automaton;
2283 automaton_decl_table = htab_create (10, automaton_decl_hash,
2284 automaton_decl_eq_p, (htab_del) 0);
2287 /* The function deletes the automaton declaration table. Only call of
2288 function `initiate_automaton_decl_table' is possible immediately
2289 after this function call. */
2290 static void
2291 finish_automaton_decl_table ()
2293 htab_delete (automaton_decl_table);
2298 /* This page contains abstract data `table of insn declarations'.
2299 Elements of the table is nodes representing insn declarations. Key
2300 of the table elements is name of given insn (in corresponding
2301 define_insn_reservation). Remember that insn names have own
2302 space. */
2304 /* The function evaluates hash value of an insn declaration. The
2305 function is used by abstract data `hashtab'. The function returns
2306 hash value (0..UINT_MAX) of given insn declaration. */
2307 static hashval_t
2308 insn_decl_hash (insn_decl)
2309 const void *insn_decl;
2311 const decl_t decl = (decl_t) insn_decl;
2313 if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
2314 abort ();
2315 return string_hash (DECL_INSN_RESERV (decl)->name);
2318 /* The function tests insn declarations on equality of their keys.
2319 The function is used by abstract data `hashtab'. The function
2320 returns 1 if declarations have the same key, 0 otherwise. */
2321 static int
2322 insn_decl_eq_p (insn_decl_1, insn_decl_2)
2323 const void *insn_decl_1;
2324 const void *insn_decl_2;
2326 const decl_t decl1 = (decl_t) insn_decl_1;
2327 const decl_t decl2 = (decl_t) insn_decl_2;
2329 if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
2330 || decl2->mode != dm_insn_reserv
2331 || DECL_INSN_RESERV (decl2)->name == NULL)
2332 abort ();
2333 return strcmp (DECL_INSN_RESERV (decl1)->name,
2334 DECL_INSN_RESERV (decl2)->name) == 0;
2337 /* The insn declaration table itself is represented by the following
2338 variable. The table does not contain insn reservation
2339 declarations. */
2340 static htab_t insn_decl_table;
2342 /* The function inserts insn declaration into the table. The function
2343 does nothing if an insn declaration with the same key exists
2344 already in the table. The function returns insn declaration node
2345 in the table with the same key as given insn declaration node. */
2346 static decl_t
2347 insert_insn_decl (insn_decl)
2348 decl_t insn_decl;
2350 void **entry_ptr;
2352 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2353 if (*entry_ptr == NULL)
2354 *entry_ptr = (void *) insn_decl;
2355 return (decl_t) *entry_ptr;
2358 /* The following variable value is node representing insn reservation
2359 declaration. The node used for searching insn reservation
2360 declaration with given name. */
2361 static struct decl work_insn_decl;
2363 /* The function searches for insn reservation declaration in the table
2364 with the same key as node representing name of the insn reservation
2365 declaration. The function returns node found in the table, NULL if
2366 such node does not exist in the table. */
2367 static decl_t
2368 find_insn_decl (name)
2369 char *name;
2371 void *entry;
2373 work_insn_decl.mode = dm_insn_reserv;
2374 DECL_INSN_RESERV (&work_insn_decl)->name = name;
2375 entry = htab_find (insn_decl_table, &work_insn_decl);
2376 return (decl_t) entry;
2379 /* The function creates empty insn declaration table and node
2380 representing insn declaration and used for searching insn
2381 declaration with given name. The function must be called only once
2382 before any work with the insn declaration table. */
2383 static void
2384 initiate_insn_decl_table ()
2386 work_insn_decl.mode = dm_insn_reserv;
2387 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2388 (htab_del) 0);
2391 /* The function deletes the insn declaration table. Only call of
2392 function `initiate_insn_decl_table' is possible immediately after
2393 this function call. */
2394 static void
2395 finish_insn_decl_table ()
2397 htab_delete (insn_decl_table);
2402 /* This page contains abstract data `table of declarations'. Elements
2403 of the table is nodes representing declarations (of units and
2404 reservations). Key of the table elements is names of given
2405 declarations. */
2407 /* The function evaluates hash value of a declaration. The function
2408 is used by abstract data `hashtab'. The function returns hash
2409 value (0..UINT_MAX) of given declaration. */
2410 static hashval_t
2411 decl_hash (decl)
2412 const void *decl;
2414 const decl_t d = (const decl_t) decl;
2416 if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
2417 && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
2418 abort ();
2419 return string_hash (d->mode == dm_unit
2420 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
2423 /* The function tests declarations on equality of their keys. The
2424 function is used by abstract data `hashtab'. The function
2425 returns 1 if the declarations have the same key, 0 otherwise. */
2426 static int
2427 decl_eq_p (decl_1, decl_2)
2428 const void *decl_1;
2429 const void *decl_2;
2431 const decl_t d1 = (const decl_t) decl_1;
2432 const decl_t d2 = (const decl_t) decl_2;
2434 if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
2435 && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
2436 || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
2437 && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
2438 abort ();
2439 return strcmp ((d1->mode == dm_unit
2440 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
2441 (d2->mode == dm_unit
2442 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2445 /* The declaration table itself is represented by the following
2446 variable. */
2447 static htab_t decl_table;
2449 /* The function inserts declaration into the table. The function does
2450 nothing if a declaration with the same key exists already in the
2451 table. The function returns declaration node in the table with the
2452 same key as given declaration node. */
2454 static decl_t
2455 insert_decl (decl)
2456 decl_t decl;
2458 void **entry_ptr;
2460 entry_ptr = htab_find_slot (decl_table, decl, 1);
2461 if (*entry_ptr == NULL)
2462 *entry_ptr = (void *) decl;
2463 return (decl_t) *entry_ptr;
2466 /* The following variable value is node representing declaration. The
2467 node used for searching declaration with given name. */
2468 static struct decl work_decl;
2470 /* The function searches for declaration in the table with the same
2471 key as node representing name of the declaration. The function
2472 returns node found in the table, NULL if such node does not exist
2473 in the table. */
2474 static decl_t
2475 find_decl (name)
2476 char *name;
2478 void *entry;
2480 work_decl.mode = dm_unit;
2481 DECL_UNIT (&work_decl)->name = name;
2482 entry = htab_find (decl_table, &work_decl);
2483 return (decl_t) entry;
2486 /* The function creates empty declaration table and node representing
2487 declaration and used for searching declaration with given name.
2488 The function must be called only once before any work with the
2489 declaration table. */
2490 static void
2491 initiate_decl_table ()
2493 work_decl.mode = dm_unit;
2494 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2497 /* The function deletes the declaration table. Only call of function
2498 `initiate_declaration_table' is possible immediately after this
2499 function call. */
2500 static void
2501 finish_decl_table ()
2503 htab_delete (decl_table);
2508 /* This page contains checker of pipeline hazard description. */
2510 /* Checking NAMES in an exclusion clause vector and returning formed
2511 unit_set_el_list. */
2512 static unit_set_el_t
2513 process_excls (names, num, excl_pos)
2514 char **names;
2515 int num;
2516 pos_t excl_pos ATTRIBUTE_UNUSED;
2518 unit_set_el_t el_list;
2519 unit_set_el_t last_el;
2520 unit_set_el_t new_el;
2521 decl_t decl_in_table;
2522 int i;
2524 el_list = NULL;
2525 last_el = NULL;
2526 for (i = 0; i < num; i++)
2528 decl_in_table = find_decl (names [i]);
2529 if (decl_in_table == NULL)
2530 error ("unit `%s' in exclusion is not declared", names [i]);
2531 else if (decl_in_table->mode != dm_unit)
2532 error ("`%s' in exclusion is not unit", names [i]);
2533 else
2535 new_el = create_node (sizeof (struct unit_set_el));
2536 new_el->unit_decl = DECL_UNIT (decl_in_table);
2537 new_el->next_unit_set_el = NULL;
2538 if (last_el == NULL)
2539 el_list = last_el = new_el;
2540 else
2542 last_el->next_unit_set_el = new_el;
2543 last_el = last_el->next_unit_set_el;
2547 return el_list;
2550 /* The function adds each element from SOURCE_LIST to the exclusion
2551 list of the each element from DEST_LIST. Checking situation "unit
2552 excludes itself". */
2553 static void
2554 add_excls (dest_list, source_list, excl_pos)
2555 unit_set_el_t dest_list;
2556 unit_set_el_t source_list;
2557 pos_t excl_pos ATTRIBUTE_UNUSED;
2559 unit_set_el_t dst;
2560 unit_set_el_t src;
2561 unit_set_el_t curr_el;
2562 unit_set_el_t prev_el;
2563 unit_set_el_t copy;
2565 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2566 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2568 if (dst->unit_decl == src->unit_decl)
2570 error ("unit `%s' excludes itself", src->unit_decl->name);
2571 continue;
2573 if (dst->unit_decl->automaton_name != NULL
2574 && src->unit_decl->automaton_name != NULL
2575 && strcmp (dst->unit_decl->automaton_name,
2576 src->unit_decl->automaton_name) != 0)
2578 error ("units `%s' and `%s' in exclusion set belong to different automata",
2579 src->unit_decl->name, dst->unit_decl->name);
2580 continue;
2582 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2583 curr_el != NULL;
2584 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2585 if (curr_el->unit_decl == src->unit_decl)
2586 break;
2587 if (curr_el == NULL)
2589 /* Element not found - insert. */
2590 copy = copy_node (src, sizeof (*src));
2591 copy->next_unit_set_el = NULL;
2592 if (prev_el == NULL)
2593 dst->unit_decl->excl_list = copy;
2594 else
2595 prev_el->next_unit_set_el = copy;
2600 /* Checking NAMES in presence/absence clause and returning the
2601 formed unit_set_el_list. The function is called only after
2602 processing all exclusion sets. */
2603 static unit_set_el_t
2604 process_presence_absence_names (names, num, req_pos, presence_p, final_p)
2605 char **names;
2606 int num;
2607 pos_t req_pos ATTRIBUTE_UNUSED;
2608 int presence_p;
2609 int final_p;
2611 unit_set_el_t el_list;
2612 unit_set_el_t last_el;
2613 unit_set_el_t new_el;
2614 decl_t decl_in_table;
2615 int i;
2617 el_list = NULL;
2618 last_el = NULL;
2619 for (i = 0; i < num; i++)
2621 decl_in_table = find_decl (names [i]);
2622 if (decl_in_table == NULL)
2623 error ((presence_p
2624 ? (final_p
2625 ? "unit `%s' in final presence set is not declared"
2626 : "unit `%s' in presence set is not declared")
2627 : (final_p
2628 ? "unit `%s' in final absence set is not declared"
2629 : "unit `%s' in absence set is not declared")), names [i]);
2630 else if (decl_in_table->mode != dm_unit)
2631 error ((presence_p
2632 ? (final_p
2633 ? "`%s' in final presence set is not unit"
2634 : "`%s' in presence set is not unit")
2635 : (final_p
2636 ? "`%s' in final absence set is not unit"
2637 : "`%s' in absence set is not unit")), names [i]);
2638 else
2640 new_el = create_node (sizeof (struct unit_set_el));
2641 new_el->unit_decl = DECL_UNIT (decl_in_table);
2642 new_el->next_unit_set_el = NULL;
2643 if (last_el == NULL)
2644 el_list = last_el = new_el;
2645 else
2647 last_el->next_unit_set_el = new_el;
2648 last_el = last_el->next_unit_set_el;
2652 return el_list;
2655 /* Checking NAMES in patterns of a presence/absence clause and
2656 returning the formed pattern_set_el_list. The function is called
2657 only after processing all exclusion sets. */
2658 static pattern_set_el_t
2659 process_presence_absence_patterns (patterns, num, req_pos, presence_p, final_p)
2660 char ***patterns;
2661 int num;
2662 pos_t req_pos ATTRIBUTE_UNUSED;
2663 int presence_p;
2664 int final_p;
2666 pattern_set_el_t el_list;
2667 pattern_set_el_t last_el;
2668 pattern_set_el_t new_el;
2669 decl_t decl_in_table;
2670 int i, j;
2672 el_list = NULL;
2673 last_el = NULL;
2674 for (i = 0; i < num; i++)
2676 for (j = 0; patterns [i] [j] != NULL; j++)
2678 new_el = create_node (sizeof (struct pattern_set_el)
2679 + sizeof (struct unit_decl *) * j);
2680 new_el->unit_decls
2681 = (struct unit_decl **) ((char *) new_el
2682 + sizeof (struct pattern_set_el));
2683 new_el->next_pattern_set_el = NULL;
2684 if (last_el == NULL)
2685 el_list = last_el = new_el;
2686 else
2688 last_el->next_pattern_set_el = new_el;
2689 last_el = last_el->next_pattern_set_el;
2691 new_el->units_num = 0;
2692 for (j = 0; patterns [i] [j] != NULL; j++)
2694 decl_in_table = find_decl (patterns [i] [j]);
2695 if (decl_in_table == NULL)
2696 error ((presence_p
2697 ? (final_p
2698 ? "unit `%s' in final presence set is not declared"
2699 : "unit `%s' in presence set is not declared")
2700 : (final_p
2701 ? "unit `%s' in final absence set is not declared"
2702 : "unit `%s' in absence set is not declared")),
2703 patterns [i] [j]);
2704 else if (decl_in_table->mode != dm_unit)
2705 error ((presence_p
2706 ? (final_p
2707 ? "`%s' in final presence set is not unit"
2708 : "`%s' in presence set is not unit")
2709 : (final_p
2710 ? "`%s' in final absence set is not unit"
2711 : "`%s' in absence set is not unit")),
2712 patterns [i] [j]);
2713 else
2715 new_el->unit_decls [new_el->units_num]
2716 = DECL_UNIT (decl_in_table);
2717 new_el->units_num++;
2721 return el_list;
2724 /* The function adds each element from PATTERN_LIST to presence (if
2725 PRESENCE_P) or absence list of the each element from DEST_LIST.
2726 Checking situations "unit requires own absence", and "unit excludes
2727 and requires presence of ...", "unit requires absence and presence
2728 of ...", "units in (final) presence set belong to different
2729 automata", and "units in (final) absence set belong to different
2730 automata". Remember that we process absence sets only after all
2731 presence sets. */
2732 static void
2733 add_presence_absence (dest_list, pattern_list, req_pos, presence_p, final_p)
2734 unit_set_el_t dest_list;
2735 pattern_set_el_t pattern_list;
2736 pos_t req_pos ATTRIBUTE_UNUSED;
2737 int presence_p;
2738 int final_p;
2740 unit_set_el_t dst;
2741 pattern_set_el_t pat;
2742 struct unit_decl *unit;
2743 unit_set_el_t curr_excl_el;
2744 pattern_set_el_t curr_pat_el;
2745 pattern_set_el_t prev_el;
2746 pattern_set_el_t copy;
2747 int i;
2748 int no_error_flag;
2750 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2751 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2753 for (i = 0; i < pat->units_num; i++)
2755 unit = pat->unit_decls [i];
2756 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2758 error ("unit `%s' requires own absence", unit->name);
2759 continue;
2761 if (dst->unit_decl->automaton_name != NULL
2762 && unit->automaton_name != NULL
2763 && strcmp (dst->unit_decl->automaton_name,
2764 unit->automaton_name) != 0)
2766 error ((presence_p
2767 ? (final_p
2768 ? "units `%s' and `%s' in final presence set belong to different automata"
2769 : "units `%s' and `%s' in presence set belong to different automata")
2770 : (final_p
2771 ? "units `%s' and `%s' in final absence set belong to different automata"
2772 : "units `%s' and `%s' in absence set belong to different automata")),
2773 unit->name, dst->unit_decl->name);
2774 continue;
2776 no_error_flag = 1;
2777 if (presence_p)
2778 for (curr_excl_el = dst->unit_decl->excl_list;
2779 curr_excl_el != NULL;
2780 curr_excl_el = curr_excl_el->next_unit_set_el)
2782 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2784 if (!w_flag)
2786 error ("unit `%s' excludes and requires presence of `%s'",
2787 dst->unit_decl->name, unit->name);
2788 no_error_flag = 0;
2790 else
2791 warning
2792 ("unit `%s' excludes and requires presence of `%s'",
2793 dst->unit_decl->name, unit->name);
2796 else if (pat->units_num == 1)
2797 for (curr_pat_el = dst->unit_decl->presence_list;
2798 curr_pat_el != NULL;
2799 curr_pat_el = curr_pat_el->next_pattern_set_el)
2800 if (curr_pat_el->units_num == 1
2801 && unit == curr_pat_el->unit_decls [0])
2803 if (!w_flag)
2805 error
2806 ("unit `%s' requires absence and presence of `%s'",
2807 dst->unit_decl->name, unit->name);
2808 no_error_flag = 0;
2810 else
2811 warning
2812 ("unit `%s' requires absence and presence of `%s'",
2813 dst->unit_decl->name, unit->name);
2815 if (no_error_flag)
2817 for (prev_el = (presence_p
2818 ? (final_p
2819 ? dst->unit_decl->final_presence_list
2820 : dst->unit_decl->final_presence_list)
2821 : (final_p
2822 ? dst->unit_decl->final_absence_list
2823 : dst->unit_decl->absence_list));
2824 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2825 prev_el = prev_el->next_pattern_set_el)
2827 copy = copy_node (pat, sizeof (*pat));
2828 copy->next_pattern_set_el = NULL;
2829 if (prev_el == NULL)
2831 if (presence_p)
2833 if (final_p)
2834 dst->unit_decl->final_presence_list = copy;
2835 else
2836 dst->unit_decl->presence_list = copy;
2838 else if (final_p)
2839 dst->unit_decl->final_absence_list = copy;
2840 else
2841 dst->unit_decl->absence_list = copy;
2843 else
2844 prev_el->next_pattern_set_el = copy;
2851 /* The function searches for bypass with given IN_INSN_RESERV in given
2852 BYPASS_LIST. */
2853 static struct bypass_decl *
2854 find_bypass (bypass_list, in_insn_reserv)
2855 struct bypass_decl *bypass_list;
2856 struct insn_reserv_decl *in_insn_reserv;
2858 struct bypass_decl *bypass;
2860 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2861 if (bypass->in_insn_reserv == in_insn_reserv)
2862 break;
2863 return bypass;
2866 /* The function processes pipeline description declarations, checks
2867 their correctness, and forms exclusion/presence/absence sets. */
2868 static void
2869 process_decls ()
2871 decl_t decl;
2872 decl_t automaton_decl;
2873 decl_t decl_in_table;
2874 decl_t out_insn_reserv;
2875 decl_t in_insn_reserv;
2876 struct bypass_decl *bypass;
2877 int automaton_presence;
2878 int i;
2880 /* Checking repeated automata declarations. */
2881 automaton_presence = 0;
2882 for (i = 0; i < description->decls_num; i++)
2884 decl = description->decls [i];
2885 if (decl->mode == dm_automaton)
2887 automaton_presence = 1;
2888 decl_in_table = insert_automaton_decl (decl);
2889 if (decl_in_table != decl)
2891 if (!w_flag)
2892 error ("repeated declaration of automaton `%s'",
2893 DECL_AUTOMATON (decl)->name);
2894 else
2895 warning ("repeated declaration of automaton `%s'",
2896 DECL_AUTOMATON (decl)->name);
2900 /* Checking undeclared automata, repeated declarations (except for
2901 automata) and correctness of their attributes (insn latency times
2902 etc.). */
2903 for (i = 0; i < description->decls_num; i++)
2905 decl = description->decls [i];
2906 if (decl->mode == dm_insn_reserv)
2908 DECL_INSN_RESERV (decl)->condexp
2909 = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
2910 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2911 error ("define_insn_reservation `%s' has negative latency time",
2912 DECL_INSN_RESERV (decl)->name);
2913 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2914 description->insns_num++;
2915 decl_in_table = insert_insn_decl (decl);
2916 if (decl_in_table != decl)
2917 error ("`%s' is already used as insn reservation name",
2918 DECL_INSN_RESERV (decl)->name);
2920 else if (decl->mode == dm_bypass)
2922 if (DECL_BYPASS (decl)->latency < 0)
2923 error ("define_bypass `%s - %s' has negative latency time",
2924 DECL_BYPASS (decl)->out_insn_name,
2925 DECL_BYPASS (decl)->in_insn_name);
2927 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2929 if (decl->mode == dm_unit)
2931 DECL_UNIT (decl)->automaton_decl = NULL;
2932 if (DECL_UNIT (decl)->automaton_name != NULL)
2934 automaton_decl
2935 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2936 if (automaton_decl == NULL)
2937 error ("automaton `%s' is not declared",
2938 DECL_UNIT (decl)->automaton_name);
2939 else
2941 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2942 DECL_UNIT (decl)->automaton_decl
2943 = DECL_AUTOMATON (automaton_decl);
2946 else if (automaton_presence)
2947 error ("define_unit `%s' without automaton when one defined",
2948 DECL_UNIT (decl)->name);
2949 DECL_UNIT (decl)->unit_num = description->units_num;
2950 description->units_num++;
2951 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2953 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2954 continue;
2956 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2958 else
2960 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2962 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2963 continue;
2965 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2967 if (decl_in_table == NULL)
2968 decl_in_table = insert_decl (decl);
2969 else
2971 if (decl->mode == dm_unit)
2972 error ("repeated declaration of unit `%s'",
2973 DECL_UNIT (decl)->name);
2974 else
2975 error ("repeated declaration of reservation `%s'",
2976 DECL_RESERV (decl)->name);
2980 /* Check bypasses and form list of bypasses for each (output)
2981 insn. */
2982 for (i = 0; i < description->decls_num; i++)
2984 decl = description->decls [i];
2985 if (decl->mode == dm_bypass)
2987 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2988 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2989 if (out_insn_reserv == NULL)
2990 error ("there is no insn reservation `%s'",
2991 DECL_BYPASS (decl)->out_insn_name);
2992 else if (in_insn_reserv == NULL)
2993 error ("there is no insn reservation `%s'",
2994 DECL_BYPASS (decl)->in_insn_name);
2995 else
2997 DECL_BYPASS (decl)->out_insn_reserv
2998 = DECL_INSN_RESERV (out_insn_reserv);
2999 DECL_BYPASS (decl)->in_insn_reserv
3000 = DECL_INSN_RESERV (in_insn_reserv);
3001 bypass
3002 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
3003 DECL_BYPASS (decl)->in_insn_reserv);
3004 if (bypass != NULL)
3006 if (DECL_BYPASS (decl)->latency == bypass->latency)
3008 if (!w_flag)
3009 error
3010 ("the same bypass `%s - %s' is already defined",
3011 DECL_BYPASS (decl)->out_insn_name,
3012 DECL_BYPASS (decl)->in_insn_name);
3013 else
3014 warning
3015 ("the same bypass `%s - %s' is already defined",
3016 DECL_BYPASS (decl)->out_insn_name,
3017 DECL_BYPASS (decl)->in_insn_name);
3019 else
3020 error ("bypass `%s - %s' is already defined",
3021 DECL_BYPASS (decl)->out_insn_name,
3022 DECL_BYPASS (decl)->in_insn_name);
3024 else
3026 DECL_BYPASS (decl)->next
3027 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
3028 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
3029 = DECL_BYPASS (decl);
3035 /* Check exclusion set declarations and form exclusion sets. */
3036 for (i = 0; i < description->decls_num; i++)
3038 decl = description->decls [i];
3039 if (decl->mode == dm_excl)
3041 unit_set_el_t unit_set_el_list;
3042 unit_set_el_t unit_set_el_list_2;
3044 unit_set_el_list
3045 = process_excls (DECL_EXCL (decl)->names,
3046 DECL_EXCL (decl)->first_list_length, decl->pos);
3047 unit_set_el_list_2
3048 = process_excls (&DECL_EXCL (decl)->names
3049 [DECL_EXCL (decl)->first_list_length],
3050 DECL_EXCL (decl)->all_names_num
3051 - DECL_EXCL (decl)->first_list_length,
3052 decl->pos);
3053 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
3054 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
3058 /* Check presence set declarations and form presence sets. */
3059 for (i = 0; i < description->decls_num; i++)
3061 decl = description->decls [i];
3062 if (decl->mode == dm_presence)
3064 unit_set_el_t unit_set_el_list;
3065 pattern_set_el_t pattern_set_el_list;
3067 unit_set_el_list
3068 = process_presence_absence_names
3069 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
3070 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
3071 pattern_set_el_list
3072 = process_presence_absence_patterns
3073 (DECL_PRESENCE (decl)->patterns,
3074 DECL_PRESENCE (decl)->patterns_num,
3075 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
3076 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3077 decl->pos, TRUE,
3078 DECL_PRESENCE (decl)->final_p);
3082 /* Check absence set declarations and form absence sets. */
3083 for (i = 0; i < description->decls_num; i++)
3085 decl = description->decls [i];
3086 if (decl->mode == dm_absence)
3088 unit_set_el_t unit_set_el_list;
3089 pattern_set_el_t pattern_set_el_list;
3091 unit_set_el_list
3092 = process_presence_absence_names
3093 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
3094 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3095 pattern_set_el_list
3096 = process_presence_absence_patterns
3097 (DECL_ABSENCE (decl)->patterns,
3098 DECL_ABSENCE (decl)->patterns_num,
3099 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3100 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3101 decl->pos, FALSE,
3102 DECL_ABSENCE (decl)->final_p);
3107 /* The following function checks that declared automaton is used. If
3108 the automaton is not used, the function fixes error/warning. The
3109 following function must be called only after `process_decls'. */
3110 static void
3111 check_automaton_usage ()
3113 decl_t decl;
3114 int i;
3116 for (i = 0; i < description->decls_num; i++)
3118 decl = description->decls [i];
3119 if (decl->mode == dm_automaton
3120 && !DECL_AUTOMATON (decl)->automaton_is_used)
3122 if (!w_flag)
3123 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
3124 else
3125 warning ("automaton `%s' is not used",
3126 DECL_AUTOMATON (decl)->name);
3131 /* The following recursive function processes all regexp in order to
3132 fix usage of units or reservations and to fix errors of undeclared
3133 name. The function may change unit_regexp onto reserv_regexp.
3134 Remember that reserv_regexp does not exist before the function
3135 call. */
3136 static regexp_t
3137 process_regexp (regexp)
3138 regexp_t regexp;
3140 decl_t decl_in_table;
3141 regexp_t new_regexp;
3142 int i;
3144 if (regexp->mode == rm_unit)
3146 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
3147 if (decl_in_table == NULL)
3148 error ("undeclared unit or reservation `%s'",
3149 REGEXP_UNIT (regexp)->name);
3150 else if (decl_in_table->mode == dm_unit)
3152 DECL_UNIT (decl_in_table)->unit_is_used = 1;
3153 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
3155 else if (decl_in_table->mode == dm_reserv)
3157 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
3158 new_regexp = create_node (sizeof (struct regexp));
3159 new_regexp->mode = rm_reserv;
3160 new_regexp->pos = regexp->pos;
3161 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
3162 REGEXP_RESERV (new_regexp)->reserv_decl
3163 = DECL_RESERV (decl_in_table);
3164 regexp = new_regexp;
3166 else
3167 abort ();
3169 else if (regexp->mode == rm_sequence)
3170 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3171 REGEXP_SEQUENCE (regexp)->regexps [i]
3172 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
3173 else if (regexp->mode == rm_allof)
3174 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3175 REGEXP_ALLOF (regexp)->regexps [i]
3176 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
3177 else if (regexp->mode == rm_oneof)
3178 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3179 REGEXP_ONEOF (regexp)->regexps [i]
3180 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
3181 else if (regexp->mode == rm_repeat)
3182 REGEXP_REPEAT (regexp)->regexp
3183 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
3184 else if (regexp->mode != rm_nothing)
3185 abort ();
3186 return regexp;
3189 /* The following function processes regexp of define_reservation and
3190 define_insn_reservation with the aid of function
3191 `process_regexp'. */
3192 static void
3193 process_regexp_decls ()
3195 decl_t decl;
3196 int i;
3198 for (i = 0; i < description->decls_num; i++)
3200 decl = description->decls [i];
3201 if (decl->mode == dm_reserv)
3202 DECL_RESERV (decl)->regexp
3203 = process_regexp (DECL_RESERV (decl)->regexp);
3204 else if (decl->mode == dm_insn_reserv)
3205 DECL_INSN_RESERV (decl)->regexp
3206 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3210 /* The following function checks that declared unit is used. If the
3211 unit is not used, the function fixes errors/warnings. The
3212 following function must be called only after `process_decls',
3213 `process_regexp_decls'. */
3214 static void
3215 check_usage ()
3217 decl_t decl;
3218 int i;
3220 for (i = 0; i < description->decls_num; i++)
3222 decl = description->decls [i];
3223 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3225 if (!w_flag)
3226 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3227 else
3228 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3230 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3232 if (!w_flag)
3233 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3234 else
3235 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3240 /* The following variable value is number of reservation being
3241 processed on loop recognition. */
3242 static int curr_loop_pass_num;
3244 /* The following recursive function returns nonzero value if REGEXP
3245 contains given decl or reservations in given regexp refers for
3246 given decl. */
3247 static int
3248 loop_in_regexp (regexp, start_decl)
3249 regexp_t regexp;
3250 decl_t start_decl;
3252 int i;
3254 if (regexp == NULL)
3255 return 0;
3256 if (regexp->mode == rm_unit)
3257 return 0;
3258 else if (regexp->mode == rm_reserv)
3260 if (start_decl->mode == dm_reserv
3261 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3262 return 1;
3263 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3264 == curr_loop_pass_num)
3265 /* declaration has been processed. */
3266 return 0;
3267 else
3269 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3270 = curr_loop_pass_num;
3271 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3272 start_decl);
3275 else if (regexp->mode == rm_sequence)
3277 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3278 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3279 return 1;
3280 return 0;
3282 else if (regexp->mode == rm_allof)
3284 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3285 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3286 return 1;
3287 return 0;
3289 else if (regexp->mode == rm_oneof)
3291 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3292 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3293 return 1;
3294 return 0;
3296 else if (regexp->mode == rm_repeat)
3297 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3298 else
3300 if (regexp->mode != rm_nothing)
3301 abort ();
3302 return 0;
3306 /* The following function fixes errors "cycle in definition ...". The
3307 function uses function `loop_in_regexp' for that. */
3308 static void
3309 check_loops_in_regexps ()
3311 decl_t decl;
3312 int i;
3314 for (i = 0; i < description->decls_num; i++)
3316 decl = description->decls [i];
3317 if (decl->mode == dm_reserv)
3318 DECL_RESERV (decl)->loop_pass_num = 0;
3320 for (i = 0; i < description->decls_num; i++)
3322 decl = description->decls [i];
3323 curr_loop_pass_num = i;
3325 if (decl->mode == dm_reserv)
3327 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
3328 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3330 if (DECL_RESERV (decl)->regexp == NULL)
3331 abort ();
3332 error ("cycle in definition of reservation `%s'",
3333 DECL_RESERV (decl)->name);
3339 /* The function recursively processes IR of reservation and defines
3340 max and min cycle for reservation of unit. */
3341 static void
3342 process_regexp_cycles (regexp, max_start_cycle, min_start_cycle,
3343 max_finish_cycle, min_finish_cycle)
3344 regexp_t regexp;
3345 int max_start_cycle, min_start_cycle;
3346 int *max_finish_cycle, *min_finish_cycle;
3348 int i;
3350 if (regexp->mode == rm_unit)
3352 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
3353 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
3354 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
3355 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
3356 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
3357 *max_finish_cycle = max_start_cycle;
3358 *min_finish_cycle = min_start_cycle;
3360 else if (regexp->mode == rm_reserv)
3361 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3362 max_start_cycle, min_start_cycle,
3363 max_finish_cycle, min_finish_cycle);
3364 else if (regexp->mode == rm_repeat)
3366 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3368 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3369 max_start_cycle, min_start_cycle,
3370 max_finish_cycle, min_finish_cycle);
3371 max_start_cycle = *max_finish_cycle + 1;
3372 min_start_cycle = *min_finish_cycle + 1;
3375 else if (regexp->mode == rm_sequence)
3377 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3379 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3380 max_start_cycle, min_start_cycle,
3381 max_finish_cycle, min_finish_cycle);
3382 max_start_cycle = *max_finish_cycle + 1;
3383 min_start_cycle = *min_finish_cycle + 1;
3386 else if (regexp->mode == rm_allof)
3388 int max_cycle = 0;
3389 int min_cycle = 0;
3391 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3393 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3394 max_start_cycle, min_start_cycle,
3395 max_finish_cycle, min_finish_cycle);
3396 if (max_cycle < *max_finish_cycle)
3397 max_cycle = *max_finish_cycle;
3398 if (i == 0 || min_cycle > *min_finish_cycle)
3399 min_cycle = *min_finish_cycle;
3401 *max_finish_cycle = max_cycle;
3402 *min_finish_cycle = min_cycle;
3404 else if (regexp->mode == rm_oneof)
3406 int max_cycle = 0;
3407 int min_cycle = 0;
3409 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3411 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3412 max_start_cycle, min_start_cycle,
3413 max_finish_cycle, min_finish_cycle);
3414 if (max_cycle < *max_finish_cycle)
3415 max_cycle = *max_finish_cycle;
3416 if (i == 0 || min_cycle > *min_finish_cycle)
3417 min_cycle = *min_finish_cycle;
3419 *max_finish_cycle = max_cycle;
3420 *min_finish_cycle = min_cycle;
3422 else
3424 if (regexp->mode != rm_nothing)
3425 abort ();
3426 *max_finish_cycle = max_start_cycle;
3427 *min_finish_cycle = min_start_cycle;
3431 /* The following function is called only for correct program. The
3432 function defines max reservation of insns in cycles. */
3433 static void
3434 evaluate_max_reserv_cycles ()
3436 int max_insn_cycles_num;
3437 int min_insn_cycles_num;
3438 decl_t decl;
3439 int i;
3441 description->max_insn_reserv_cycles = 0;
3442 for (i = 0; i < description->decls_num; i++)
3444 decl = description->decls [i];
3445 if (decl->mode == dm_insn_reserv)
3447 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3448 &max_insn_cycles_num, &min_insn_cycles_num);
3449 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3450 description->max_insn_reserv_cycles = max_insn_cycles_num;
3453 description->max_insn_reserv_cycles++;
3456 /* The following function calls functions for checking all
3457 description. */
3458 static void
3459 check_all_description ()
3461 process_decls ();
3462 check_automaton_usage ();
3463 process_regexp_decls ();
3464 check_usage ();
3465 check_loops_in_regexps ();
3466 if (!have_error)
3467 evaluate_max_reserv_cycles ();
3472 /* The page contains abstract data `ticker'. This data is used to
3473 report time of different phases of building automata. It is
3474 possibly to write a description for which automata will be built
3475 during several minutes even on fast machine. */
3477 /* The following function creates ticker and makes it active. */
3478 static ticker_t
3479 create_ticker ()
3481 ticker_t ticker;
3483 ticker.modified_creation_time = get_run_time ();
3484 ticker.incremented_off_time = 0;
3485 return ticker;
3488 /* The following function switches off given ticker. */
3489 static void
3490 ticker_off (ticker)
3491 ticker_t *ticker;
3493 if (ticker->incremented_off_time == 0)
3494 ticker->incremented_off_time = get_run_time () + 1;
3497 /* The following function switches on given ticker. */
3498 static void
3499 ticker_on (ticker)
3500 ticker_t *ticker;
3502 if (ticker->incremented_off_time != 0)
3504 ticker->modified_creation_time
3505 += get_run_time () - ticker->incremented_off_time + 1;
3506 ticker->incremented_off_time = 0;
3510 /* The following function returns current time in milliseconds since
3511 the moment when given ticker was created. */
3512 static int
3513 active_time (ticker)
3514 ticker_t ticker;
3516 if (ticker.incremented_off_time != 0)
3517 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3518 else
3519 return get_run_time () - ticker.modified_creation_time;
3522 /* The following function returns string representation of active time
3523 of given ticker. The result is string representation of seconds
3524 with accuracy of 1/100 second. Only result of the last call of the
3525 function exists. Therefore the following code is not correct
3527 printf ("parser time: %s\ngeneration time: %s\n",
3528 active_time_string (parser_ticker),
3529 active_time_string (generation_ticker));
3531 Correct code has to be the following
3533 printf ("parser time: %s\n", active_time_string (parser_ticker));
3534 printf ("generation time: %s\n",
3535 active_time_string (generation_ticker));
3538 static void
3539 print_active_time (f, ticker)
3540 FILE *f;
3541 ticker_t ticker;
3543 int msecs;
3545 msecs = active_time (ticker);
3546 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3551 /* The following variable value is number of automaton which are
3552 really being created. This value is defined on the base of
3553 argument of option `-split'. If the variable has zero value the
3554 number of automata is defined by the constructions `%automaton'.
3555 This case occurs when option `-split' is absent or has zero
3556 argument. If constructions `define_automaton' is absent only one
3557 automaton is created. */
3558 static int automata_num;
3560 /* The following variable values are times of
3561 o transformation of regular expressions
3562 o building NDFA (DFA if !ndfa_flag)
3563 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3564 o DFA minimization
3565 o building insn equivalence classes
3566 o all previous ones
3567 o code output */
3568 static ticker_t transform_time;
3569 static ticker_t NDFA_time;
3570 static ticker_t NDFA_to_DFA_time;
3571 static ticker_t minimize_time;
3572 static ticker_t equiv_time;
3573 static ticker_t automaton_generation_time;
3574 static ticker_t output_time;
3576 /* The following variable values are times of
3577 all checking
3578 all generation
3579 all pipeline hazard translator work */
3580 static ticker_t check_time;
3581 static ticker_t generation_time;
3582 static ticker_t all_time;
3586 /* Pseudo insn decl which denotes advancing cycle. */
3587 static decl_t advance_cycle_insn_decl;
3588 static void
3589 add_advance_cycle_insn_decl ()
3591 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3592 advance_cycle_insn_decl->mode = dm_insn_reserv;
3593 advance_cycle_insn_decl->pos = no_pos;
3594 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3595 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
3596 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3597 = description->insns_num;
3598 description->decls [description->decls_num] = advance_cycle_insn_decl;
3599 description->decls_num++;
3600 description->insns_num++;
3601 num_dfa_decls++;
3605 /* Abstract data `alternative states' which represents
3606 nondeterministic nature of the description (see comments for
3607 structures alt_state and state). */
3609 /* List of free states. */
3610 static alt_state_t first_free_alt_state;
3612 #ifndef NDEBUG
3613 /* The following variables is maximal number of allocated nodes
3614 alt_state. */
3615 static int allocated_alt_states_num = 0;
3616 #endif
3618 /* The following function returns free node alt_state. It may be new
3619 allocated node or node freed earlier. */
3620 static alt_state_t
3621 get_free_alt_state ()
3623 alt_state_t result;
3625 if (first_free_alt_state != NULL)
3627 result = first_free_alt_state;
3628 first_free_alt_state = first_free_alt_state->next_alt_state;
3630 else
3632 #ifndef NDEBUG
3633 allocated_alt_states_num++;
3634 #endif
3635 result = create_node (sizeof (struct alt_state));
3637 result->state = NULL;
3638 result->next_alt_state = NULL;
3639 result->next_sorted_alt_state = NULL;
3640 return result;
3643 /* The function frees node ALT_STATE. */
3644 static void
3645 free_alt_state (alt_state)
3646 alt_state_t alt_state;
3648 if (alt_state == NULL)
3649 return;
3650 alt_state->next_alt_state = first_free_alt_state;
3651 first_free_alt_state = alt_state;
3654 /* The function frees list started with node ALT_STATE_LIST. */
3655 static void
3656 free_alt_states (alt_states_list)
3657 alt_state_t alt_states_list;
3659 alt_state_t curr_alt_state;
3660 alt_state_t next_alt_state;
3662 for (curr_alt_state = alt_states_list;
3663 curr_alt_state != NULL;
3664 curr_alt_state = next_alt_state)
3666 next_alt_state = curr_alt_state->next_alt_state;
3667 free_alt_state (curr_alt_state);
3671 /* The function compares unique numbers of alt states. */
3672 static int
3673 alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
3674 const void *alt_state_ptr_1;
3675 const void *alt_state_ptr_2;
3677 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3678 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3679 return 0;
3680 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3681 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3682 return -1;
3683 else
3684 return 1;
3687 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3688 states from the list. The comparison key is alt state unique
3689 number. */
3690 static alt_state_t
3691 uniq_sort_alt_states (alt_states_list)
3692 alt_state_t alt_states_list;
3694 alt_state_t curr_alt_state;
3695 vla_ptr_t alt_states;
3696 size_t i;
3697 size_t prev_unique_state_ind;
3698 alt_state_t result;
3699 alt_state_t *result_ptr;
3701 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3702 for (curr_alt_state = alt_states_list;
3703 curr_alt_state != NULL;
3704 curr_alt_state = curr_alt_state->next_alt_state)
3705 VLA_PTR_ADD (alt_states, curr_alt_state);
3706 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3707 sizeof (alt_state_t), alt_state_cmp);
3708 if (VLA_PTR_LENGTH (alt_states) == 0)
3709 result = NULL;
3710 else
3712 result_ptr = VLA_PTR_BEGIN (alt_states);
3713 prev_unique_state_ind = 0;
3714 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3715 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3717 prev_unique_state_ind++;
3718 result_ptr [prev_unique_state_ind] = result_ptr [i];
3720 #if 0
3721 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3722 free_alt_state (result_ptr [i]);
3723 #endif
3724 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3725 result_ptr = VLA_PTR_BEGIN (alt_states);
3726 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3727 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3728 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3729 result = *result_ptr;
3731 VLA_PTR_DELETE (alt_states);
3732 return result;
3735 /* The function checks equality of alt state lists. Remember that the
3736 lists must be already sorted by the previous function. */
3737 static int
3738 alt_states_eq (alt_states_1, alt_states_2)
3739 alt_state_t alt_states_1;
3740 alt_state_t alt_states_2;
3742 while (alt_states_1 != NULL && alt_states_2 != NULL
3743 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3745 alt_states_1 = alt_states_1->next_sorted_alt_state;
3746 alt_states_2 = alt_states_2->next_sorted_alt_state;
3748 return alt_states_1 == alt_states_2;
3751 /* Initialization of the abstract data. */
3752 static void
3753 initiate_alt_states ()
3755 first_free_alt_state = NULL;
3758 /* Finishing work with the abstract data. */
3759 static void
3760 finish_alt_states ()
3766 /* The page contains macros for work with bits strings. We could use
3767 standard gcc bitmap or sbitmap but it would result in difficulties
3768 of building canadian cross. */
3770 /* Set bit number bitno in the bit string. The macro is not side
3771 effect proof. */
3772 #define SET_BIT(bitstring, bitno) \
3773 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3775 #define CLEAR_BIT(bitstring, bitno) \
3776 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3778 /* Test if bit number bitno in the bitstring is set. The macro is not
3779 side effect proof. */
3780 #define TEST_BIT(bitstring, bitno) \
3781 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3785 /* This page contains abstract data `state'. */
3787 /* Maximal length of reservations in cycles (>= 1). */
3788 static int max_cycles_num;
3790 /* Number of set elements (see type set_el_t) needed for
3791 representation of one cycle reservation. It is depended on units
3792 number. */
3793 static int els_in_cycle_reserv;
3795 /* Number of set elements (see type set_el_t) needed for
3796 representation of maximal length reservation. Deterministic
3797 reservation is stored as set (bit string) of length equal to the
3798 variable value * number of bits in set_el_t. */
3799 static int els_in_reservs;
3801 /* VLA for representation of array of pointers to unit
3802 declarations. */
3803 static vla_ptr_t units_container;
3805 /* The start address of the array. */
3806 static unit_decl_t *units_array;
3808 /* Temporary reservation of maximal length. */
3809 static reserv_sets_t temp_reserv;
3811 /* The state table itself is represented by the following variable. */
3812 static htab_t state_table;
3814 /* VLA for representation of array of pointers to free nodes
3815 `state'. */
3816 static vla_ptr_t free_states;
3818 static int curr_unique_state_num;
3820 #ifndef NDEBUG
3821 /* The following variables is maximal number of allocated nodes
3822 `state'. */
3823 static int allocated_states_num = 0;
3824 #endif
3826 /* Allocate new reservation set. */
3827 static reserv_sets_t
3828 alloc_empty_reserv_sets ()
3830 reserv_sets_t result;
3832 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3833 result = (reserv_sets_t) obstack_base (&irp);
3834 obstack_finish (&irp);
3835 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3836 return result;
3839 /* Hash value of reservation set. */
3840 static unsigned
3841 reserv_sets_hash_value (reservs)
3842 reserv_sets_t reservs;
3844 set_el_t hash_value;
3845 unsigned result;
3846 int reservs_num, i;
3847 set_el_t *reserv_ptr;
3849 hash_value = 0;
3850 reservs_num = els_in_reservs;
3851 reserv_ptr = reservs;
3852 i = 0;
3853 while (reservs_num != 0)
3855 reservs_num--;
3856 hash_value += ((*reserv_ptr >> i)
3857 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3858 i++;
3859 if (i == sizeof (set_el_t) * CHAR_BIT)
3860 i = 0;
3861 reserv_ptr++;
3863 if (sizeof (set_el_t) <= sizeof (unsigned))
3864 return hash_value;
3865 result = 0;
3866 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3868 result += (unsigned) hash_value;
3869 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3871 return result;
3874 /* Comparison of given reservation sets. */
3875 static int
3876 reserv_sets_cmp (reservs_1, reservs_2)
3877 reserv_sets_t reservs_1;
3878 reserv_sets_t reservs_2;
3880 int reservs_num;
3881 set_el_t *reserv_ptr_1;
3882 set_el_t *reserv_ptr_2;
3884 if (reservs_1 == NULL || reservs_2 == NULL)
3885 abort ();
3886 reservs_num = els_in_reservs;
3887 reserv_ptr_1 = reservs_1;
3888 reserv_ptr_2 = reservs_2;
3889 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3891 reservs_num--;
3892 reserv_ptr_1++;
3893 reserv_ptr_2++;
3895 if (reservs_num == 0)
3896 return 0;
3897 else if (*reserv_ptr_1 < *reserv_ptr_2)
3898 return -1;
3899 else
3900 return 1;
3903 /* The function checks equality of the reservation sets. */
3904 static int
3905 reserv_sets_eq (reservs_1, reservs_2)
3906 reserv_sets_t reservs_1;
3907 reserv_sets_t reservs_2;
3909 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3912 /* Set up in the reservation set that unit with UNIT_NUM is used on
3913 CYCLE_NUM. */
3914 static void
3915 set_unit_reserv (reservs, cycle_num, unit_num)
3916 reserv_sets_t reservs;
3917 int cycle_num;
3918 int unit_num;
3920 if (cycle_num >= max_cycles_num)
3921 abort ();
3922 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3923 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3926 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3927 used on CYCLE_NUM. */
3928 static int
3929 test_unit_reserv (reservs, cycle_num, unit_num)
3930 reserv_sets_t reservs;
3931 int cycle_num;
3932 int unit_num;
3934 if (cycle_num >= max_cycles_num)
3935 abort ();
3936 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3937 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3940 /* The function checks that the reservation set represents no one unit
3941 reservation. */
3942 static int
3943 it_is_empty_reserv_sets (operand)
3944 reserv_sets_t operand;
3946 set_el_t *reserv_ptr;
3947 int reservs_num;
3949 if (operand == NULL)
3950 abort ();
3951 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3952 reservs_num != 0;
3953 reserv_ptr++, reservs_num--)
3954 if (*reserv_ptr != 0)
3955 return 0;
3956 return 1;
3959 /* The function checks that the reservation sets are intersected,
3960 i.e. there is a unit reservation on a cycle in both reservation
3961 sets. */
3962 static int
3963 reserv_sets_are_intersected (operand_1, operand_2)
3964 reserv_sets_t operand_1;
3965 reserv_sets_t operand_2;
3967 set_el_t *el_ptr_1;
3968 set_el_t *el_ptr_2;
3969 set_el_t *cycle_ptr_1;
3970 set_el_t *cycle_ptr_2;
3972 if (operand_1 == NULL || operand_2 == NULL)
3973 abort ();
3974 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3975 el_ptr_1 < operand_1 + els_in_reservs;
3976 el_ptr_1++, el_ptr_2++)
3977 if (*el_ptr_1 & *el_ptr_2)
3978 return 1;
3979 reserv_sets_or (temp_reserv, operand_1, operand_2);
3980 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3981 cycle_ptr_1 < operand_1 + els_in_reservs;
3982 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3984 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3985 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3986 el_ptr_1++, el_ptr_2++)
3987 if (*el_ptr_1 & *el_ptr_2)
3988 return 1;
3989 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3990 return 1;
3991 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3992 - operand_2),
3993 cycle_ptr_2, TRUE))
3994 return 1;
3995 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3996 return 1;
3997 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3998 cycle_ptr_2, TRUE))
3999 return 1;
4001 return 0;
4004 /* The function sets up RESULT bits by bits of OPERAND shifted on one
4005 cpu cycle. The remaining bits of OPERAND (representing the last
4006 cycle unit reservations) are not changed. */
4007 static void
4008 reserv_sets_shift (result, operand)
4009 reserv_sets_t result;
4010 reserv_sets_t operand;
4012 int i;
4014 if (result == NULL || operand == NULL || result == operand)
4015 abort ();
4016 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
4017 result [i - els_in_cycle_reserv] = operand [i];
4020 /* OR of the reservation sets. */
4021 static void
4022 reserv_sets_or (result, operand_1, operand_2)
4023 reserv_sets_t result;
4024 reserv_sets_t operand_1;
4025 reserv_sets_t operand_2;
4027 set_el_t *el_ptr_1;
4028 set_el_t *el_ptr_2;
4029 set_el_t *result_set_el_ptr;
4031 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
4032 abort ();
4033 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
4034 el_ptr_1 < operand_1 + els_in_reservs;
4035 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
4036 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
4039 /* AND of the reservation sets. */
4040 static void
4041 reserv_sets_and (result, operand_1, operand_2)
4042 reserv_sets_t result;
4043 reserv_sets_t operand_1;
4044 reserv_sets_t operand_2;
4046 set_el_t *el_ptr_1;
4047 set_el_t *el_ptr_2;
4048 set_el_t *result_set_el_ptr;
4050 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
4051 abort ();
4052 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
4053 el_ptr_1 < operand_1 + els_in_reservs;
4054 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
4055 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
4058 /* The function outputs string representation of units reservation on
4059 cycle START_CYCLE in the reservation set. The function uses repeat
4060 construction if REPETITION_NUM > 1. */
4061 static void
4062 output_cycle_reservs (f, reservs, start_cycle, repetition_num)
4063 FILE *f;
4064 reserv_sets_t reservs;
4065 int start_cycle;
4066 int repetition_num;
4068 int unit_num;
4069 int reserved_units_num;
4071 reserved_units_num = 0;
4072 for (unit_num = 0; unit_num < description->units_num; unit_num++)
4073 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
4074 * sizeof (set_el_t) * CHAR_BIT + unit_num))
4075 reserved_units_num++;
4076 if (repetition_num <= 0)
4077 abort ();
4078 if (repetition_num != 1 && reserved_units_num > 1)
4079 fprintf (f, "(");
4080 reserved_units_num = 0;
4081 for (unit_num = 0;
4082 unit_num < description->units_num;
4083 unit_num++)
4084 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
4085 * sizeof (set_el_t) * CHAR_BIT + unit_num))
4087 if (reserved_units_num != 0)
4088 fprintf (f, "+");
4089 reserved_units_num++;
4090 fprintf (f, "%s", units_array [unit_num]->name);
4092 if (reserved_units_num == 0)
4093 fprintf (f, NOTHING_NAME);
4094 if (repetition_num <= 0)
4095 abort ();
4096 if (repetition_num != 1 && reserved_units_num > 1)
4097 fprintf (f, ")");
4098 if (repetition_num != 1)
4099 fprintf (f, "*%d", repetition_num);
4102 /* The function outputs string representation of units reservation in
4103 the reservation set. */
4104 static void
4105 output_reserv_sets (f, reservs)
4106 FILE *f;
4107 reserv_sets_t reservs;
4109 int start_cycle = 0;
4110 int cycle;
4111 int repetition_num;
4113 repetition_num = 0;
4114 for (cycle = 0; cycle < max_cycles_num; cycle++)
4115 if (repetition_num == 0)
4117 repetition_num++;
4118 start_cycle = cycle;
4120 else if (memcmp
4121 ((char *) reservs + start_cycle * els_in_cycle_reserv
4122 * sizeof (set_el_t),
4123 (char *) reservs + cycle * els_in_cycle_reserv
4124 * sizeof (set_el_t),
4125 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
4126 repetition_num++;
4127 else
4129 if (start_cycle != 0)
4130 fprintf (f, ", ");
4131 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
4132 repetition_num = 1;
4133 start_cycle = cycle;
4135 if (start_cycle < max_cycles_num)
4137 if (start_cycle != 0)
4138 fprintf (f, ", ");
4139 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
4143 /* The following function returns free node state for AUTOMATON. It
4144 may be new allocated node or node freed earlier. The function also
4145 allocates reservation set if WITH_RESERVS has nonzero value. */
4146 static state_t
4147 get_free_state (with_reservs, automaton)
4148 int with_reservs;
4149 automaton_t automaton;
4151 state_t result;
4153 if (max_cycles_num <= 0 || automaton == NULL)
4154 abort ();
4155 if (VLA_PTR_LENGTH (free_states) != 0)
4157 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
4158 VLA_PTR_SHORTEN (free_states, 1);
4159 result->automaton = automaton;
4160 result->first_out_arc = NULL;
4161 result->it_was_placed_in_stack_for_NDFA_forming = 0;
4162 result->it_was_placed_in_stack_for_DFA_forming = 0;
4163 result->component_states = NULL;
4164 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
4166 else
4168 #ifndef NDEBUG
4169 allocated_states_num++;
4170 #endif
4171 result = create_node (sizeof (struct state));
4172 result->automaton = automaton;
4173 result->first_out_arc = NULL;
4174 result->unique_num = curr_unique_state_num;
4175 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
4176 curr_unique_state_num++;
4178 if (with_reservs)
4180 if (result->reservs == NULL)
4181 result->reservs = alloc_empty_reserv_sets ();
4182 else
4183 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
4185 return result;
4188 /* The function frees node STATE. */
4189 static void
4190 free_state (state)
4191 state_t state;
4193 free_alt_states (state->component_states);
4194 VLA_PTR_ADD (free_states, state);
4197 /* Hash value of STATE. If STATE represents deterministic state it is
4198 simply hash value of the corresponding reservation set. Otherwise
4199 it is formed from hash values of the component deterministic
4200 states. One more key is order number of state automaton. */
4201 static hashval_t
4202 state_hash (state)
4203 const void *state;
4205 unsigned int hash_value;
4206 alt_state_t alt_state;
4208 if (((state_t) state)->component_states == NULL)
4209 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
4210 else
4212 hash_value = 0;
4213 for (alt_state = ((state_t) state)->component_states;
4214 alt_state != NULL;
4215 alt_state = alt_state->next_sorted_alt_state)
4216 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4217 | (hash_value << CHAR_BIT))
4218 + alt_state->state->unique_num);
4220 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4221 | (hash_value << CHAR_BIT))
4222 + ((state_t) state)->automaton->automaton_order_num);
4223 return hash_value;
4226 /* Return nonzero value if the states are the same. */
4227 static int
4228 state_eq_p (state_1, state_2)
4229 const void *state_1;
4230 const void *state_2;
4232 alt_state_t alt_state_1;
4233 alt_state_t alt_state_2;
4235 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
4236 return 0;
4237 else if (((state_t) state_1)->component_states == NULL
4238 && ((state_t) state_2)->component_states == NULL)
4239 return reserv_sets_eq (((state_t) state_1)->reservs,
4240 ((state_t) state_2)->reservs);
4241 else if (((state_t) state_1)->component_states != NULL
4242 && ((state_t) state_2)->component_states != NULL)
4244 for (alt_state_1 = ((state_t) state_1)->component_states,
4245 alt_state_2 = ((state_t) state_2)->component_states;
4246 alt_state_1 != NULL && alt_state_2 != NULL;
4247 alt_state_1 = alt_state_1->next_sorted_alt_state,
4248 alt_state_2 = alt_state_2->next_sorted_alt_state)
4249 /* All state in the list must be already in the hash table.
4250 Also the lists must be sorted. */
4251 if (alt_state_1->state != alt_state_2->state)
4252 return 0;
4253 return alt_state_1 == alt_state_2;
4255 else
4256 return 0;
4259 /* Insert STATE into the state table. */
4260 static state_t
4261 insert_state (state)
4262 state_t state;
4264 void **entry_ptr;
4266 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
4267 if (*entry_ptr == NULL)
4268 *entry_ptr = (void *) state;
4269 return (state_t) *entry_ptr;
4272 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4273 deterministic STATE. */
4274 static void
4275 set_state_reserv (state, cycle_num, unit_num)
4276 state_t state;
4277 int cycle_num;
4278 int unit_num;
4280 set_unit_reserv (state->reservs, cycle_num, unit_num);
4283 /* Return nonzero value if the deterministic states contains a
4284 reservation of the same cpu unit on the same cpu cycle. */
4285 static int
4286 intersected_state_reservs_p (state1, state2)
4287 state_t state1;
4288 state_t state2;
4290 if (state1->automaton != state2->automaton)
4291 abort ();
4292 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
4295 /* Return deterministic state (inserted into the table) which
4296 representing the automaton state which is union of reservations of
4297 the deterministic states masked by RESERVS. */
4298 static state_t
4299 states_union (state1, state2, reservs)
4300 state_t state1;
4301 state_t state2;
4302 reserv_sets_t reservs;
4304 state_t result;
4305 state_t state_in_table;
4307 if (state1->automaton != state2->automaton)
4308 abort ();
4309 result = get_free_state (1, state1->automaton);
4310 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
4311 reserv_sets_and (result->reservs, result->reservs, reservs);
4312 state_in_table = insert_state (result);
4313 if (result != state_in_table)
4315 free_state (result);
4316 result = state_in_table;
4318 return result;
4321 /* Return deterministic state (inserted into the table) which
4322 represent the automaton state is obtained from deterministic STATE
4323 by advancing cpu cycle and masking by RESERVS. */
4324 static state_t
4325 state_shift (state, reservs)
4326 state_t state;
4327 reserv_sets_t reservs;
4329 state_t result;
4330 state_t state_in_table;
4332 result = get_free_state (1, state->automaton);
4333 reserv_sets_shift (result->reservs, state->reservs);
4334 reserv_sets_and (result->reservs, result->reservs, reservs);
4335 state_in_table = insert_state (result);
4336 if (result != state_in_table)
4338 free_state (result);
4339 result = state_in_table;
4341 return result;
4344 /* Initialization of the abstract data. */
4345 static void
4346 initiate_states ()
4348 decl_t decl;
4349 int i;
4351 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
4352 units_array
4353 = (description->decls_num && description->units_num
4354 ? VLA_PTR_BEGIN (units_container) : NULL);
4355 for (i = 0; i < description->decls_num; i++)
4357 decl = description->decls [i];
4358 if (decl->mode == dm_unit)
4359 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
4361 max_cycles_num = description->max_insn_reserv_cycles;
4362 els_in_cycle_reserv
4363 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
4364 / (sizeof (set_el_t) * CHAR_BIT));
4365 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
4366 curr_unique_state_num = 0;
4367 initiate_alt_states ();
4368 VLA_PTR_CREATE (free_states, 1500, "free states");
4369 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
4370 temp_reserv = alloc_empty_reserv_sets ();
4373 /* Finishing work with the abstract data. */
4374 static void
4375 finish_states ()
4377 VLA_PTR_DELETE (units_container);
4378 htab_delete (state_table);
4379 VLA_PTR_DELETE (free_states);
4380 finish_alt_states ();
4385 /* Abstract data `arcs'. */
4387 /* List of free arcs. */
4388 static arc_t first_free_arc;
4390 #ifndef NDEBUG
4391 /* The following variables is maximal number of allocated nodes
4392 `arc'. */
4393 static int allocated_arcs_num = 0;
4394 #endif
4396 /* The function frees node ARC. */
4397 static void
4398 free_arc (arc)
4399 arc_t arc;
4401 arc->next_out_arc = first_free_arc;
4402 first_free_arc = arc;
4405 /* The function removes and frees ARC staring from FROM_STATE. */
4406 static void
4407 remove_arc (from_state, arc)
4408 state_t from_state;
4409 arc_t arc;
4411 arc_t prev_arc;
4412 arc_t curr_arc;
4414 if (arc == NULL)
4415 abort ();
4416 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
4417 curr_arc != NULL;
4418 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4419 if (curr_arc == arc)
4420 break;
4421 if (curr_arc == NULL)
4422 abort ();
4423 if (prev_arc == NULL)
4424 from_state->first_out_arc = arc->next_out_arc;
4425 else
4426 prev_arc->next_out_arc = arc->next_out_arc;
4427 free_arc (arc);
4430 /* The functions returns arc with given characteristics (or NULL if
4431 the arc does not exist). */
4432 static arc_t
4433 find_arc (from_state, to_state, insn)
4434 state_t from_state;
4435 state_t to_state;
4436 ainsn_t insn;
4438 arc_t arc;
4440 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4441 if (arc->to_state == to_state && arc->insn == insn)
4442 return arc;
4443 return NULL;
4446 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4447 and with given STATE_ALTS. The function returns added arc (or
4448 already existing arc). */
4449 static arc_t
4450 add_arc (from_state, to_state, ainsn, state_alts)
4451 state_t from_state;
4452 state_t to_state;
4453 ainsn_t ainsn;
4454 int state_alts;
4456 arc_t new_arc;
4458 new_arc = find_arc (from_state, to_state, ainsn);
4459 if (new_arc != NULL)
4460 return new_arc;
4461 if (first_free_arc == NULL)
4463 #ifndef NDEBUG
4464 allocated_arcs_num++;
4465 #endif
4466 new_arc = create_node (sizeof (struct arc));
4467 new_arc->to_state = NULL;
4468 new_arc->insn = NULL;
4469 new_arc->next_out_arc = NULL;
4471 else
4473 new_arc = first_free_arc;
4474 first_free_arc = first_free_arc->next_out_arc;
4476 new_arc->to_state = to_state;
4477 new_arc->insn = ainsn;
4478 ainsn->arc_exists_p = 1;
4479 new_arc->next_out_arc = from_state->first_out_arc;
4480 from_state->first_out_arc = new_arc;
4481 new_arc->next_arc_marked_by_insn = NULL;
4482 new_arc->state_alts = state_alts;
4483 return new_arc;
4486 /* The function returns the first arc starting from STATE. */
4487 static arc_t
4488 first_out_arc (state)
4489 state_t state;
4491 return state->first_out_arc;
4494 /* The function returns next out arc after ARC. */
4495 static arc_t
4496 next_out_arc (arc)
4497 arc_t arc;
4499 return arc->next_out_arc;
4502 /* Initialization of the abstract data. */
4503 static void
4504 initiate_arcs ()
4506 first_free_arc = NULL;
4509 /* Finishing work with the abstract data. */
4510 static void
4511 finish_arcs ()
4517 /* Abstract data `automata lists'. */
4519 /* List of free states. */
4520 static automata_list_el_t first_free_automata_list_el;
4522 /* The list being formed. */
4523 static automata_list_el_t current_automata_list;
4525 /* Hash table of automata lists. */
4526 static htab_t automata_list_table;
4528 /* The following function returns free automata list el. It may be
4529 new allocated node or node freed earlier. */
4530 static automata_list_el_t
4531 get_free_automata_list_el ()
4533 automata_list_el_t result;
4535 if (first_free_automata_list_el != NULL)
4537 result = first_free_automata_list_el;
4538 first_free_automata_list_el
4539 = first_free_automata_list_el->next_automata_list_el;
4541 else
4542 result = create_node (sizeof (struct automata_list_el));
4543 result->automaton = NULL;
4544 result->next_automata_list_el = NULL;
4545 return result;
4548 /* The function frees node AUTOMATA_LIST_EL. */
4549 static void
4550 free_automata_list_el (automata_list_el)
4551 automata_list_el_t automata_list_el;
4553 if (automata_list_el == NULL)
4554 return;
4555 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4556 first_free_automata_list_el = automata_list_el;
4559 /* The function frees list AUTOMATA_LIST. */
4560 static void
4561 free_automata_list (automata_list)
4562 automata_list_el_t automata_list;
4564 automata_list_el_t curr_automata_list_el;
4565 automata_list_el_t next_automata_list_el;
4567 for (curr_automata_list_el = automata_list;
4568 curr_automata_list_el != NULL;
4569 curr_automata_list_el = next_automata_list_el)
4571 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4572 free_automata_list_el (curr_automata_list_el);
4576 /* Hash value of AUTOMATA_LIST. */
4577 static hashval_t
4578 automata_list_hash (automata_list)
4579 const void *automata_list;
4581 unsigned int hash_value;
4582 automata_list_el_t curr_automata_list_el;
4584 hash_value = 0;
4585 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4586 curr_automata_list_el != NULL;
4587 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4588 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4589 | (hash_value << CHAR_BIT))
4590 + curr_automata_list_el->automaton->automaton_order_num);
4591 return hash_value;
4594 /* Return nonzero value if the automata_lists are the same. */
4595 static int
4596 automata_list_eq_p (automata_list_1, automata_list_2)
4597 const void *automata_list_1;
4598 const void *automata_list_2;
4600 automata_list_el_t automata_list_el_1;
4601 automata_list_el_t automata_list_el_2;
4603 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4604 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4605 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4606 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4607 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4608 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4609 return 0;
4610 return automata_list_el_1 == automata_list_el_2;
4613 /* Initialization of the abstract data. */
4614 static void
4615 initiate_automata_lists ()
4617 first_free_automata_list_el = NULL;
4618 automata_list_table = htab_create (1500, automata_list_hash,
4619 automata_list_eq_p, (htab_del) 0);
4622 /* The following function starts new automata list and makes it the
4623 current one. */
4624 static void
4625 automata_list_start ()
4627 current_automata_list = NULL;
4630 /* The following function adds AUTOMATON to the current list. */
4631 static void
4632 automata_list_add (automaton)
4633 automaton_t automaton;
4635 automata_list_el_t el;
4637 el = get_free_automata_list_el ();
4638 el->automaton = automaton;
4639 el->next_automata_list_el = current_automata_list;
4640 current_automata_list = el;
4643 /* The following function finishes forming the current list, inserts
4644 it into the table and returns it. */
4645 static automata_list_el_t
4646 automata_list_finish ()
4648 void **entry_ptr;
4650 if (current_automata_list == NULL)
4651 return NULL;
4652 entry_ptr = htab_find_slot (automata_list_table,
4653 (void *) current_automata_list, 1);
4654 if (*entry_ptr == NULL)
4655 *entry_ptr = (void *) current_automata_list;
4656 else
4657 free_automata_list (current_automata_list);
4658 current_automata_list = NULL;
4659 return (automata_list_el_t) *entry_ptr;
4662 /* Finishing work with the abstract data. */
4663 static void
4664 finish_automata_lists ()
4666 htab_delete (automata_list_table);
4671 /* The page contains abstract data for work with exclusion sets (see
4672 exclusion_set in file rtl.def). */
4674 /* The following variable refers to an exclusion set returned by
4675 get_excl_set. This is bit string of length equal to cpu units
4676 number. If exclusion set for given unit contains 1 for a unit,
4677 then simultaneous reservation of the units is prohibited. */
4678 static reserv_sets_t excl_set;
4680 /* The array contains exclusion sets for each unit. */
4681 static reserv_sets_t *unit_excl_set_table;
4683 /* The following function forms the array containing exclusion sets
4684 for each unit. */
4685 static void
4686 initiate_excl_sets ()
4688 decl_t decl;
4689 reserv_sets_t unit_excl_set;
4690 unit_set_el_t el;
4691 int i;
4693 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4694 excl_set = (reserv_sets_t) obstack_base (&irp);
4695 obstack_finish (&irp);
4696 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4697 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4698 obstack_finish (&irp);
4699 /* Evaluate unit exclusion sets. */
4700 for (i = 0; i < description->decls_num; i++)
4702 decl = description->decls [i];
4703 if (decl->mode == dm_unit)
4705 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4706 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4707 obstack_finish (&irp);
4708 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4709 for (el = DECL_UNIT (decl)->excl_list;
4710 el != NULL;
4711 el = el->next_unit_set_el)
4713 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4714 el->unit_decl->in_set_p = TRUE;
4716 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4721 /* The function sets up and return EXCL_SET which is union of
4722 exclusion sets for each unit in IN_SET. */
4723 static reserv_sets_t
4724 get_excl_set (in_set)
4725 reserv_sets_t in_set;
4727 int excl_char_num;
4728 int chars_num;
4729 int i;
4730 int start_unit_num;
4731 int unit_num;
4733 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4734 memset (excl_set, 0, chars_num);
4735 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4736 if (((unsigned char *) in_set) [excl_char_num])
4737 for (i = CHAR_BIT - 1; i >= 0; i--)
4738 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4740 start_unit_num = excl_char_num * CHAR_BIT + i;
4741 if (start_unit_num >= description->units_num)
4742 return excl_set;
4743 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4745 excl_set [unit_num]
4746 |= unit_excl_set_table [start_unit_num] [unit_num];
4749 return excl_set;
4754 /* The page contains abstract data for work with presence/absence
4755 pattern sets (see presence_set/absence_set in file rtl.def). */
4757 /* The following arrays contain correspondingly presence, final
4758 presence, absence, and final absence patterns for each unit. */
4759 static pattern_reserv_t *unit_presence_set_table;
4760 static pattern_reserv_t *unit_final_presence_set_table;
4761 static pattern_reserv_t *unit_absence_set_table;
4762 static pattern_reserv_t *unit_final_absence_set_table;
4764 /* The following function forms list of reservation sets for given
4765 PATTERN_LIST. */
4766 static pattern_reserv_t
4767 form_reserv_sets_list (pattern_list)
4768 pattern_set_el_t pattern_list;
4770 pattern_set_el_t el;
4771 pattern_reserv_t first, curr, prev;
4772 int i;
4774 prev = first = NULL;
4775 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4777 curr = create_node (sizeof (struct pattern_reserv));
4778 curr->reserv = alloc_empty_reserv_sets ();
4779 curr->next_pattern_reserv = NULL;
4780 for (i = 0; i < el->units_num; i++)
4782 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4783 el->unit_decls [i]->in_set_p = TRUE;
4785 if (prev != NULL)
4786 prev->next_pattern_reserv = curr;
4787 else
4788 first = curr;
4789 prev = curr;
4791 return first;
4794 /* The following function forms the array containing presence and
4795 absence pattern sets for each unit. */
4796 static void
4797 initiate_presence_absence_pattern_sets ()
4799 decl_t decl;
4800 int i;
4802 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4803 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4804 obstack_finish (&irp);
4805 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4806 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4807 obstack_finish (&irp);
4808 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4809 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4810 obstack_finish (&irp);
4811 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4812 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4813 obstack_finish (&irp);
4814 /* Evaluate unit presence/absence sets. */
4815 for (i = 0; i < description->decls_num; i++)
4817 decl = description->decls [i];
4818 if (decl->mode == dm_unit)
4820 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4821 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4822 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4823 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4824 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4825 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4826 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4827 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4832 /* The function checks that CHECKED_SET satisfies all presence pattern
4833 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4834 is ok. */
4835 static int
4836 check_presence_pattern_sets (checked_set, origional_set, final_p)
4837 reserv_sets_t checked_set, origional_set;
4838 int final_p;
4840 int char_num;
4841 int chars_num;
4842 int i;
4843 int start_unit_num;
4844 int unit_num;
4845 int presence_p;
4846 pattern_reserv_t pat_reserv;
4848 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4849 for (char_num = 0; char_num < chars_num; char_num++)
4850 if (((unsigned char *) origional_set) [char_num])
4851 for (i = CHAR_BIT - 1; i >= 0; i--)
4852 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4854 start_unit_num = char_num * CHAR_BIT + i;
4855 if (start_unit_num >= description->units_num)
4856 break;
4857 if ((final_p
4858 && unit_final_presence_set_table [start_unit_num] == NULL)
4859 || (!final_p
4860 && unit_presence_set_table [start_unit_num] == NULL))
4861 continue;
4862 presence_p = FALSE;
4863 for (pat_reserv = (final_p
4864 ? unit_final_presence_set_table [start_unit_num]
4865 : unit_presence_set_table [start_unit_num]);
4866 pat_reserv != NULL;
4867 pat_reserv = pat_reserv->next_pattern_reserv)
4869 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4870 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4871 != pat_reserv->reserv [unit_num])
4872 break;
4873 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4875 if (!presence_p)
4876 return FALSE;
4878 return TRUE;
4881 /* The function checks that CHECKED_SET satisfies all absence pattern
4882 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4883 is ok. */
4884 static int
4885 check_absence_pattern_sets (checked_set, origional_set, final_p)
4886 reserv_sets_t checked_set, origional_set;
4887 int final_p;
4889 int char_num;
4890 int chars_num;
4891 int i;
4892 int start_unit_num;
4893 int unit_num;
4894 pattern_reserv_t pat_reserv;
4896 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4897 for (char_num = 0; char_num < chars_num; char_num++)
4898 if (((unsigned char *) origional_set) [char_num])
4899 for (i = CHAR_BIT - 1; i >= 0; i--)
4900 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4902 start_unit_num = char_num * CHAR_BIT + i;
4903 if (start_unit_num >= description->units_num)
4904 break;
4905 for (pat_reserv = (final_p
4906 ? unit_final_absence_set_table [start_unit_num]
4907 : unit_absence_set_table [start_unit_num]);
4908 pat_reserv != NULL;
4909 pat_reserv = pat_reserv->next_pattern_reserv)
4911 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4912 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4913 != pat_reserv->reserv [unit_num]
4914 && pat_reserv->reserv [unit_num])
4915 break;
4916 if (unit_num >= els_in_cycle_reserv)
4917 return FALSE;
4920 return TRUE;
4925 /* This page contains code for transformation of original reservations
4926 described in .md file. The main goal of transformations is
4927 simplifying reservation and lifting up all `|' on the top of IR
4928 reservation representation. */
4931 /* The following function makes copy of IR representation of
4932 reservation. The function also substitutes all reservations
4933 defined by define_reservation by corresponding value during making
4934 the copy. */
4935 static regexp_t
4936 copy_insn_regexp (regexp)
4937 regexp_t regexp;
4939 regexp_t result;
4940 int i;
4942 if (regexp->mode == rm_reserv)
4943 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4944 else if (regexp->mode == rm_unit)
4945 result = copy_node (regexp, sizeof (struct regexp));
4946 else if (regexp->mode == rm_repeat)
4948 result = copy_node (regexp, sizeof (struct regexp));
4949 REGEXP_REPEAT (result)->regexp
4950 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4952 else if (regexp->mode == rm_sequence)
4954 result = copy_node (regexp,
4955 sizeof (struct regexp) + sizeof (regexp_t)
4956 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4957 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4958 REGEXP_SEQUENCE (result)->regexps [i]
4959 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4961 else if (regexp->mode == rm_allof)
4963 result = copy_node (regexp,
4964 sizeof (struct regexp) + sizeof (regexp_t)
4965 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4966 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4967 REGEXP_ALLOF (result)->regexps [i]
4968 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4970 else if (regexp->mode == rm_oneof)
4972 result = copy_node (regexp,
4973 sizeof (struct regexp) + sizeof (regexp_t)
4974 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4975 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4976 REGEXP_ONEOF (result)->regexps [i]
4977 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4979 else
4981 if (regexp->mode != rm_nothing)
4982 abort ();
4983 result = copy_node (regexp, sizeof (struct regexp));
4985 return result;
4988 /* The following variable is set up 1 if a transformation has been
4989 applied. */
4990 static int regexp_transformed_p;
4992 /* The function makes transformation
4993 A*N -> A, A, ... */
4994 static regexp_t
4995 transform_1 (regexp)
4996 regexp_t regexp;
4998 int i;
4999 int repeat_num;
5000 regexp_t operand;
5001 pos_t pos;
5003 if (regexp->mode == rm_repeat)
5005 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
5006 if (repeat_num <= 1)
5007 abort ();
5008 operand = REGEXP_REPEAT (regexp)->regexp;
5009 pos = regexp->mode;
5010 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
5011 * (repeat_num - 1));
5012 regexp->mode = rm_sequence;
5013 regexp->pos = pos;
5014 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
5015 for (i = 0; i < repeat_num; i++)
5016 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
5017 regexp_transformed_p = 1;
5019 return regexp;
5022 /* The function makes transformations
5023 ...,(A,B,...),C,... -> ...,A,B,...,C,...
5024 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
5025 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
5026 static regexp_t
5027 transform_2 (regexp)
5028 regexp_t regexp;
5030 if (regexp->mode == rm_sequence)
5032 regexp_t sequence = NULL;
5033 regexp_t result;
5034 int sequence_index = 0;
5035 int i, j;
5037 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5038 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
5040 sequence_index = i;
5041 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
5042 break;
5044 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
5046 if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
5047 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
5048 abort ();
5049 result = create_node (sizeof (struct regexp)
5050 + sizeof (regexp_t)
5051 * (REGEXP_SEQUENCE (regexp)->regexps_num
5052 + REGEXP_SEQUENCE (sequence)->regexps_num
5053 - 2));
5054 result->mode = rm_sequence;
5055 result->pos = regexp->pos;
5056 REGEXP_SEQUENCE (result)->regexps_num
5057 = (REGEXP_SEQUENCE (regexp)->regexps_num
5058 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
5059 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5060 if (i < sequence_index)
5061 REGEXP_SEQUENCE (result)->regexps [i]
5062 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
5063 else if (i > sequence_index)
5064 REGEXP_SEQUENCE (result)->regexps
5065 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
5066 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
5067 else
5068 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
5069 REGEXP_SEQUENCE (result)->regexps [i + j]
5070 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
5071 regexp_transformed_p = 1;
5072 regexp = result;
5075 else if (regexp->mode == rm_allof)
5077 regexp_t allof = NULL;
5078 regexp_t result;
5079 int allof_index = 0;
5080 int i, j;
5082 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5083 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
5085 allof_index = i;
5086 allof = REGEXP_ALLOF (regexp)->regexps [i];
5087 break;
5089 if (i < REGEXP_ALLOF (regexp)->regexps_num)
5091 if (REGEXP_ALLOF (allof)->regexps_num <= 1
5092 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5093 abort ();
5094 result = create_node (sizeof (struct regexp)
5095 + sizeof (regexp_t)
5096 * (REGEXP_ALLOF (regexp)->regexps_num
5097 + REGEXP_ALLOF (allof)->regexps_num - 2));
5098 result->mode = rm_allof;
5099 result->pos = regexp->pos;
5100 REGEXP_ALLOF (result)->regexps_num
5101 = (REGEXP_ALLOF (regexp)->regexps_num
5102 + REGEXP_ALLOF (allof)->regexps_num - 1);
5103 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5104 if (i < allof_index)
5105 REGEXP_ALLOF (result)->regexps [i]
5106 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
5107 else if (i > allof_index)
5108 REGEXP_ALLOF (result)->regexps
5109 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
5110 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
5111 else
5112 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
5113 REGEXP_ALLOF (result)->regexps [i + j]
5114 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
5115 regexp_transformed_p = 1;
5116 regexp = result;
5119 else if (regexp->mode == rm_oneof)
5121 regexp_t oneof = NULL;
5122 regexp_t result;
5123 int oneof_index = 0;
5124 int i, j;
5126 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5127 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
5129 oneof_index = i;
5130 oneof = REGEXP_ONEOF (regexp)->regexps [i];
5131 break;
5133 if (i < REGEXP_ONEOF (regexp)->regexps_num)
5135 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5136 || REGEXP_ONEOF (regexp)->regexps_num <= 1)
5137 abort ();
5138 result = create_node (sizeof (struct regexp)
5139 + sizeof (regexp_t)
5140 * (REGEXP_ONEOF (regexp)->regexps_num
5141 + REGEXP_ONEOF (oneof)->regexps_num - 2));
5142 result->mode = rm_oneof;
5143 result->pos = regexp->pos;
5144 REGEXP_ONEOF (result)->regexps_num
5145 = (REGEXP_ONEOF (regexp)->regexps_num
5146 + REGEXP_ONEOF (oneof)->regexps_num - 1);
5147 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5148 if (i < oneof_index)
5149 REGEXP_ONEOF (result)->regexps [i]
5150 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
5151 else if (i > oneof_index)
5152 REGEXP_ONEOF (result)->regexps
5153 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
5154 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
5155 else
5156 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
5157 REGEXP_ONEOF (result)->regexps [i + j]
5158 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
5159 regexp_transformed_p = 1;
5160 regexp = result;
5163 return regexp;
5166 /* The function makes transformations
5167 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
5168 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
5169 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
5170 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
5171 static regexp_t
5172 transform_3 (regexp)
5173 regexp_t regexp;
5175 if (regexp->mode == rm_sequence)
5177 regexp_t oneof = NULL;
5178 int oneof_index = 0;
5179 regexp_t result;
5180 regexp_t sequence;
5181 int i, j;
5183 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5184 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
5186 oneof_index = i;
5187 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
5188 break;
5190 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
5192 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5193 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
5194 abort ();
5195 result = create_node (sizeof (struct regexp)
5196 + sizeof (regexp_t)
5197 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5198 result->mode = rm_oneof;
5199 result->pos = regexp->pos;
5200 REGEXP_ONEOF (result)->regexps_num
5201 = REGEXP_ONEOF (oneof)->regexps_num;
5202 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5204 sequence
5205 = create_node (sizeof (struct regexp)
5206 + sizeof (regexp_t)
5207 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
5208 sequence->mode = rm_sequence;
5209 sequence->pos = regexp->pos;
5210 REGEXP_SEQUENCE (sequence)->regexps_num
5211 = REGEXP_SEQUENCE (regexp)->regexps_num;
5212 REGEXP_ONEOF (result)->regexps [i] = sequence;
5213 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
5214 if (j != oneof_index)
5215 REGEXP_SEQUENCE (sequence)->regexps [j]
5216 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
5217 else
5218 REGEXP_SEQUENCE (sequence)->regexps [j]
5219 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5221 regexp_transformed_p = 1;
5222 regexp = result;
5225 else if (regexp->mode == rm_allof)
5227 regexp_t oneof = NULL;
5228 regexp_t seq;
5229 int oneof_index = 0;
5230 int max_seq_length, allof_length;
5231 regexp_t result;
5232 regexp_t allof = NULL;
5233 regexp_t allof_op = NULL;
5234 int i, j;
5236 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5237 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
5239 oneof_index = i;
5240 oneof = REGEXP_ALLOF (regexp)->regexps [i];
5241 break;
5243 if (i < REGEXP_ALLOF (regexp)->regexps_num)
5245 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5246 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5247 abort ();
5248 result = create_node (sizeof (struct regexp)
5249 + sizeof (regexp_t)
5250 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5251 result->mode = rm_oneof;
5252 result->pos = regexp->pos;
5253 REGEXP_ONEOF (result)->regexps_num
5254 = REGEXP_ONEOF (oneof)->regexps_num;
5255 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5257 allof
5258 = create_node (sizeof (struct regexp)
5259 + sizeof (regexp_t)
5260 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
5261 allof->mode = rm_allof;
5262 allof->pos = regexp->pos;
5263 REGEXP_ALLOF (allof)->regexps_num
5264 = REGEXP_ALLOF (regexp)->regexps_num;
5265 REGEXP_ONEOF (result)->regexps [i] = allof;
5266 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
5267 if (j != oneof_index)
5268 REGEXP_ALLOF (allof)->regexps [j]
5269 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
5270 else
5271 REGEXP_ALLOF (allof)->regexps [j]
5272 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5274 regexp_transformed_p = 1;
5275 regexp = result;
5277 max_seq_length = 0;
5278 if (regexp->mode == rm_allof)
5279 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5281 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
5283 seq = REGEXP_ALLOF (regexp)->regexps [i];
5284 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
5285 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
5287 else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit
5288 && REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_nothing)
5290 max_seq_length = 0;
5291 break;
5294 if (max_seq_length != 0)
5296 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5297 abort ();
5298 result = create_node (sizeof (struct regexp)
5299 + sizeof (regexp_t) * (max_seq_length - 1));
5300 result->mode = rm_sequence;
5301 result->pos = regexp->pos;
5302 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5303 for (i = 0; i < max_seq_length; i++)
5305 allof_length = 0;
5306 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5307 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5308 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5309 ->regexps [j])->regexps_num)))
5311 allof_op
5312 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5313 ->regexps [i]);
5314 allof_length++;
5316 else if (i == 0
5317 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5318 == rm_unit
5319 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5320 == rm_nothing)))
5322 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5323 allof_length++;
5325 if (allof_length == 1)
5326 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5327 else
5329 allof = create_node (sizeof (struct regexp)
5330 + sizeof (regexp_t)
5331 * (allof_length - 1));
5332 allof->mode = rm_allof;
5333 allof->pos = regexp->pos;
5334 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5335 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5336 allof_length = 0;
5337 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5338 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5339 && (i <
5340 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5341 ->regexps [j])->regexps_num)))
5343 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5344 ->regexps [j])
5345 ->regexps [i]);
5346 REGEXP_ALLOF (allof)->regexps [allof_length]
5347 = allof_op;
5348 allof_length++;
5350 else if (i == 0
5351 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5352 == rm_unit
5353 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5354 == rm_nothing)))
5356 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5357 REGEXP_ALLOF (allof)->regexps [allof_length]
5358 = allof_op;
5359 allof_length++;
5363 regexp_transformed_p = 1;
5364 regexp = result;
5367 return regexp;
5370 /* The function traverses IR of reservation and applies transformations
5371 implemented by FUNC. */
5372 static regexp_t
5373 regexp_transform_func (regexp, func)
5374 regexp_t regexp;
5375 regexp_t (*func) PARAMS ((regexp_t regexp));
5377 int i;
5379 if (regexp->mode == rm_sequence)
5380 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5381 REGEXP_SEQUENCE (regexp)->regexps [i]
5382 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5383 else if (regexp->mode == rm_allof)
5384 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5385 REGEXP_ALLOF (regexp)->regexps [i]
5386 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5387 else if (regexp->mode == rm_oneof)
5388 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5389 REGEXP_ONEOF (regexp)->regexps [i]
5390 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5391 else if (regexp->mode == rm_repeat)
5392 REGEXP_REPEAT (regexp)->regexp
5393 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5394 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5395 abort ();
5396 return (*func) (regexp);
5399 /* The function applies all transformations for IR representation of
5400 reservation REGEXP. */
5401 static regexp_t
5402 transform_regexp (regexp)
5403 regexp_t regexp;
5405 regexp = regexp_transform_func (regexp, transform_1);
5408 regexp_transformed_p = 0;
5409 regexp = regexp_transform_func (regexp, transform_2);
5410 regexp = regexp_transform_func (regexp, transform_3);
5412 while (regexp_transformed_p);
5413 return regexp;
5416 /* The function applies all transformations for reservations of all
5417 insn declarations. */
5418 static void
5419 transform_insn_regexps ()
5421 decl_t decl;
5422 int i;
5424 transform_time = create_ticker ();
5425 add_advance_cycle_insn_decl ();
5426 fprintf (stderr, "Reservation transformation...");
5427 fflush (stderr);
5428 for (i = 0; i < description->decls_num; i++)
5430 decl = description->decls [i];
5431 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5432 DECL_INSN_RESERV (decl)->transformed_regexp
5433 = transform_regexp (copy_insn_regexp
5434 (DECL_INSN_RESERV (decl)->regexp));
5436 fprintf (stderr, "done\n");
5437 ticker_off (&transform_time);
5438 fflush (stderr);
5443 /* The following variable value is TRUE if the first annotated message
5444 about units to automata distribution has been output. */
5445 static int annotation_message_reported_p;
5447 /* The following structure describes usage of a unit in a reservation. */
5448 struct unit_usage
5450 unit_decl_t unit_decl;
5451 /* The following forms a list of units used on the same cycle in the
5452 same alternative. */
5453 struct unit_usage *next;
5456 /* Obstack for unit_usage structures. */
5457 static struct obstack unit_usages;
5459 /* VLA for representation of array of pointers to unit usage
5460 structures. There is an element for each combination of
5461 (alternative number, cycle). Unit usages on given cycle in
5462 alternative with given number are referred through element with
5463 index equals to the cycle * number of all alternatives in the regexp
5464 + the alternative number. */
5465 static vla_ptr_t cycle_alt_unit_usages;
5467 /* The following function creates the structure unit_usage for UNIT on
5468 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5469 accessed through cycle_alt_unit_usages. */
5470 static void
5471 store_alt_unit_usage (regexp, unit, cycle, alt_num)
5472 regexp_t regexp;
5473 regexp_t unit;
5474 int cycle;
5475 int alt_num;
5477 size_t i, length, old_length;
5478 unit_decl_t unit_decl;
5479 struct unit_usage *unit_usage_ptr;
5480 int index;
5482 if (regexp == NULL || regexp->mode != rm_oneof
5483 || alt_num >= REGEXP_ONEOF (regexp)->regexps_num)
5484 abort ();
5485 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5486 old_length = VLA_PTR_LENGTH (cycle_alt_unit_usages);
5487 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
5488 if (old_length < length)
5490 VLA_PTR_EXPAND (cycle_alt_unit_usages, length - old_length);
5491 for (i = old_length; i < length; i++)
5492 VLA_PTR (cycle_alt_unit_usages, i) = NULL;
5494 obstack_blank (&unit_usages, sizeof (struct unit_usage));
5495 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5496 obstack_finish (&unit_usages);
5497 unit_usage_ptr->unit_decl = unit_decl;
5498 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5499 unit_usage_ptr->next = VLA_PTR (cycle_alt_unit_usages, index);
5500 VLA_PTR (cycle_alt_unit_usages, index) = unit_usage_ptr;
5501 unit_decl->last_distribution_check_cycle = -1; /* undefined */
5504 /* The function processes given REGEXP to find units with the wrong
5505 distribution. */
5506 static void
5507 check_regexp_units_distribution (insn_reserv_name, regexp)
5508 const char *insn_reserv_name;
5509 regexp_t regexp;
5511 int i, j, k, cycle;
5512 regexp_t seq, allof, unit;
5513 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
5515 if (regexp == NULL || regexp->mode != rm_oneof)
5516 return;
5517 /* Store all unit usages in the regexp: */
5518 obstack_init (&unit_usages);
5519 VLA_PTR_CREATE (cycle_alt_unit_usages, 100, "unit usages on cycles");
5520 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5522 seq = REGEXP_ONEOF (regexp)->regexps [i];
5523 if (seq->mode == rm_sequence)
5524 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5526 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5527 if (allof->mode == rm_allof)
5528 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5530 unit = REGEXP_ALLOF (allof)->regexps [k];
5531 if (unit->mode == rm_unit)
5532 store_alt_unit_usage (regexp, unit, j, i);
5533 else if (unit->mode != rm_nothing)
5534 abort ();
5536 else if (allof->mode == rm_unit)
5537 store_alt_unit_usage (regexp, allof, j, i);
5538 else if (allof->mode != rm_nothing)
5539 abort ();
5541 else if (seq->mode == rm_allof)
5542 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5544 unit = REGEXP_ALLOF (seq)->regexps [k];
5545 if (unit->mode == rm_unit)
5546 store_alt_unit_usage (regexp, unit, 0, i);
5547 else if (unit->mode != rm_nothing)
5548 abort ();
5550 else if (seq->mode == rm_unit)
5551 store_alt_unit_usage (regexp, seq, 0, i);
5552 else if (seq->mode != rm_nothing)
5553 abort ();
5555 /* Check distribution: */
5556 for (i = 0; i < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages); i++)
5558 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5559 for (unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages, i);
5560 unit_usage_ptr != NULL;
5561 unit_usage_ptr = unit_usage_ptr->next)
5562 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5564 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5565 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5566 k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages)
5567 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5568 k++)
5570 for (other_unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages, k);
5571 other_unit_usage_ptr != NULL;
5572 other_unit_usage_ptr = other_unit_usage_ptr->next)
5573 if (unit_usage_ptr->unit_decl->automaton_decl
5574 == other_unit_usage_ptr->unit_decl->automaton_decl)
5575 break;
5576 if (other_unit_usage_ptr == NULL
5577 && VLA_PTR (cycle_alt_unit_usages, k) != NULL)
5578 break;
5580 if (k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages)
5581 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5583 if (!annotation_message_reported_p)
5585 fprintf (stderr, "\n");
5586 error ("The following units do not satisfy units-automata distribution rule");
5587 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5588 annotation_message_reported_p = TRUE;
5590 error ("Unit %s, reserv. %s, cycle %d",
5591 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5592 cycle);
5596 VLA_PTR_DELETE (cycle_alt_unit_usages);
5597 obstack_free (&unit_usages, NULL);
5600 /* The function finds units which violates units to automata
5601 distribution rule. If the units exist, report about them. */
5602 static void
5603 check_unit_distributions_to_automata ()
5605 decl_t decl;
5606 int i;
5608 fprintf (stderr, "Check unit distributions to automata...");
5609 annotation_message_reported_p = FALSE;
5610 for (i = 0; i < description->decls_num; i++)
5612 decl = description->decls [i];
5613 if (decl->mode == dm_insn_reserv)
5614 check_regexp_units_distribution
5615 (DECL_INSN_RESERV (decl)->name,
5616 DECL_INSN_RESERV (decl)->transformed_regexp);
5618 fprintf (stderr, "done\n");
5623 /* The page contains code for building alt_states (see comments for
5624 IR) describing all possible insns reservations of an automaton. */
5626 /* Current state being formed for which the current alt_state
5627 refers. */
5628 static state_t state_being_formed;
5630 /* Current alt_state being formed. */
5631 static alt_state_t alt_state_being_formed;
5633 /* This recursive function processes `,' and units in reservation
5634 REGEXP for forming alt_states of AUTOMATON. It is believed that
5635 CURR_CYCLE is start cycle of all reservation REGEXP. */
5636 static int
5637 process_seq_for_forming_states (regexp, automaton, curr_cycle)
5638 regexp_t regexp;
5639 automaton_t automaton;
5640 int curr_cycle;
5642 int i;
5644 if (regexp == NULL)
5645 return curr_cycle;
5646 else if (regexp->mode == rm_unit)
5648 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5649 == automaton->automaton_order_num)
5650 set_state_reserv (state_being_formed, curr_cycle,
5651 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5652 return curr_cycle;
5654 else if (regexp->mode == rm_sequence)
5656 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5657 curr_cycle
5658 = process_seq_for_forming_states
5659 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5660 return curr_cycle;
5662 else if (regexp->mode == rm_allof)
5664 int finish_cycle = 0;
5665 int cycle;
5667 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5669 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5670 ->regexps [i],
5671 automaton, curr_cycle);
5672 if (finish_cycle < cycle)
5673 finish_cycle = cycle;
5675 return finish_cycle;
5677 else
5679 if (regexp->mode != rm_nothing)
5680 abort ();
5681 return curr_cycle;
5685 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5686 inserts alt_state into the table. */
5687 static void
5688 finish_forming_alt_state (alt_state, automaton)
5689 alt_state_t alt_state;
5690 automaton_t automaton ATTRIBUTE_UNUSED;
5692 state_t state_in_table;
5693 state_t corresponding_state;
5695 corresponding_state = alt_state->state;
5696 state_in_table = insert_state (corresponding_state);
5697 if (state_in_table != corresponding_state)
5699 free_state (corresponding_state);
5700 alt_state->state = state_in_table;
5704 /* The following variable value is current automaton insn for whose
5705 reservation the alt states are created. */
5706 static ainsn_t curr_ainsn;
5708 /* This recursive function processes `|' in reservation REGEXP for
5709 forming alt_states of AUTOMATON. List of the alt states should
5710 have the same order as in the description. */
5711 static void
5712 process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5713 regexp_t regexp;
5714 automaton_t automaton;
5715 int inside_oneof_p;
5717 int i;
5719 if (regexp->mode != rm_oneof)
5721 alt_state_being_formed = get_free_alt_state ();
5722 state_being_formed = get_free_state (1, automaton);
5723 alt_state_being_formed->state = state_being_formed;
5724 /* We inserts in reverse order but we process alternatives also
5725 in reverse order. So we have the same order of alternative
5726 as in the description. */
5727 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5728 curr_ainsn->alt_states = alt_state_being_formed;
5729 (void) process_seq_for_forming_states (regexp, automaton, 0);
5730 finish_forming_alt_state (alt_state_being_formed, automaton);
5732 else
5734 if (inside_oneof_p)
5735 abort ();
5736 /* We processes it in reverse order to get list with the same
5737 order as in the description. See also the previous
5738 commentary. */
5739 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5740 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5741 automaton, 1);
5745 /* Create nodes alt_state for all AUTOMATON insns. */
5746 static void
5747 create_alt_states (automaton)
5748 automaton_t automaton;
5750 struct insn_reserv_decl *reserv_decl;
5752 for (curr_ainsn = automaton->ainsn_list;
5753 curr_ainsn != NULL;
5754 curr_ainsn = curr_ainsn->next_ainsn)
5756 reserv_decl = curr_ainsn->insn_reserv_decl;
5757 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5759 curr_ainsn->alt_states = NULL;
5760 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5761 automaton, 0);
5762 curr_ainsn->sorted_alt_states
5763 = uniq_sort_alt_states (curr_ainsn->alt_states);
5770 /* The page contains major code for building DFA(s) for fast pipeline
5771 hazards recognition. */
5773 /* The function forms list of ainsns of AUTOMATON with the same
5774 reservation. */
5775 static void
5776 form_ainsn_with_same_reservs (automaton)
5777 automaton_t automaton;
5779 ainsn_t curr_ainsn;
5780 size_t i;
5781 vla_ptr_t first_insns;
5782 vla_ptr_t last_insns;
5784 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5785 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5786 for (curr_ainsn = automaton->ainsn_list;
5787 curr_ainsn != NULL;
5788 curr_ainsn = curr_ainsn->next_ainsn)
5789 if (curr_ainsn->insn_reserv_decl
5790 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5792 curr_ainsn->next_same_reservs_insn = NULL;
5793 curr_ainsn->first_insn_with_same_reservs = 1;
5795 else
5797 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5798 if (alt_states_eq
5799 (curr_ainsn->sorted_alt_states,
5800 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5801 break;
5802 curr_ainsn->next_same_reservs_insn = NULL;
5803 if (i < VLA_PTR_LENGTH (first_insns))
5805 curr_ainsn->first_insn_with_same_reservs = 0;
5806 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5807 = curr_ainsn;
5808 VLA_PTR (last_insns, i) = curr_ainsn;
5810 else
5812 VLA_PTR_ADD (first_insns, curr_ainsn);
5813 VLA_PTR_ADD (last_insns, curr_ainsn);
5814 curr_ainsn->first_insn_with_same_reservs = 1;
5817 VLA_PTR_DELETE (first_insns);
5818 VLA_PTR_DELETE (last_insns);
5821 /* Forming unit reservations which can affect creating the automaton
5822 states achieved from a given state. It permits to build smaller
5823 automata in many cases. We would have the same automata after
5824 the minimization without such optimization, but the automaton
5825 right after the building could be huge. So in other words, usage
5826 of reservs_matter means some minimization during building the
5827 automaton. */
5828 static reserv_sets_t
5829 form_reservs_matter (automaton)
5830 automaton_t automaton;
5832 int cycle, unit;
5833 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5835 for (cycle = 0; cycle < max_cycles_num; cycle++)
5836 for (unit = 0; unit < description->units_num; unit++)
5837 if (units_array [unit]->automaton_decl
5838 == automaton->corresponding_automaton_decl
5839 && (cycle >= units_array [unit]->min_occ_cycle_num
5840 /* We can not remove queried unit from reservations. */
5841 || units_array [unit]->query_p
5842 /* We can not remove units which are used
5843 `exclusion_set', `presence_set',
5844 `final_presence_set', `absence_set', and
5845 `final_absence_set'. */
5846 || units_array [unit]->in_set_p))
5847 set_unit_reserv (reservs_matter, cycle, unit);
5848 return reservs_matter;
5851 /* The following function creates all states of nondeterministic (if
5852 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5853 static void
5854 make_automaton (automaton)
5855 automaton_t automaton;
5857 ainsn_t ainsn;
5858 struct insn_reserv_decl *insn_reserv_decl;
5859 alt_state_t alt_state;
5860 state_t state;
5861 state_t start_state;
5862 state_t state2;
5863 ainsn_t advance_cycle_ainsn;
5864 arc_t added_arc;
5865 vla_ptr_t state_stack;
5866 int states_n;
5867 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5869 VLA_PTR_CREATE (state_stack, 150, "state stack");
5870 /* Create the start state (empty state). */
5871 start_state = insert_state (get_free_state (1, automaton));
5872 automaton->start_state = start_state;
5873 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5874 VLA_PTR_ADD (state_stack, start_state);
5875 states_n = 1;
5876 while (VLA_PTR_LENGTH (state_stack) != 0)
5878 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5879 VLA_PTR_SHORTEN (state_stack, 1);
5880 advance_cycle_ainsn = NULL;
5881 for (ainsn = automaton->ainsn_list;
5882 ainsn != NULL;
5883 ainsn = ainsn->next_ainsn)
5884 if (ainsn->first_insn_with_same_reservs)
5886 insn_reserv_decl = ainsn->insn_reserv_decl;
5887 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5889 /* We process alt_states in the same order as they are
5890 present in the description. */
5891 added_arc = NULL;
5892 for (alt_state = ainsn->alt_states;
5893 alt_state != NULL;
5894 alt_state = alt_state->next_alt_state)
5896 state2 = alt_state->state;
5897 if (!intersected_state_reservs_p (state, state2))
5899 state2 = states_union (state, state2, reservs_matter);
5900 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5902 state2->it_was_placed_in_stack_for_NDFA_forming
5903 = 1;
5904 VLA_PTR_ADD (state_stack, state2);
5905 states_n++;
5906 if (states_n % 100 == 0)
5907 fprintf (stderr, "*");
5909 added_arc = add_arc (state, state2, ainsn, 1);
5910 if (!ndfa_flag)
5911 break;
5914 if (!ndfa_flag && added_arc != NULL)
5916 added_arc->state_alts = 0;
5917 for (alt_state = ainsn->alt_states;
5918 alt_state != NULL;
5919 alt_state = alt_state->next_alt_state)
5921 state2 = alt_state->state;
5922 if (!intersected_state_reservs_p (state, state2))
5923 added_arc->state_alts++;
5927 else
5928 advance_cycle_ainsn = ainsn;
5930 /* Add transition to advance cycle. */
5931 state2 = state_shift (state, reservs_matter);
5932 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5934 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5935 VLA_PTR_ADD (state_stack, state2);
5936 states_n++;
5937 if (states_n % 100 == 0)
5938 fprintf (stderr, "*");
5940 if (advance_cycle_ainsn == NULL)
5941 abort ();
5942 add_arc (state, state2, advance_cycle_ainsn, 1);
5944 VLA_PTR_DELETE (state_stack);
5947 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5948 static void
5949 form_arcs_marked_by_insn (state)
5950 state_t state;
5952 decl_t decl;
5953 arc_t arc;
5954 int i;
5956 for (i = 0; i < description->decls_num; i++)
5958 decl = description->decls [i];
5959 if (decl->mode == dm_insn_reserv)
5960 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5962 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5964 if (arc->insn == NULL)
5965 abort ();
5966 arc->next_arc_marked_by_insn
5967 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5968 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5972 /* The function creates composed state (see comments for IR) from
5973 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5974 same insn. If the composed state is not in STATE_STACK yet, it is
5975 pushed into STATE_STACK. */
5976 static int
5977 create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5978 state_t original_state;
5979 arc_t arcs_marked_by_insn;
5980 vla_ptr_t *state_stack;
5982 state_t state;
5983 alt_state_t alt_state, curr_alt_state;
5984 alt_state_t new_alt_state;
5985 arc_t curr_arc;
5986 arc_t next_arc;
5987 state_t state_in_table;
5988 state_t temp_state;
5989 alt_state_t canonical_alt_states_list;
5990 int alts_number;
5991 int new_state_p = 0;
5993 if (arcs_marked_by_insn == NULL)
5994 return new_state_p;
5995 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5996 state = arcs_marked_by_insn->to_state;
5997 else
5999 if (!ndfa_flag)
6000 abort ();
6001 /* Create composed state. */
6002 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
6003 curr_alt_state = NULL;
6004 for (curr_arc = arcs_marked_by_insn;
6005 curr_arc != NULL;
6006 curr_arc = curr_arc->next_arc_marked_by_insn)
6007 if (curr_arc->to_state->component_states == NULL)
6009 new_alt_state = get_free_alt_state ();
6010 new_alt_state->next_alt_state = curr_alt_state;
6011 new_alt_state->state = curr_arc->to_state;
6012 curr_alt_state = new_alt_state;
6014 else
6015 for (alt_state = curr_arc->to_state->component_states;
6016 alt_state != NULL;
6017 alt_state = alt_state->next_sorted_alt_state)
6019 new_alt_state = get_free_alt_state ();
6020 new_alt_state->next_alt_state = curr_alt_state;
6021 new_alt_state->state = alt_state->state;
6022 if (alt_state->state->component_states != NULL)
6023 abort ();
6024 curr_alt_state = new_alt_state;
6026 /* There are not identical sets in the alt state list. */
6027 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
6028 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
6030 temp_state = state;
6031 state = canonical_alt_states_list->state;
6032 free_state (temp_state);
6034 else
6036 state->component_states = canonical_alt_states_list;
6037 state_in_table = insert_state (state);
6038 if (state_in_table != state)
6040 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
6041 abort ();
6042 free_state (state);
6043 state = state_in_table;
6045 else
6047 if (state->it_was_placed_in_stack_for_DFA_forming)
6048 abort ();
6049 new_state_p = 1;
6050 for (curr_alt_state = state->component_states;
6051 curr_alt_state != NULL;
6052 curr_alt_state = curr_alt_state->next_sorted_alt_state)
6053 for (curr_arc = first_out_arc (curr_alt_state->state);
6054 curr_arc != NULL;
6055 curr_arc = next_out_arc (curr_arc))
6056 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
6058 arcs_marked_by_insn->to_state = state;
6059 for (alts_number = 0,
6060 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
6061 curr_arc != NULL;
6062 curr_arc = next_arc)
6064 next_arc = curr_arc->next_arc_marked_by_insn;
6065 remove_arc (original_state, curr_arc);
6066 alts_number++;
6068 arcs_marked_by_insn->state_alts = alts_number;
6071 if (!state->it_was_placed_in_stack_for_DFA_forming)
6073 state->it_was_placed_in_stack_for_DFA_forming = 1;
6074 VLA_PTR_ADD (*state_stack, state);
6076 return new_state_p;
6079 /* The function transforms nondeterministic AUTOMATON into
6080 deterministic. */
6081 static void
6082 NDFA_to_DFA (automaton)
6083 automaton_t automaton;
6085 state_t start_state;
6086 state_t state;
6087 decl_t decl;
6088 vla_ptr_t state_stack;
6089 int i;
6090 int states_n;
6092 VLA_PTR_CREATE (state_stack, 150, "state stack");
6093 /* Create the start state (empty state). */
6094 start_state = automaton->start_state;
6095 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
6096 VLA_PTR_ADD (state_stack, start_state);
6097 states_n = 1;
6098 while (VLA_PTR_LENGTH (state_stack) != 0)
6100 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
6101 VLA_PTR_SHORTEN (state_stack, 1);
6102 form_arcs_marked_by_insn (state);
6103 for (i = 0; i < description->decls_num; i++)
6105 decl = description->decls [i];
6106 if (decl->mode == dm_insn_reserv
6107 && create_composed_state
6108 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
6109 &state_stack))
6111 states_n++;
6112 if (states_n % 100 == 0)
6113 fprintf (stderr, "*");
6117 VLA_PTR_DELETE (state_stack);
6120 /* The following variable value is current number (1, 2, ...) of passing
6121 graph of states. */
6122 static int curr_state_graph_pass_num;
6124 /* This recursive function passes all states achieved from START_STATE
6125 and applies APPLIED_FUNC to them. */
6126 static void
6127 pass_state_graph (start_state, applied_func)
6128 state_t start_state;
6129 void (*applied_func) PARAMS ((state_t state));
6131 arc_t arc;
6133 if (start_state->pass_num == curr_state_graph_pass_num)
6134 return;
6135 start_state->pass_num = curr_state_graph_pass_num;
6136 (*applied_func) (start_state);
6137 for (arc = first_out_arc (start_state);
6138 arc != NULL;
6139 arc = next_out_arc (arc))
6140 pass_state_graph (arc->to_state, applied_func);
6143 /* This recursive function passes all states of AUTOMATON and applies
6144 APPLIED_FUNC to them. */
6145 static void
6146 pass_states (automaton, applied_func)
6147 automaton_t automaton;
6148 void (*applied_func) PARAMS ((state_t state));
6150 curr_state_graph_pass_num++;
6151 pass_state_graph (automaton->start_state, applied_func);
6154 /* The function initializes code for passing of all states. */
6155 static void
6156 initiate_pass_states ()
6158 curr_state_graph_pass_num = 0;
6161 /* The following vla is used for storing pointers to all achieved
6162 states. */
6163 static vla_ptr_t all_achieved_states;
6165 /* This function is called by function pass_states to add an achieved
6166 STATE. */
6167 static void
6168 add_achieved_state (state)
6169 state_t state;
6171 VLA_PTR_ADD (all_achieved_states, state);
6174 /* The function sets up equivalence numbers of insns which mark all
6175 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
6176 nonzero value) or by equiv_class_num_2 of the destination state.
6177 The function returns number of out arcs of STATE. */
6178 static int
6179 set_out_arc_insns_equiv_num (state, odd_iteration_flag)
6180 state_t state;
6181 int odd_iteration_flag;
6183 int state_out_arcs_num;
6184 arc_t arc;
6186 state_out_arcs_num = 0;
6187 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6189 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
6190 || arc->insn->insn_reserv_decl->state_alts != 0)
6191 abort ();
6192 state_out_arcs_num++;
6193 arc->insn->insn_reserv_decl->equiv_class_num
6194 = (odd_iteration_flag
6195 ? arc->to_state->equiv_class_num_1
6196 : arc->to_state->equiv_class_num_2);
6197 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
6198 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
6199 || arc->insn->insn_reserv_decl->state_alts <= 0)
6200 abort ();
6202 return state_out_arcs_num;
6205 /* The function clears equivalence numbers and alt_states in all insns
6206 which mark all out arcs of STATE. */
6207 static void
6208 clear_arc_insns_equiv_num (state)
6209 state_t state;
6211 arc_t arc;
6213 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6215 arc->insn->insn_reserv_decl->equiv_class_num = 0;
6216 arc->insn->insn_reserv_decl->state_alts = 0;
6220 /* The function copies pointers to equivalent states from vla FROM
6221 into vla TO. */
6222 static void
6223 copy_equiv_class (to, from)
6224 vla_ptr_t *to;
6225 const vla_ptr_t *from;
6227 state_t *class_ptr;
6229 VLA_PTR_NULLIFY (*to);
6230 for (class_ptr = VLA_PTR_BEGIN (*from);
6231 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
6232 class_ptr++)
6233 VLA_PTR_ADD (*to, *class_ptr);
6236 /* The following function returns TRUE if STATE reserves the unit with
6237 UNIT_NUM on the first cycle. */
6238 static int
6239 first_cycle_unit_presence (state, unit_num)
6240 state_t state;
6241 int unit_num;
6243 int presence_p;
6245 if (state->component_states == NULL)
6246 presence_p = test_unit_reserv (state->reservs, 0, unit_num);
6247 else
6248 presence_p
6249 = test_unit_reserv (state->component_states->state->reservs,
6250 0, unit_num);
6251 return presence_p;
6254 /* The function returns nonzero value if STATE is not equivalent to
6255 ANOTHER_STATE from the same current partition on equivalence
6256 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
6257 output arcs. Iteration of making equivalence partition is defined
6258 by ODD_ITERATION_FLAG. */
6259 static int
6260 state_is_differed (state, another_state, another_state_out_arcs_num,
6261 odd_iteration_flag)
6262 state_t state, another_state;
6263 int another_state_out_arcs_num;
6264 int odd_iteration_flag;
6266 arc_t arc;
6267 int state_out_arcs_num;
6268 int i, presence1_p, presence2_p;
6270 state_out_arcs_num = 0;
6271 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6273 state_out_arcs_num++;
6274 if ((odd_iteration_flag
6275 ? arc->to_state->equiv_class_num_1
6276 : arc->to_state->equiv_class_num_2)
6277 != arc->insn->insn_reserv_decl->equiv_class_num
6278 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
6279 return 1;
6281 if (state_out_arcs_num != another_state_out_arcs_num)
6282 return 1;
6283 /* Now we are looking at the states with the point of view of query
6284 units. */
6285 for (i = 0; i < description->units_num; i++)
6286 if (units_array [i]->query_p)
6288 presence1_p = first_cycle_unit_presence (state, i);
6289 presence2_p = first_cycle_unit_presence (another_state, i);
6290 if ((presence1_p && !presence2_p) || (!presence1_p && presence2_p))
6291 return 1;
6293 return 0;
6296 /* The function makes initial partition of STATES on equivalent
6297 classes. */
6298 static state_t
6299 init_equiv_class (states, states_num)
6300 state_t *states;
6301 int states_num;
6303 state_t *state_ptr;
6304 state_t result_equiv_class;
6306 result_equiv_class = NULL;
6307 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
6309 (*state_ptr)->equiv_class_num_1 = 1;
6310 (*state_ptr)->next_equiv_class_state = result_equiv_class;
6311 result_equiv_class = *state_ptr;
6313 return result_equiv_class;
6316 /* The function processes equivalence class given by its pointer
6317 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
6318 are not equivalent states, the function partitions the class
6319 removing nonequivalent states and placing them in
6320 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6321 assigns it to the state equivalence number. If the class has been
6322 partitioned, the function returns nonzero value. */
6323 static int
6324 partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6325 next_iteration_classes, new_equiv_class_num_ptr)
6326 state_t *equiv_class_ptr;
6327 int odd_iteration_flag;
6328 vla_ptr_t *next_iteration_classes;
6329 int *new_equiv_class_num_ptr;
6331 state_t new_equiv_class;
6332 int partition_p;
6333 state_t first_state;
6334 state_t curr_state;
6335 state_t prev_state;
6336 state_t next_state;
6337 int out_arcs_num;
6339 partition_p = 0;
6340 if (*equiv_class_ptr == NULL)
6341 abort ();
6342 for (first_state = *equiv_class_ptr;
6343 first_state != NULL;
6344 first_state = new_equiv_class)
6346 new_equiv_class = NULL;
6347 if (first_state->next_equiv_class_state != NULL)
6349 /* There are more one states in the class equivalence. */
6350 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
6351 odd_iteration_flag);
6352 for (prev_state = first_state,
6353 curr_state = first_state->next_equiv_class_state;
6354 curr_state != NULL;
6355 curr_state = next_state)
6357 next_state = curr_state->next_equiv_class_state;
6358 if (state_is_differed (curr_state, first_state, out_arcs_num,
6359 odd_iteration_flag))
6361 /* Remove curr state from the class equivalence. */
6362 prev_state->next_equiv_class_state = next_state;
6363 /* Add curr state to the new class equivalence. */
6364 curr_state->next_equiv_class_state = new_equiv_class;
6365 if (new_equiv_class == NULL)
6366 (*new_equiv_class_num_ptr)++;
6367 if (odd_iteration_flag)
6368 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6369 else
6370 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6371 new_equiv_class = curr_state;
6372 partition_p = 1;
6374 else
6375 prev_state = curr_state;
6377 clear_arc_insns_equiv_num (first_state);
6379 if (new_equiv_class != NULL)
6380 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
6382 return partition_p;
6385 /* The function finds equivalent states of AUTOMATON. */
6386 static void
6387 evaluate_equiv_classes (automaton, equiv_classes)
6388 automaton_t automaton;
6389 vla_ptr_t *equiv_classes;
6391 state_t new_equiv_class;
6392 int new_equiv_class_num;
6393 int odd_iteration_flag;
6394 int finish_flag;
6395 vla_ptr_t next_iteration_classes;
6396 state_t *equiv_class_ptr;
6397 state_t *state_ptr;
6399 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6400 pass_states (automaton, add_achieved_state);
6401 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6402 VLA_PTR_LENGTH (all_achieved_states));
6403 odd_iteration_flag = 0;
6404 new_equiv_class_num = 1;
6405 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6406 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6409 odd_iteration_flag = !odd_iteration_flag;
6410 finish_flag = 1;
6411 copy_equiv_class (equiv_classes, &next_iteration_classes);
6412 /* Transfer equiv numbers for the next iteration. */
6413 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6414 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6415 state_ptr++)
6416 if (odd_iteration_flag)
6417 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6418 else
6419 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6420 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6421 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6422 equiv_class_ptr++)
6423 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6424 &next_iteration_classes,
6425 &new_equiv_class_num))
6426 finish_flag = 0;
6428 while (!finish_flag);
6429 VLA_PTR_DELETE (next_iteration_classes);
6430 VLA_PTR_DELETE (all_achieved_states);
6433 /* The function merges equivalent states of AUTOMATON. */
6434 static void
6435 merge_states (automaton, equiv_classes)
6436 automaton_t automaton;
6437 vla_ptr_t *equiv_classes;
6439 state_t *equiv_class_ptr;
6440 state_t curr_state;
6441 state_t new_state;
6442 state_t first_class_state;
6443 alt_state_t alt_states;
6444 alt_state_t alt_state, new_alt_state;
6445 arc_t curr_arc;
6446 arc_t next_arc;
6448 /* Create states corresponding to equivalence classes containing two
6449 or more states. */
6450 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6451 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6452 equiv_class_ptr++)
6453 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6455 /* There are more one states in the class equivalence. */
6456 /* Create new compound state. */
6457 new_state = get_free_state (0, automaton);
6458 alt_states = NULL;
6459 first_class_state = *equiv_class_ptr;
6460 for (curr_state = first_class_state;
6461 curr_state != NULL;
6462 curr_state = curr_state->next_equiv_class_state)
6464 curr_state->equiv_class_state = new_state;
6465 if (curr_state->component_states == NULL)
6467 new_alt_state = get_free_alt_state ();
6468 new_alt_state->state = curr_state;
6469 new_alt_state->next_alt_state = alt_states;
6470 alt_states = new_alt_state;
6472 else
6473 for (alt_state = curr_state->component_states;
6474 alt_state != NULL;
6475 alt_state = alt_state->next_sorted_alt_state)
6477 new_alt_state = get_free_alt_state ();
6478 new_alt_state->state = alt_state->state;
6479 new_alt_state->next_alt_state = alt_states;
6480 alt_states = new_alt_state;
6483 /* Its is important that alt states were sorted before and
6484 after merging to have the same quering results. */
6485 new_state->component_states = uniq_sort_alt_states (alt_states);
6487 else
6488 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6489 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6490 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6491 equiv_class_ptr++)
6492 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6494 first_class_state = *equiv_class_ptr;
6495 /* Create new arcs output from the state corresponding to
6496 equiv class. */
6497 for (curr_arc = first_out_arc (first_class_state);
6498 curr_arc != NULL;
6499 curr_arc = next_out_arc (curr_arc))
6500 add_arc (first_class_state->equiv_class_state,
6501 curr_arc->to_state->equiv_class_state,
6502 curr_arc->insn, curr_arc->state_alts);
6503 /* Delete output arcs from states of given class equivalence. */
6504 for (curr_state = first_class_state;
6505 curr_state != NULL;
6506 curr_state = curr_state->next_equiv_class_state)
6508 if (automaton->start_state == curr_state)
6509 automaton->start_state = curr_state->equiv_class_state;
6510 /* Delete the state and its output arcs. */
6511 for (curr_arc = first_out_arc (curr_state);
6512 curr_arc != NULL;
6513 curr_arc = next_arc)
6515 next_arc = next_out_arc (curr_arc);
6516 free_arc (curr_arc);
6520 else
6522 /* Change `to_state' of arcs output from the state of given
6523 equivalence class. */
6524 for (curr_arc = first_out_arc (*equiv_class_ptr);
6525 curr_arc != NULL;
6526 curr_arc = next_out_arc (curr_arc))
6527 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6531 /* The function sets up new_cycle_p for states if there is arc to the
6532 state marked by advance_cycle_insn_decl. */
6533 static void
6534 set_new_cycle_flags (state)
6535 state_t state;
6537 arc_t arc;
6539 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6540 if (arc->insn->insn_reserv_decl
6541 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6542 arc->to_state->new_cycle_p = 1;
6545 /* The top level function for minimization of deterministic
6546 AUTOMATON. */
6547 static void
6548 minimize_DFA (automaton)
6549 automaton_t automaton;
6551 vla_ptr_t equiv_classes;
6553 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6554 evaluate_equiv_classes (automaton, &equiv_classes);
6555 merge_states (automaton, &equiv_classes);
6556 pass_states (automaton, set_new_cycle_flags);
6557 VLA_PTR_DELETE (equiv_classes);
6560 /* Values of two variables are counted number of states and arcs in an
6561 automaton. */
6562 static int curr_counted_states_num;
6563 static int curr_counted_arcs_num;
6565 /* The function is called by function `pass_states' to count states
6566 and arcs of an automaton. */
6567 static void
6568 incr_states_and_arcs_nums (state)
6569 state_t state;
6571 arc_t arc;
6573 curr_counted_states_num++;
6574 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6575 curr_counted_arcs_num++;
6578 /* The function counts states and arcs of AUTOMATON. */
6579 static void
6580 count_states_and_arcs (automaton, states_num, arcs_num)
6581 automaton_t automaton;
6582 int *states_num;
6583 int *arcs_num;
6585 curr_counted_states_num = 0;
6586 curr_counted_arcs_num = 0;
6587 pass_states (automaton, incr_states_and_arcs_nums);
6588 *states_num = curr_counted_states_num;
6589 *arcs_num = curr_counted_arcs_num;
6592 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6593 recognition after checking and simplifying IR of the
6594 description. */
6595 static void
6596 build_automaton (automaton)
6597 automaton_t automaton;
6599 int states_num;
6600 int arcs_num;
6602 ticker_on (&NDFA_time);
6603 if (automaton->corresponding_automaton_decl == NULL)
6604 fprintf (stderr, "Create anonymous automaton (1 star is 100 new states):");
6605 else
6606 fprintf (stderr, "Create automaton `%s' (1 star is 100 new states):",
6607 automaton->corresponding_automaton_decl->name);
6608 make_automaton (automaton);
6609 fprintf (stderr, " done\n");
6610 ticker_off (&NDFA_time);
6611 count_states_and_arcs (automaton, &states_num, &arcs_num);
6612 automaton->NDFA_states_num = states_num;
6613 automaton->NDFA_arcs_num = arcs_num;
6614 ticker_on (&NDFA_to_DFA_time);
6615 if (automaton->corresponding_automaton_decl == NULL)
6616 fprintf (stderr, "Make anonymous DFA (1 star is 100 new states):");
6617 else
6618 fprintf (stderr, "Make DFA `%s' (1 star is 100 new states):",
6619 automaton->corresponding_automaton_decl->name);
6620 NDFA_to_DFA (automaton);
6621 fprintf (stderr, " done\n");
6622 ticker_off (&NDFA_to_DFA_time);
6623 count_states_and_arcs (automaton, &states_num, &arcs_num);
6624 automaton->DFA_states_num = states_num;
6625 automaton->DFA_arcs_num = arcs_num;
6626 if (!no_minimization_flag)
6628 ticker_on (&minimize_time);
6629 if (automaton->corresponding_automaton_decl == NULL)
6630 fprintf (stderr, "Minimize anonymous DFA...");
6631 else
6632 fprintf (stderr, "Minimize DFA `%s'...",
6633 automaton->corresponding_automaton_decl->name);
6634 minimize_DFA (automaton);
6635 fprintf (stderr, "done\n");
6636 ticker_off (&minimize_time);
6637 count_states_and_arcs (automaton, &states_num, &arcs_num);
6638 automaton->minimal_DFA_states_num = states_num;
6639 automaton->minimal_DFA_arcs_num = arcs_num;
6645 /* The page contains code for enumeration of all states of an automaton. */
6647 /* Variable used for enumeration of all states of an automaton. Its
6648 value is current number of automaton states. */
6649 static int curr_state_order_num;
6651 /* The function is called by function `pass_states' for enumerating
6652 states. */
6653 static void
6654 set_order_state_num (state)
6655 state_t state;
6657 state->order_state_num = curr_state_order_num;
6658 curr_state_order_num++;
6661 /* The function enumerates all states of AUTOMATON. */
6662 static void
6663 enumerate_states (automaton)
6664 automaton_t automaton;
6666 curr_state_order_num = 0;
6667 pass_states (automaton, set_order_state_num);
6668 automaton->achieved_states_num = curr_state_order_num;
6673 /* The page contains code for finding equivalent automaton insns
6674 (ainsns). */
6676 /* The function inserts AINSN into cyclic list
6677 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6678 static ainsn_t
6679 insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6680 ainsn_t ainsn;
6681 ainsn_t cyclic_equiv_class_insn_list;
6683 if (cyclic_equiv_class_insn_list == NULL)
6684 ainsn->next_equiv_class_insn = ainsn;
6685 else
6687 ainsn->next_equiv_class_insn
6688 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6689 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6691 return ainsn;
6694 /* The function deletes equiv_class_insn into cyclic list of
6695 equivalent ainsns. */
6696 static void
6697 delete_ainsn_from_equiv_class (equiv_class_insn)
6698 ainsn_t equiv_class_insn;
6700 ainsn_t curr_equiv_class_insn;
6701 ainsn_t prev_equiv_class_insn;
6703 prev_equiv_class_insn = equiv_class_insn;
6704 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6705 curr_equiv_class_insn != equiv_class_insn;
6706 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6707 prev_equiv_class_insn = curr_equiv_class_insn;
6708 if (prev_equiv_class_insn != equiv_class_insn)
6709 prev_equiv_class_insn->next_equiv_class_insn
6710 = equiv_class_insn->next_equiv_class_insn;
6713 /* The function processes AINSN of a state in order to find equivalent
6714 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6715 state. */
6716 static void
6717 process_insn_equiv_class (ainsn, insn_arcs_array)
6718 ainsn_t ainsn;
6719 arc_t *insn_arcs_array;
6721 ainsn_t next_insn;
6722 ainsn_t curr_insn;
6723 ainsn_t cyclic_insn_list;
6724 arc_t arc;
6726 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6727 abort ();
6728 curr_insn = ainsn;
6729 /* New class of ainsns which are not equivalent to given ainsn. */
6730 cyclic_insn_list = NULL;
6733 next_insn = curr_insn->next_equiv_class_insn;
6734 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6735 if (arc == NULL
6736 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6737 != arc->to_state))
6739 delete_ainsn_from_equiv_class (curr_insn);
6740 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6741 cyclic_insn_list);
6743 curr_insn = next_insn;
6745 while (curr_insn != ainsn);
6748 /* The function processes STATE in order to find equivalent ainsns. */
6749 static void
6750 process_state_for_insn_equiv_partition (state)
6751 state_t state;
6753 arc_t arc;
6754 arc_t *insn_arcs_array;
6755 int i;
6756 vla_ptr_t insn_arcs_vect;
6758 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6759 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6760 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6761 /* Process insns of the arcs. */
6762 for (i = 0; i < description->insns_num; i++)
6763 insn_arcs_array [i] = NULL;
6764 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6765 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6766 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6767 process_insn_equiv_class (arc->insn, insn_arcs_array);
6768 VLA_PTR_DELETE (insn_arcs_vect);
6771 /* The function searches for equivalent ainsns of AUTOMATON. */
6772 static void
6773 set_insn_equiv_classes (automaton)
6774 automaton_t automaton;
6776 ainsn_t ainsn;
6777 ainsn_t first_insn;
6778 ainsn_t curr_insn;
6779 ainsn_t cyclic_insn_list;
6780 ainsn_t insn_with_same_reservs;
6781 int equiv_classes_num;
6783 /* All insns are included in one equivalence class. */
6784 cyclic_insn_list = NULL;
6785 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6786 if (ainsn->first_insn_with_same_reservs)
6787 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6788 cyclic_insn_list);
6789 /* Process insns in order to make equivalence partition. */
6790 pass_states (automaton, process_state_for_insn_equiv_partition);
6791 /* Enumerate equiv classes. */
6792 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6793 /* Set undefined value. */
6794 ainsn->insn_equiv_class_num = -1;
6795 equiv_classes_num = 0;
6796 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6797 if (ainsn->insn_equiv_class_num < 0)
6799 first_insn = ainsn;
6800 if (!first_insn->first_insn_with_same_reservs)
6801 abort ();
6802 first_insn->first_ainsn_with_given_equialence_num = 1;
6803 curr_insn = first_insn;
6806 for (insn_with_same_reservs = curr_insn;
6807 insn_with_same_reservs != NULL;
6808 insn_with_same_reservs
6809 = insn_with_same_reservs->next_same_reservs_insn)
6810 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6811 curr_insn = curr_insn->next_equiv_class_insn;
6813 while (curr_insn != first_insn);
6814 equiv_classes_num++;
6816 automaton->insn_equiv_classes_num = equiv_classes_num;
6821 /* This page contains code for creating DFA(s) and calls functions
6822 building them. */
6825 /* The following value is used to prevent floating point overflow for
6826 estimating an automaton bound. The value should be less DBL_MAX on
6827 the host machine. We use here approximate minimum of maximal
6828 double floating point value required by ANSI C standard. It
6829 will work for non ANSI sun compiler too. */
6831 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6833 /* The function estimate size of the single DFA used by PHR (pipeline
6834 hazards recognizer). */
6835 static double
6836 estimate_one_automaton_bound ()
6838 decl_t decl;
6839 double one_automaton_estimation_bound;
6840 double root_value;
6841 int i;
6843 one_automaton_estimation_bound = 1.0;
6844 for (i = 0; i < description->decls_num; i++)
6846 decl = description->decls [i];
6847 if (decl->mode == dm_unit)
6849 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6850 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6851 / automata_num);
6852 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6853 > one_automaton_estimation_bound)
6854 one_automaton_estimation_bound *= root_value;
6857 return one_automaton_estimation_bound;
6860 /* The function compares unit declarations according to their maximal
6861 cycle in reservations. */
6862 static int
6863 compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6864 const void *unit_decl_1;
6865 const void *unit_decl_2;
6867 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6868 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6869 return 1;
6870 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6871 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6872 return 0;
6873 else
6874 return -1;
6877 /* The function makes heuristic assigning automata to units. Actually
6878 efficacy of the algorithm has been checked yet??? */
6879 static void
6880 units_to_automata_heuristic_distr ()
6882 double estimation_bound;
6883 decl_t decl;
6884 decl_t *unit_decl_ptr;
6885 int automaton_num;
6886 int rest_units_num;
6887 double bound_value;
6888 vla_ptr_t unit_decls;
6889 int i;
6891 if (description->units_num == 0)
6892 return;
6893 estimation_bound = estimate_one_automaton_bound ();
6894 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6895 for (i = 0; i < description->decls_num; i++)
6897 decl = description->decls [i];
6898 if (decl->mode == dm_unit)
6899 VLA_PTR_ADD (unit_decls, decl);
6901 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6902 sizeof (decl_t), compare_max_occ_cycle_nums);
6903 automaton_num = 0;
6904 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6905 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6906 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6907 for (unit_decl_ptr++;
6908 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6909 unit_decl_ptr++)
6911 rest_units_num
6912 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6913 if (automata_num - automaton_num - 1 > rest_units_num)
6914 abort ();
6915 if (automaton_num < automata_num - 1
6916 && ((automata_num - automaton_num - 1 == rest_units_num)
6917 || (bound_value
6918 > (estimation_bound
6919 / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6921 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6922 automaton_num++;
6924 else
6925 bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6926 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6928 if (automaton_num != automata_num - 1)
6929 abort ();
6930 VLA_PTR_DELETE (unit_decls);
6933 /* The functions creates automaton insns for each automata. Automaton
6934 insn is simply insn for given automaton which makes reservation
6935 only of units of the automaton. */
6936 static ainsn_t
6937 create_ainsns ()
6939 decl_t decl;
6940 ainsn_t first_ainsn;
6941 ainsn_t curr_ainsn;
6942 ainsn_t prev_ainsn;
6943 int i;
6945 first_ainsn = NULL;
6946 prev_ainsn = NULL;
6947 for (i = 0; i < description->decls_num; i++)
6949 decl = description->decls [i];
6950 if (decl->mode == dm_insn_reserv)
6952 curr_ainsn = create_node (sizeof (struct ainsn));
6953 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6954 curr_ainsn->important_p = FALSE;
6955 curr_ainsn->next_ainsn = NULL;
6956 if (prev_ainsn == NULL)
6957 first_ainsn = curr_ainsn;
6958 else
6959 prev_ainsn->next_ainsn = curr_ainsn;
6960 prev_ainsn = curr_ainsn;
6963 return first_ainsn;
6966 /* The function assigns automata to units according to constructions
6967 `define_automaton' in the description. */
6968 static void
6969 units_to_automata_distr ()
6971 decl_t decl;
6972 int i;
6974 for (i = 0; i < description->decls_num; i++)
6976 decl = description->decls [i];
6977 if (decl->mode == dm_unit)
6979 if (DECL_UNIT (decl)->automaton_decl == NULL
6980 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6981 == NULL))
6982 /* Distribute to the first automaton. */
6983 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6984 else
6985 DECL_UNIT (decl)->corresponding_automaton_num
6986 = (DECL_UNIT (decl)->automaton_decl
6987 ->corresponding_automaton->automaton_order_num);
6992 /* The function creates DFA(s) for fast pipeline hazards recognition
6993 after checking and simplifying IR of the description. */
6994 static void
6995 create_automata ()
6997 automaton_t curr_automaton;
6998 automaton_t prev_automaton;
6999 decl_t decl;
7000 int curr_automaton_num;
7001 int i;
7003 if (automata_num != 0)
7005 units_to_automata_heuristic_distr ();
7006 for (prev_automaton = NULL, curr_automaton_num = 0;
7007 curr_automaton_num < automata_num;
7008 curr_automaton_num++, prev_automaton = curr_automaton)
7010 curr_automaton = create_node (sizeof (struct automaton));
7011 curr_automaton->ainsn_list = create_ainsns ();
7012 curr_automaton->corresponding_automaton_decl = NULL;
7013 curr_automaton->next_automaton = NULL;
7014 curr_automaton->automaton_order_num = curr_automaton_num;
7015 if (prev_automaton == NULL)
7016 description->first_automaton = curr_automaton;
7017 else
7018 prev_automaton->next_automaton = curr_automaton;
7021 else
7023 curr_automaton_num = 0;
7024 prev_automaton = NULL;
7025 for (i = 0; i < description->decls_num; i++)
7027 decl = description->decls [i];
7028 if (decl->mode == dm_automaton
7029 && DECL_AUTOMATON (decl)->automaton_is_used)
7031 curr_automaton = create_node (sizeof (struct automaton));
7032 curr_automaton->ainsn_list = create_ainsns ();
7033 curr_automaton->corresponding_automaton_decl
7034 = DECL_AUTOMATON (decl);
7035 curr_automaton->next_automaton = NULL;
7036 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
7037 curr_automaton->automaton_order_num = curr_automaton_num;
7038 if (prev_automaton == NULL)
7039 description->first_automaton = curr_automaton;
7040 else
7041 prev_automaton->next_automaton = curr_automaton;
7042 curr_automaton_num++;
7043 prev_automaton = curr_automaton;
7046 if (curr_automaton_num == 0)
7048 curr_automaton = create_node (sizeof (struct automaton));
7049 curr_automaton->ainsn_list = create_ainsns ();
7050 curr_automaton->corresponding_automaton_decl = NULL;
7051 curr_automaton->next_automaton = NULL;
7052 description->first_automaton = curr_automaton;
7054 units_to_automata_distr ();
7056 NDFA_time = create_ticker ();
7057 ticker_off (&NDFA_time);
7058 NDFA_to_DFA_time = create_ticker ();
7059 ticker_off (&NDFA_to_DFA_time);
7060 minimize_time = create_ticker ();
7061 ticker_off (&minimize_time);
7062 equiv_time = create_ticker ();
7063 ticker_off (&equiv_time);
7064 for (curr_automaton = description->first_automaton;
7065 curr_automaton != NULL;
7066 curr_automaton = curr_automaton->next_automaton)
7068 if (curr_automaton->corresponding_automaton_decl == NULL)
7069 fprintf (stderr, "Prepare anonymous automaton creation ... ");
7070 else
7071 fprintf (stderr, "Prepare automaton `%s' creation...",
7072 curr_automaton->corresponding_automaton_decl->name);
7073 create_alt_states (curr_automaton);
7074 form_ainsn_with_same_reservs (curr_automaton);
7075 fprintf (stderr, "done\n");
7076 build_automaton (curr_automaton);
7077 enumerate_states (curr_automaton);
7078 ticker_on (&equiv_time);
7079 set_insn_equiv_classes (curr_automaton);
7080 ticker_off (&equiv_time);
7086 /* This page contains code for forming string representation of
7087 regexp. The representation is formed on IR obstack. So you should
7088 not work with IR obstack between regexp_representation and
7089 finish_regexp_representation calls. */
7091 /* This recursive function forms string representation of regexp
7092 (without tailing '\0'). */
7093 static void
7094 form_regexp (regexp)
7095 regexp_t regexp;
7097 int i;
7099 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
7101 const char *name = (regexp->mode == rm_unit
7102 ? REGEXP_UNIT (regexp)->name
7103 : REGEXP_RESERV (regexp)->name);
7105 obstack_grow (&irp, name, strlen (name));
7107 else if (regexp->mode == rm_sequence)
7108 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
7110 if (i != 0)
7111 obstack_1grow (&irp, ',');
7112 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
7114 else if (regexp->mode == rm_allof)
7116 obstack_1grow (&irp, '(');
7117 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
7119 if (i != 0)
7120 obstack_1grow (&irp, '+');
7121 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
7122 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
7123 obstack_1grow (&irp, '(');
7124 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
7125 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
7126 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
7127 obstack_1grow (&irp, ')');
7129 obstack_1grow (&irp, ')');
7131 else if (regexp->mode == rm_oneof)
7132 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
7134 if (i != 0)
7135 obstack_1grow (&irp, '|');
7136 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
7137 obstack_1grow (&irp, '(');
7138 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
7139 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
7140 obstack_1grow (&irp, ')');
7142 else if (regexp->mode == rm_repeat)
7144 char digits [30];
7146 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
7147 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
7148 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
7149 obstack_1grow (&irp, '(');
7150 form_regexp (REGEXP_REPEAT (regexp)->regexp);
7151 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
7152 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
7153 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
7154 obstack_1grow (&irp, ')');
7155 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
7156 obstack_grow (&irp, digits, strlen (digits));
7158 else if (regexp->mode == rm_nothing)
7159 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
7160 else
7161 abort ();
7164 /* The function returns string representation of REGEXP on IR
7165 obstack. */
7166 static const char *
7167 regexp_representation (regexp)
7168 regexp_t regexp;
7170 form_regexp (regexp);
7171 obstack_1grow (&irp, '\0');
7172 return obstack_base (&irp);
7175 /* The function frees memory allocated for last formed string
7176 representation of regexp. */
7177 static void
7178 finish_regexp_representation ()
7180 int length = obstack_object_size (&irp);
7182 obstack_blank_fast (&irp, -length);
7187 /* This page contains code for output PHR (pipeline hazards recognizer). */
7189 /* The function outputs minimal C type which is sufficient for
7190 representation numbers in range min_range_value and
7191 max_range_value. Because host machine and build machine may be
7192 different, we use here minimal values required by ANSI C standard
7193 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
7194 approximation. */
7196 static void
7197 output_range_type (f, min_range_value, max_range_value)
7198 FILE *f;
7199 long int min_range_value;
7200 long int max_range_value;
7202 if (min_range_value >= 0 && max_range_value <= 255)
7203 fprintf (f, "unsigned char");
7204 else if (min_range_value >= -127 && max_range_value <= 127)
7205 fprintf (f, "signed char");
7206 else if (min_range_value >= 0 && max_range_value <= 65535)
7207 fprintf (f, "unsigned short");
7208 else if (min_range_value >= -32767 && max_range_value <= 32767)
7209 fprintf (f, "short");
7210 else
7211 fprintf (f, "int");
7214 /* The following macro value is used as value of member
7215 `longest_path_length' of state when we are processing path and the
7216 state on the path. */
7218 #define ON_THE_PATH -2
7220 /* The following recursive function searches for the length of the
7221 longest path starting from STATE which does not contain cycles and
7222 `cycle advance' arcs. */
7224 static int
7225 longest_path_length (state)
7226 state_t state;
7228 arc_t arc;
7229 int length, result;
7231 if (state->longest_path_length == ON_THE_PATH)
7232 /* We don't expect the path cycle here. Our graph may contain
7233 only cycles with one state on the path not containing `cycle
7234 advance' arcs -- see comment below. */
7235 abort ();
7236 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
7237 /* We already visited the state. */
7238 return state->longest_path_length;
7240 result = 0;
7241 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7242 /* Ignore cycles containing one state and `cycle advance' arcs. */
7243 if (arc->to_state != state
7244 && (arc->insn->insn_reserv_decl
7245 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
7247 length = longest_path_length (arc->to_state);
7248 if (length > result)
7249 result = length;
7251 state->longest_path_length = result + 1;
7252 return result;
7255 /* The following variable value is value of the corresponding global
7256 variable in the automaton based pipeline interface. */
7258 static int max_dfa_issue_rate;
7260 /* The following function processes the longest path length staring
7261 from STATE to find MAX_DFA_ISSUE_RATE. */
7263 static void
7264 process_state_longest_path_length (state)
7265 state_t state;
7267 int value;
7269 value = longest_path_length (state);
7270 if (value > max_dfa_issue_rate)
7271 max_dfa_issue_rate = value;
7274 /* The following macro value is name of the corresponding global
7275 variable in the automaton based pipeline interface. */
7277 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
7279 /* The following function calculates value of the corresponding
7280 global variable and outputs its declaration. */
7282 static void
7283 output_dfa_max_issue_rate ()
7285 automaton_t automaton;
7287 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
7288 abort ();
7289 max_dfa_issue_rate = 0;
7290 for (automaton = description->first_automaton;
7291 automaton != NULL;
7292 automaton = automaton->next_automaton)
7293 pass_states (automaton, process_state_longest_path_length);
7294 fprintf (output_file, "\nint %s = %d;\n",
7295 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
7298 /* The function outputs all initialization values of VECT with length
7299 vect_length. */
7300 static void
7301 output_vect (vect, vect_length)
7302 vect_el_t *vect;
7303 int vect_length;
7305 int els_on_line;
7307 els_on_line = 1;
7308 if (vect_length == 0)
7309 fprintf (output_file,
7310 "0 /* This is dummy el because the vect is empty */");
7311 else
7315 fprintf (output_file, "%5ld", (long) *vect);
7316 vect_length--;
7317 if (els_on_line == 10)
7319 els_on_line = 0;
7320 fprintf (output_file, ",\n");
7322 else if (vect_length != 0)
7323 fprintf (output_file, ", ");
7324 els_on_line++;
7325 vect++;
7327 while (vect_length != 0);
7331 /* The following is name of the structure which represents DFA(s) for
7332 PHR. */
7333 #define CHIP_NAME "DFA_chip"
7335 /* The following is name of member which represents state of a DFA for
7336 PHR. */
7337 static void
7338 output_chip_member_name (f, automaton)
7339 FILE *f;
7340 automaton_t automaton;
7342 if (automaton->corresponding_automaton_decl == NULL)
7343 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
7344 else
7345 fprintf (f, "%s_automaton_state",
7346 automaton->corresponding_automaton_decl->name);
7349 /* The following is name of temporary variable which stores state of a
7350 DFA for PHR. */
7351 static void
7352 output_temp_chip_member_name (f, automaton)
7353 FILE *f;
7354 automaton_t automaton;
7356 fprintf (f, "_");
7357 output_chip_member_name (f, automaton);
7360 /* This is name of macro value which is code of pseudo_insn
7361 representing advancing cpu cycle. Its value is used as internal
7362 code unknown insn. */
7363 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7365 /* Output name of translate vector for given automaton. */
7366 static void
7367 output_translate_vect_name (f, automaton)
7368 FILE *f;
7369 automaton_t automaton;
7371 if (automaton->corresponding_automaton_decl == NULL)
7372 fprintf (f, "translate_%d", automaton->automaton_order_num);
7373 else
7374 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
7377 /* Output name for simple transition table representation. */
7378 static void
7379 output_trans_full_vect_name (f, automaton)
7380 FILE *f;
7381 automaton_t automaton;
7383 if (automaton->corresponding_automaton_decl == NULL)
7384 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7385 else
7386 fprintf (f, "%s_transitions",
7387 automaton->corresponding_automaton_decl->name);
7390 /* Output name of comb vector of the transition table for given
7391 automaton. */
7392 static void
7393 output_trans_comb_vect_name (f, automaton)
7394 FILE *f;
7395 automaton_t automaton;
7397 if (automaton->corresponding_automaton_decl == NULL)
7398 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7399 else
7400 fprintf (f, "%s_transitions",
7401 automaton->corresponding_automaton_decl->name);
7404 /* Output name of check vector of the transition table for given
7405 automaton. */
7406 static void
7407 output_trans_check_vect_name (f, automaton)
7408 FILE *f;
7409 automaton_t automaton;
7411 if (automaton->corresponding_automaton_decl == NULL)
7412 fprintf (f, "check_%d", automaton->automaton_order_num);
7413 else
7414 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7417 /* Output name of base vector of the transition table for given
7418 automaton. */
7419 static void
7420 output_trans_base_vect_name (f, automaton)
7421 FILE *f;
7422 automaton_t automaton;
7424 if (automaton->corresponding_automaton_decl == NULL)
7425 fprintf (f, "base_%d", automaton->automaton_order_num);
7426 else
7427 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7430 /* Output name for simple alternatives number representation. */
7431 static void
7432 output_state_alts_full_vect_name (f, automaton)
7433 FILE *f;
7434 automaton_t automaton;
7436 if (automaton->corresponding_automaton_decl == NULL)
7437 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7438 else
7439 fprintf (f, "%s_state_alts",
7440 automaton->corresponding_automaton_decl->name);
7443 /* Output name of comb vector of the alternatives number table for given
7444 automaton. */
7445 static void
7446 output_state_alts_comb_vect_name (f, automaton)
7447 FILE *f;
7448 automaton_t automaton;
7450 if (automaton->corresponding_automaton_decl == NULL)
7451 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7452 else
7453 fprintf (f, "%s_state_alts",
7454 automaton->corresponding_automaton_decl->name);
7457 /* Output name of check vector of the alternatives number table for given
7458 automaton. */
7459 static void
7460 output_state_alts_check_vect_name (f, automaton)
7461 FILE *f;
7462 automaton_t automaton;
7464 if (automaton->corresponding_automaton_decl == NULL)
7465 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7466 else
7467 fprintf (f, "%s_check_state_alts",
7468 automaton->corresponding_automaton_decl->name);
7471 /* Output name of base vector of the alternatives number table for given
7472 automaton. */
7473 static void
7474 output_state_alts_base_vect_name (f, automaton)
7475 FILE *f;
7476 automaton_t automaton;
7478 if (automaton->corresponding_automaton_decl == NULL)
7479 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7480 else
7481 fprintf (f, "%s_base_state_alts",
7482 automaton->corresponding_automaton_decl->name);
7485 /* Output name of simple min issue delay table representation. */
7486 static void
7487 output_min_issue_delay_vect_name (f, automaton)
7488 FILE *f;
7489 automaton_t automaton;
7491 if (automaton->corresponding_automaton_decl == NULL)
7492 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7493 else
7494 fprintf (f, "%s_min_issue_delay",
7495 automaton->corresponding_automaton_decl->name);
7498 /* Output name of deadlock vector for given automaton. */
7499 static void
7500 output_dead_lock_vect_name (f, automaton)
7501 FILE *f;
7502 automaton_t automaton;
7504 if (automaton->corresponding_automaton_decl == NULL)
7505 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7506 else
7507 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7510 /* Output name of reserved units table for AUTOMATON into file F. */
7511 static void
7512 output_reserved_units_table_name (f, automaton)
7513 FILE *f;
7514 automaton_t automaton;
7516 if (automaton->corresponding_automaton_decl == NULL)
7517 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7518 else
7519 fprintf (f, "%s_reserved_units",
7520 automaton->corresponding_automaton_decl->name);
7523 /* Name of the PHR interface macro. */
7524 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7526 /* Name of the PHR interface macro. */
7527 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7529 /* Names of an internal functions: */
7530 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7532 /* This is external type of DFA(s) state. */
7533 #define STATE_TYPE_NAME "state_t"
7535 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7537 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7539 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7541 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7543 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7545 /* Name of cache of insn dfa codes. */
7546 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7548 /* Name of length of cache of insn dfa codes. */
7549 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7551 /* Names of the PHR interface functions: */
7552 #define SIZE_FUNC_NAME "state_size"
7554 #define TRANSITION_FUNC_NAME "state_transition"
7556 #define STATE_ALTS_FUNC_NAME "state_alts"
7558 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7560 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7562 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7564 #define RESET_FUNC_NAME "state_reset"
7566 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7568 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7570 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7572 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7574 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7576 #define DFA_START_FUNC_NAME "dfa_start"
7578 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7580 /* Names of parameters of the PHR interface functions. */
7581 #define STATE_NAME "state"
7583 #define INSN_PARAMETER_NAME "insn"
7585 #define INSN2_PARAMETER_NAME "insn2"
7587 #define CHIP_PARAMETER_NAME "chip"
7589 #define FILE_PARAMETER_NAME "f"
7591 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7593 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7595 /* Names of the variables whose values are internal insn code of rtx
7596 insn. */
7597 #define INTERNAL_INSN_CODE_NAME "insn_code"
7599 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7601 /* Names of temporary variables in some functions. */
7602 #define TEMPORARY_VARIABLE_NAME "temp"
7604 #define I_VARIABLE_NAME "i"
7606 /* Name of result variable in some functions. */
7607 #define RESULT_VARIABLE_NAME "res"
7609 /* Name of function (attribute) to translate insn into internal insn
7610 code. */
7611 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7613 /* Name of function (attribute) to translate insn into internal insn
7614 code with caching. */
7615 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7617 /* Name of function (attribute) to translate insn into internal insn
7618 code. */
7619 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7621 /* Name of function (attribute) to translate insn into internal insn
7622 code. */
7623 #define BYPASS_P_FUNC_NAME "bypass_p"
7625 /* Output C type which is used for representation of codes of states
7626 of AUTOMATON. */
7627 static void
7628 output_state_member_type (f, automaton)
7629 FILE *f;
7630 automaton_t automaton;
7632 output_range_type (f, 0, automaton->achieved_states_num);
7635 /* Output definition of the structure representing current DFA(s)
7636 state(s). */
7637 static void
7638 output_chip_definitions ()
7640 automaton_t automaton;
7642 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7643 for (automaton = description->first_automaton;
7644 automaton != NULL;
7645 automaton = automaton->next_automaton)
7647 fprintf (output_file, " ");
7648 output_state_member_type (output_file, automaton);
7649 fprintf (output_file, " ");
7650 output_chip_member_name (output_file, automaton);
7651 fprintf (output_file, ";\n");
7653 fprintf (output_file, "};\n\n");
7654 #if 0
7655 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7656 #endif
7660 /* The function outputs translate vector of internal insn code into
7661 insn equivalence class number. The equivalence class number is
7662 used to access to table and vectors representing DFA(s). */
7663 static void
7664 output_translate_vect (automaton)
7665 automaton_t automaton;
7667 ainsn_t ainsn;
7668 int insn_value;
7669 vla_hwint_t translate_vect;
7671 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7672 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7673 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7674 /* Undefined value */
7675 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7676 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7677 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7678 = ainsn->insn_equiv_class_num;
7679 fprintf (output_file,
7680 "/* Vector translating external insn codes to internal ones.*/\n");
7681 fprintf (output_file, "static const ");
7682 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7683 fprintf (output_file, " ");
7684 output_translate_vect_name (output_file, automaton);
7685 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7686 output_vect (VLA_HWINT_BEGIN (translate_vect),
7687 VLA_HWINT_LENGTH (translate_vect));
7688 fprintf (output_file, "};\n\n");
7689 VLA_HWINT_DELETE (translate_vect);
7692 /* The value in a table state x ainsn -> something which represents
7693 undefined value. */
7694 static int undefined_vect_el_value;
7696 /* The following function returns nonzero value if the best
7697 representation of the table is comb vector. */
7698 static int
7699 comb_vect_p (tab)
7700 state_ainsn_table_t tab;
7702 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7703 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7706 /* The following function creates new table for AUTOMATON. */
7707 static state_ainsn_table_t
7708 create_state_ainsn_table (automaton)
7709 automaton_t automaton;
7711 state_ainsn_table_t tab;
7712 int full_vect_length;
7713 int i;
7715 tab = create_node (sizeof (struct state_ainsn_table));
7716 tab->automaton = automaton;
7717 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7718 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7719 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7720 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7721 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7722 full_vect_length = (automaton->insn_equiv_classes_num
7723 * automaton->achieved_states_num);
7724 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7725 for (i = 0; i < full_vect_length; i++)
7726 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7727 tab->min_base_vect_el_value = 0;
7728 tab->max_base_vect_el_value = 0;
7729 tab->min_comb_vect_el_value = 0;
7730 tab->max_comb_vect_el_value = 0;
7731 return tab;
7734 /* The following function outputs the best C representation of the
7735 table TAB of given TABLE_NAME. */
7736 static void
7737 output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7738 output_comb_vect_name_func,
7739 output_check_vect_name_func,
7740 output_base_vect_name_func)
7741 state_ainsn_table_t tab;
7742 char *table_name;
7743 void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7744 void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7745 void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7746 void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7748 if (!comb_vect_p (tab))
7750 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7751 fprintf (output_file, "static const ");
7752 output_range_type (output_file, tab->min_comb_vect_el_value,
7753 tab->max_comb_vect_el_value);
7754 fprintf (output_file, " ");
7755 (*output_full_vect_name_func) (output_file, tab->automaton);
7756 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7757 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7758 VLA_HWINT_LENGTH (tab->full_vect));
7759 fprintf (output_file, "};\n\n");
7761 else
7763 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7764 fprintf (output_file, "static const ");
7765 output_range_type (output_file, tab->min_comb_vect_el_value,
7766 tab->max_comb_vect_el_value);
7767 fprintf (output_file, " ");
7768 (*output_comb_vect_name_func) (output_file, tab->automaton);
7769 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7770 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7771 VLA_HWINT_LENGTH (tab->comb_vect));
7772 fprintf (output_file, "};\n\n");
7773 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7774 fprintf (output_file, "static const ");
7775 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7776 fprintf (output_file, " ");
7777 (*output_check_vect_name_func) (output_file, tab->automaton);
7778 fprintf (output_file, "[] = {\n");
7779 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7780 VLA_HWINT_LENGTH (tab->check_vect));
7781 fprintf (output_file, "};\n\n");
7782 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7783 fprintf (output_file, "static const ");
7784 output_range_type (output_file, tab->min_base_vect_el_value,
7785 tab->max_base_vect_el_value);
7786 fprintf (output_file, " ");
7787 (*output_base_vect_name_func) (output_file, tab->automaton);
7788 fprintf (output_file, "[] = {\n");
7789 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7790 VLA_HWINT_LENGTH (tab->base_vect));
7791 fprintf (output_file, "};\n\n");
7795 /* The following function adds vector with length VECT_LENGTH and
7796 elements pointed by VECT to table TAB as its line with number
7797 VECT_NUM. */
7798 static void
7799 add_vect (tab, vect_num, vect, vect_length)
7800 state_ainsn_table_t tab;
7801 int vect_num;
7802 vect_el_t *vect;
7803 int vect_length;
7805 int real_vect_length;
7806 vect_el_t *comb_vect_start;
7807 vect_el_t *check_vect_start;
7808 int comb_vect_index;
7809 int comb_vect_els_num;
7810 int vect_index;
7811 int first_unempty_vect_index;
7812 int additional_els_num;
7813 int no_state_value;
7814 vect_el_t vect_el;
7815 int i;
7817 if (vect_length == 0)
7818 abort ();
7819 real_vect_length = tab->automaton->insn_equiv_classes_num;
7820 if (vect [vect_length - 1] == undefined_vect_el_value)
7821 abort ();
7822 /* Form full vector in the table: */
7823 for (i = 0; i < vect_length; i++)
7824 VLA_HWINT (tab->full_vect,
7825 i + tab->automaton->insn_equiv_classes_num * vect_num)
7826 = vect [i];
7827 /* Form comb vector in the table: */
7828 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7829 abort ();
7830 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7831 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7832 for (first_unempty_vect_index = 0;
7833 first_unempty_vect_index < vect_length;
7834 first_unempty_vect_index++)
7835 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7836 break;
7837 /* Search for the place in comb vect for the inserted vect. */
7838 for (comb_vect_index = 0;
7839 comb_vect_index < comb_vect_els_num;
7840 comb_vect_index++)
7842 for (vect_index = first_unempty_vect_index;
7843 vect_index < vect_length
7844 && vect_index + comb_vect_index < comb_vect_els_num;
7845 vect_index++)
7846 if (vect [vect_index] != undefined_vect_el_value
7847 && (comb_vect_start [vect_index + comb_vect_index]
7848 != undefined_vect_el_value))
7849 break;
7850 if (vect_index >= vect_length
7851 || vect_index + comb_vect_index >= comb_vect_els_num)
7852 break;
7854 /* Slot was found. */
7855 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7856 if (additional_els_num < 0)
7857 additional_els_num = 0;
7858 /* Expand comb and check vectors. */
7859 vect_el = undefined_vect_el_value;
7860 no_state_value = tab->automaton->achieved_states_num;
7861 while (additional_els_num > 0)
7863 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7864 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7865 additional_els_num--;
7867 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7868 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7869 if (VLA_HWINT_LENGTH (tab->comb_vect)
7870 < (size_t) (comb_vect_index + real_vect_length))
7871 abort ();
7872 /* Fill comb and check vectors. */
7873 for (vect_index = 0; vect_index < vect_length; vect_index++)
7874 if (vect [vect_index] != undefined_vect_el_value)
7876 if (comb_vect_start [comb_vect_index + vect_index]
7877 != undefined_vect_el_value)
7878 abort ();
7879 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7880 if (vect [vect_index] < 0)
7881 abort ();
7882 if (tab->max_comb_vect_el_value < vect [vect_index])
7883 tab->max_comb_vect_el_value = vect [vect_index];
7884 if (tab->min_comb_vect_el_value > vect [vect_index])
7885 tab->min_comb_vect_el_value = vect [vect_index];
7886 check_vect_start [comb_vect_index + vect_index] = vect_num;
7888 if (tab->max_base_vect_el_value < comb_vect_index)
7889 tab->max_base_vect_el_value = comb_vect_index;
7890 if (tab->min_base_vect_el_value > comb_vect_index)
7891 tab->min_base_vect_el_value = comb_vect_index;
7892 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7895 /* Return number of out arcs of STATE. */
7896 static int
7897 out_state_arcs_num (state)
7898 state_t state;
7900 int result;
7901 arc_t arc;
7903 result = 0;
7904 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7906 if (arc->insn == NULL)
7907 abort ();
7908 if (arc->insn->first_ainsn_with_given_equialence_num)
7909 result++;
7911 return result;
7914 /* Compare number of possible transitions from the states. */
7915 static int
7916 compare_transition_els_num (state_ptr_1, state_ptr_2)
7917 const void *state_ptr_1;
7918 const void *state_ptr_2;
7920 int transition_els_num_1;
7921 int transition_els_num_2;
7923 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7924 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7925 if (transition_els_num_1 < transition_els_num_2)
7926 return 1;
7927 else if (transition_els_num_1 == transition_els_num_2)
7928 return 0;
7929 else
7930 return -1;
7933 /* The function adds element EL_VALUE to vector VECT for a table state
7934 x AINSN. */
7935 static void
7936 add_vect_el (vect, ainsn, el_value)
7937 vla_hwint_t *vect;
7938 ainsn_t ainsn;
7939 int el_value;
7941 int equiv_class_num;
7942 int vect_index;
7944 if (ainsn == NULL)
7945 abort ();
7946 equiv_class_num = ainsn->insn_equiv_class_num;
7947 for (vect_index = VLA_HWINT_LENGTH (*vect);
7948 vect_index <= equiv_class_num;
7949 vect_index++)
7950 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7951 VLA_HWINT (*vect, equiv_class_num) = el_value;
7954 /* This is for forming vector of states of an automaton. */
7955 static vla_ptr_t output_states_vect;
7957 /* The function is called by function pass_states. The function adds
7958 STATE to `output_states_vect'. */
7959 static void
7960 add_states_vect_el (state)
7961 state_t state;
7963 VLA_PTR_ADD (output_states_vect, state);
7966 /* Form and output vectors (comb, check, base or full vector)
7967 representing transition table of AUTOMATON. */
7968 static void
7969 output_trans_table (automaton)
7970 automaton_t automaton;
7972 state_t *state_ptr;
7973 arc_t arc;
7974 vla_hwint_t transition_vect;
7976 undefined_vect_el_value = automaton->achieved_states_num;
7977 automaton->trans_table = create_state_ainsn_table (automaton);
7978 /* Create vect of pointers to states ordered by num of transitions
7979 from the state (state with the maximum num is the first). */
7980 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7981 pass_states (automaton, add_states_vect_el);
7982 qsort (VLA_PTR_BEGIN (output_states_vect),
7983 VLA_PTR_LENGTH (output_states_vect),
7984 sizeof (state_t), compare_transition_els_num);
7985 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7986 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7987 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7988 state_ptr++)
7990 VLA_HWINT_NULLIFY (transition_vect);
7991 for (arc = first_out_arc (*state_ptr);
7992 arc != NULL;
7993 arc = next_out_arc (arc))
7995 if (arc->insn == NULL)
7996 abort ();
7997 if (arc->insn->first_ainsn_with_given_equialence_num)
7998 add_vect_el (&transition_vect, arc->insn,
7999 arc->to_state->order_state_num);
8001 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
8002 VLA_HWINT_BEGIN (transition_vect),
8003 VLA_HWINT_LENGTH (transition_vect));
8005 output_state_ainsn_table
8006 (automaton->trans_table, (char *) "state transitions",
8007 output_trans_full_vect_name, output_trans_comb_vect_name,
8008 output_trans_check_vect_name, output_trans_base_vect_name);
8009 VLA_PTR_DELETE (output_states_vect);
8010 VLA_HWINT_DELETE (transition_vect);
8013 /* Form and output vectors (comb, check, base or simple vect)
8014 representing alts number table of AUTOMATON. The table is state x
8015 ainsn -> number of possible alternative reservations by the
8016 ainsn. */
8017 static void
8018 output_state_alts_table (automaton)
8019 automaton_t automaton;
8021 state_t *state_ptr;
8022 arc_t arc;
8023 vla_hwint_t state_alts_vect;
8025 undefined_vect_el_value = 0; /* no alts when transition is not possible */
8026 automaton->state_alts_table = create_state_ainsn_table (automaton);
8027 /* Create vect of pointers to states ordered by num of transitions
8028 from the state (state with the maximum num is the first). */
8029 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8030 pass_states (automaton, add_states_vect_el);
8031 qsort (VLA_PTR_BEGIN (output_states_vect),
8032 VLA_PTR_LENGTH (output_states_vect),
8033 sizeof (state_t), compare_transition_els_num);
8034 /* Create base, comb, and check vectors. */
8035 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
8036 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8037 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8038 state_ptr++)
8040 VLA_HWINT_NULLIFY (state_alts_vect);
8041 for (arc = first_out_arc (*state_ptr);
8042 arc != NULL;
8043 arc = next_out_arc (arc))
8045 if (arc->insn == NULL)
8046 abort ();
8047 if (arc->insn->first_ainsn_with_given_equialence_num)
8048 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
8050 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
8051 VLA_HWINT_BEGIN (state_alts_vect),
8052 VLA_HWINT_LENGTH (state_alts_vect));
8054 output_state_ainsn_table
8055 (automaton->state_alts_table, (char *) "state insn alternatives",
8056 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
8057 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
8058 VLA_PTR_DELETE (output_states_vect);
8059 VLA_HWINT_DELETE (state_alts_vect);
8062 /* The current number of passing states to find minimal issue delay
8063 value for an ainsn and state. */
8064 static int curr_state_pass_num;
8066 /* This recursive function passes states to find minimal issue delay
8067 value for AINSN. The state being visited is STATE. The function
8068 returns minimal issue delay value for AINSN in STATE or -1 if we
8069 enter into a loop. */
8070 static int
8071 min_issue_delay_pass_states (state, ainsn)
8072 state_t state;
8073 ainsn_t ainsn;
8075 arc_t arc;
8076 int min_insn_issue_delay, insn_issue_delay;
8078 if (state->state_pass_num == curr_state_pass_num
8079 || state->min_insn_issue_delay != -1)
8080 /* We've entered into a loop or already have the correct value for
8081 given state and ainsn. */
8082 return state->min_insn_issue_delay;
8083 state->state_pass_num = curr_state_pass_num;
8084 min_insn_issue_delay = -1;
8085 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8086 if (arc->insn == ainsn)
8088 min_insn_issue_delay = 0;
8089 break;
8091 else
8093 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
8094 if (insn_issue_delay != -1)
8096 if (arc->insn->insn_reserv_decl
8097 == DECL_INSN_RESERV (advance_cycle_insn_decl))
8098 insn_issue_delay++;
8099 if (min_insn_issue_delay == -1
8100 || min_insn_issue_delay > insn_issue_delay)
8102 min_insn_issue_delay = insn_issue_delay;
8103 if (insn_issue_delay == 0)
8104 break;
8108 return min_insn_issue_delay;
8111 /* The function searches minimal issue delay value for AINSN in STATE.
8112 The function can return negative value if we can not issue AINSN. We
8113 will report about it later. */
8114 static int
8115 min_issue_delay (state, ainsn)
8116 state_t state;
8117 ainsn_t ainsn;
8119 curr_state_pass_num++;
8120 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
8121 return state->min_insn_issue_delay;
8124 /* The function initiates code for finding minimal issue delay values.
8125 It should be called only once. */
8126 static void
8127 initiate_min_issue_delay_pass_states ()
8129 curr_state_pass_num = 0;
8132 /* Form and output vectors representing minimal issue delay table of
8133 AUTOMATON. The table is state x ainsn -> minimal issue delay of
8134 the ainsn. */
8135 static void
8136 output_min_issue_delay_table (automaton)
8137 automaton_t automaton;
8139 vla_hwint_t min_issue_delay_vect;
8140 vla_hwint_t compressed_min_issue_delay_vect;
8141 vect_el_t min_delay;
8142 ainsn_t ainsn;
8143 state_t *state_ptr;
8144 int i;
8146 /* Create vect of pointers to states ordered by num of transitions
8147 from the state (state with the maximum num is the first). */
8148 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8149 pass_states (automaton, add_states_vect_el);
8150 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
8151 VLA_HWINT_EXPAND (min_issue_delay_vect,
8152 VLA_HWINT_LENGTH (output_states_vect)
8153 * automaton->insn_equiv_classes_num);
8154 for (i = 0;
8155 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
8156 * automaton->insn_equiv_classes_num);
8157 i++)
8158 VLA_HWINT (min_issue_delay_vect, i) = 0;
8159 automaton->max_min_delay = 0;
8160 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
8161 if (ainsn->first_ainsn_with_given_equialence_num)
8163 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8164 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8165 state_ptr++)
8166 (*state_ptr)->min_insn_issue_delay = -1;
8167 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8168 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8169 state_ptr++)
8171 min_delay = min_issue_delay (*state_ptr, ainsn);
8172 if (automaton->max_min_delay < min_delay)
8173 automaton->max_min_delay = min_delay;
8174 VLA_HWINT (min_issue_delay_vect,
8175 (*state_ptr)->order_state_num
8176 * automaton->insn_equiv_classes_num
8177 + ainsn->insn_equiv_class_num) = min_delay;
8180 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
8181 fprintf (output_file, "static const ");
8182 output_range_type (output_file, 0, automaton->max_min_delay);
8183 fprintf (output_file, " ");
8184 output_min_issue_delay_vect_name (output_file, automaton);
8185 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
8186 /* Compress the vector */
8187 if (automaton->max_min_delay < 2)
8188 automaton->min_issue_delay_table_compression_factor = 8;
8189 else if (automaton->max_min_delay < 4)
8190 automaton->min_issue_delay_table_compression_factor = 4;
8191 else if (automaton->max_min_delay < 16)
8192 automaton->min_issue_delay_table_compression_factor = 2;
8193 else
8194 automaton->min_issue_delay_table_compression_factor = 1;
8195 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
8196 "compressed min issue delay vector");
8197 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
8198 (VLA_HWINT_LENGTH (min_issue_delay_vect)
8199 + automaton->min_issue_delay_table_compression_factor
8200 - 1)
8201 / automaton->min_issue_delay_table_compression_factor);
8202 for (i = 0;
8203 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
8204 i++)
8205 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
8206 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
8207 VLA_HWINT (compressed_min_issue_delay_vect,
8208 i / automaton->min_issue_delay_table_compression_factor)
8209 |= (VLA_HWINT (min_issue_delay_vect, i)
8210 << (8 - (i % automaton->min_issue_delay_table_compression_factor
8211 + 1)
8212 * (8 / automaton->min_issue_delay_table_compression_factor)));
8213 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
8214 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
8215 fprintf (output_file, "};\n\n");
8216 VLA_PTR_DELETE (output_states_vect);
8217 VLA_HWINT_DELETE (min_issue_delay_vect);
8218 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
8221 #ifndef NDEBUG
8222 /* Number of states which contains transition only by advancing cpu
8223 cycle. */
8224 static int locked_states_num;
8225 #endif
8227 /* Form and output vector representing the locked states of
8228 AUTOMATON. */
8229 static void
8230 output_dead_lock_vect (automaton)
8231 automaton_t automaton;
8233 state_t *state_ptr;
8234 arc_t arc;
8235 vla_hwint_t dead_lock_vect;
8237 /* Create vect of pointers to states ordered by num of
8238 transitions from the state (state with the maximum num is the
8239 first). */
8240 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8241 pass_states (automaton, add_states_vect_el);
8242 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
8243 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
8244 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8245 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8246 state_ptr++)
8248 arc = first_out_arc (*state_ptr);
8249 if (arc == NULL)
8250 abort ();
8251 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
8252 = (next_out_arc (arc) == NULL
8253 && (arc->insn->insn_reserv_decl
8254 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
8255 #ifndef NDEBUG
8256 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
8257 locked_states_num++;
8258 #endif
8260 fprintf (output_file, "/* Vector for locked state flags. */\n");
8261 fprintf (output_file, "static const ");
8262 output_range_type (output_file, 0, 1);
8263 fprintf (output_file, " ");
8264 output_dead_lock_vect_name (output_file, automaton);
8265 fprintf (output_file, "[] = {\n");
8266 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
8267 VLA_HWINT_LENGTH (dead_lock_vect));
8268 fprintf (output_file, "};\n\n");
8269 VLA_HWINT_DELETE (dead_lock_vect);
8270 VLA_PTR_DELETE (output_states_vect);
8273 /* Form and output vector representing reserved units of the states of
8274 AUTOMATON. */
8275 static void
8276 output_reserved_units_table (automaton)
8277 automaton_t automaton;
8279 state_t *curr_state_ptr;
8280 vla_hwint_t reserved_units_table;
8281 size_t state_byte_size;
8282 int i;
8284 /* Create vect of pointers to states. */
8285 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8286 pass_states (automaton, add_states_vect_el);
8287 /* Create vector. */
8288 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
8289 state_byte_size = (description->query_units_num + 7) / 8;
8290 VLA_HWINT_EXPAND (reserved_units_table,
8291 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8292 for (i = 0;
8293 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8294 i++)
8295 VLA_HWINT (reserved_units_table, i) = 0;
8296 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
8297 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8298 curr_state_ptr++)
8300 for (i = 0; i < description->units_num; i++)
8301 if (units_array [i]->query_p
8302 && first_cycle_unit_presence (*curr_state_ptr, i))
8303 VLA_HWINT (reserved_units_table,
8304 (*curr_state_ptr)->order_state_num * state_byte_size
8305 + units_array [i]->query_num / 8)
8306 += (1 << (units_array [i]->query_num % 8));
8308 fprintf (output_file, "/* Vector for reserved units of states. */\n");
8309 fprintf (output_file, "static const ");
8310 output_range_type (output_file, 0, 255);
8311 fprintf (output_file, " ");
8312 output_reserved_units_table_name (output_file, automaton);
8313 fprintf (output_file, "[] = {\n");
8314 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
8315 VLA_HWINT_LENGTH (reserved_units_table));
8316 fprintf (output_file, "};\n\n");
8317 VLA_HWINT_DELETE (reserved_units_table);
8318 VLA_PTR_DELETE (output_states_vect);
8321 /* The function outputs all tables representing DFA(s) used for fast
8322 pipeline hazards recognition. */
8323 static void
8324 output_tables ()
8326 automaton_t automaton;
8328 #ifndef NDEBUG
8329 locked_states_num = 0;
8330 #endif
8331 initiate_min_issue_delay_pass_states ();
8332 for (automaton = description->first_automaton;
8333 automaton != NULL;
8334 automaton = automaton->next_automaton)
8336 output_translate_vect (automaton);
8337 output_trans_table (automaton);
8338 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
8339 output_state_alts_table (automaton);
8340 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8341 AUTOMATON_STATE_ALTS_MACRO_NAME);
8342 output_min_issue_delay_table (automaton);
8343 output_dead_lock_vect (automaton);
8344 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
8345 output_reserved_units_table (automaton);
8346 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8347 CPU_UNITS_QUERY_MACRO_NAME);
8349 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
8350 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8353 /* The function outputs definition and value of PHR interface variable
8354 `max_insn_queue_index'. Its value is not less than maximal queue
8355 length needed for the insn scheduler. */
8356 static void
8357 output_max_insn_queue_index_def ()
8359 int i, max, latency;
8360 decl_t decl;
8362 max = description->max_insn_reserv_cycles;
8363 for (i = 0; i < description->decls_num; i++)
8365 decl = description->decls [i];
8366 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8368 latency = DECL_INSN_RESERV (decl)->default_latency;
8369 if (latency > max)
8370 max = latency;
8372 else if (decl->mode == dm_bypass)
8374 latency = DECL_BYPASS (decl)->latency;
8375 if (latency > max)
8376 max = latency;
8379 for (i = 0; (1 << i) <= max; i++)
8381 if (i < 0)
8382 abort ();
8383 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
8387 /* The function outputs switch cases for insn reservations using
8388 function *output_automata_list_code. */
8389 static void
8390 output_insn_code_cases (output_automata_list_code)
8391 void (*output_automata_list_code) PARAMS ((automata_list_el_t));
8393 decl_t decl, decl2;
8394 int i, j;
8396 for (i = 0; i < description->decls_num; i++)
8398 decl = description->decls [i];
8399 if (decl->mode == dm_insn_reserv)
8400 DECL_INSN_RESERV (decl)->processed_p = FALSE;
8402 for (i = 0; i < description->decls_num; i++)
8404 decl = description->decls [i];
8405 if (decl->mode == dm_insn_reserv
8406 && !DECL_INSN_RESERV (decl)->processed_p)
8408 for (j = i; j < description->decls_num; j++)
8410 decl2 = description->decls [j];
8411 if (decl2->mode == dm_insn_reserv
8412 && (DECL_INSN_RESERV (decl2)->important_automata_list
8413 == DECL_INSN_RESERV (decl)->important_automata_list))
8415 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8416 fprintf (output_file, " case %d: /* %s */\n",
8417 DECL_INSN_RESERV (decl2)->insn_num,
8418 DECL_INSN_RESERV (decl2)->name);
8421 (*output_automata_list_code)
8422 (DECL_INSN_RESERV (decl)->important_automata_list);
8428 /* The function outputs a code for evaluation of a minimal delay of
8429 issue of insns which have reservations in given AUTOMATA_LIST. */
8430 static void
8431 output_automata_list_min_issue_delay_code (automata_list)
8432 automata_list_el_t automata_list;
8434 automata_list_el_t el;
8435 automaton_t automaton;
8437 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8439 automaton = el->automaton;
8440 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8441 output_min_issue_delay_vect_name (output_file, automaton);
8442 fprintf (output_file,
8443 (automaton->min_issue_delay_table_compression_factor != 1
8444 ? " [(" : " ["));
8445 output_translate_vect_name (output_file, automaton);
8446 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8447 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8448 output_chip_member_name (output_file, automaton);
8449 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8450 if (automaton->min_issue_delay_table_compression_factor == 1)
8451 fprintf (output_file, "];\n");
8452 else
8454 fprintf (output_file, ") / %d];\n",
8455 automaton->min_issue_delay_table_compression_factor);
8456 fprintf (output_file, " %s = (%s >> (8 - (",
8457 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8458 output_translate_vect_name (output_file, automaton);
8459 fprintf
8460 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8461 INTERNAL_INSN_CODE_NAME,
8462 automaton->min_issue_delay_table_compression_factor,
8463 8 / automaton->min_issue_delay_table_compression_factor,
8464 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8465 - 1);
8467 if (el == automata_list)
8468 fprintf (output_file, " %s = %s;\n",
8469 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8470 else
8472 fprintf (output_file, " if (%s > %s)\n",
8473 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8474 fprintf (output_file, " %s = %s;\n",
8475 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8478 fprintf (output_file, " break;\n\n");
8481 /* Output function `internal_min_issue_delay'. */
8482 static void
8483 output_internal_min_issue_delay_func ()
8485 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8486 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
8487 fprintf (output_file,
8488 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8489 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8490 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8491 CHIP_PARAMETER_NAME);
8492 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8493 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8494 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8495 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8496 fprintf (output_file,
8497 "\n default:\n %s = -1;\n break;\n }\n",
8498 RESULT_VARIABLE_NAME);
8499 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8500 fprintf (output_file, "}\n\n");
8503 /* The function outputs a code changing state after issue of insns
8504 which have reservations in given AUTOMATA_LIST. */
8505 static void
8506 output_automata_list_transition_code (automata_list)
8507 automata_list_el_t automata_list;
8509 automata_list_el_t el, next_el;
8511 fprintf (output_file, " {\n");
8512 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8513 for (el = automata_list;; el = next_el)
8515 next_el = el->next_automata_list_el;
8516 if (next_el == NULL)
8517 break;
8518 fprintf (output_file, " ");
8519 output_state_member_type (output_file, el->automaton);
8520 fprintf (output_file, " ");
8521 output_temp_chip_member_name (output_file, el->automaton);
8522 fprintf (output_file, ";\n");
8524 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8525 if (comb_vect_p (el->automaton->trans_table))
8527 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8528 output_trans_base_vect_name (output_file, el->automaton);
8529 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8530 output_chip_member_name (output_file, el->automaton);
8531 fprintf (output_file, "] + ");
8532 output_translate_vect_name (output_file, el->automaton);
8533 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8534 fprintf (output_file, " if (");
8535 output_trans_check_vect_name (output_file, el->automaton);
8536 fprintf (output_file, " [%s] != %s->",
8537 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8538 output_chip_member_name (output_file, el->automaton);
8539 fprintf (output_file, ")\n");
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 fprintf (output_file, " ");
8545 if (el->next_automata_list_el != NULL)
8546 output_temp_chip_member_name (output_file, el->automaton);
8547 else
8549 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8550 output_chip_member_name (output_file, el->automaton);
8552 fprintf (output_file, " = ");
8553 output_trans_comb_vect_name (output_file, el->automaton);
8554 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8556 else
8558 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8559 output_trans_full_vect_name (output_file, el->automaton);
8560 fprintf (output_file, " [");
8561 output_translate_vect_name (output_file, el->automaton);
8562 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8563 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8564 output_chip_member_name (output_file, el->automaton);
8565 fprintf (output_file, " * %d];\n",
8566 el->automaton->insn_equiv_classes_num);
8567 fprintf (output_file, " if (%s >= %d)\n",
8568 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8569 fprintf (output_file, " return %s (%s, %s);\n",
8570 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8571 CHIP_PARAMETER_NAME);
8572 fprintf (output_file, " else\n ");
8573 if (el->next_automata_list_el != NULL)
8574 output_temp_chip_member_name (output_file, el->automaton);
8575 else
8577 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8578 output_chip_member_name (output_file, el->automaton);
8580 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8582 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8583 for (el = automata_list;; el = next_el)
8585 next_el = el->next_automata_list_el;
8586 if (next_el == NULL)
8587 break;
8588 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8589 output_chip_member_name (output_file, el->automaton);
8590 fprintf (output_file, " = ");
8591 output_temp_chip_member_name (output_file, el->automaton);
8592 fprintf (output_file, ";\n");
8594 fprintf (output_file, " return -1;\n");
8595 fprintf (output_file, " }\n");
8598 /* Output function `internal_state_transition'. */
8599 static void
8600 output_internal_trans_func ()
8602 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8603 INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
8604 fprintf (output_file,
8605 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
8606 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8607 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
8608 CHIP_NAME, CHIP_PARAMETER_NAME);
8609 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8610 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8611 output_insn_code_cases (output_automata_list_transition_code);
8612 fprintf (output_file, "\n default:\n return -1;\n }\n");
8613 fprintf (output_file, "}\n\n");
8616 /* Output code
8618 if (insn != 0)
8620 insn_code = dfa_insn_code (insn);
8621 if (insn_code > DFA__ADVANCE_CYCLE)
8622 return code;
8624 else
8625 insn_code = DFA__ADVANCE_CYCLE;
8627 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8628 code denotes CODE. */
8629 static void
8630 output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
8631 const char *insn_name;
8632 const char *insn_code_name;
8633 int code;
8635 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8636 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8637 DFA_INSN_CODE_FUNC_NAME, insn_name);
8638 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8639 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8640 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8641 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8645 /* This function outputs `dfa_insn_code' and its helper function
8646 `dfa_insn_code_enlarge'. */
8647 static void
8648 output_dfa_insn_code_func ()
8650 /* Emacs c-mode gets really confused if there's a { or } in column 0
8651 inside a string, so don't do that. */
8652 fprintf (output_file, "\
8653 static void dfa_insn_code_enlarge PARAMS ((int));\n\
8654 static void\n\
8655 dfa_insn_code_enlarge (uid)\n\
8656 int uid;\n{\n\
8657 int i = %s;\n\
8658 %s = 2 * uid;\n\
8659 %s = xrealloc (%s,\n\
8660 %s * sizeof(int));\n\
8661 for (; i < %s; i++)\n\
8662 %s[i] = -1;\n}\n\n",
8663 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8664 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8665 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8666 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8667 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8668 DFA_INSN_CODES_VARIABLE_NAME);
8669 fprintf (output_file, "\
8670 static inline int %s PARAMS ((rtx));\n\
8671 static inline int\n%s (%s)\n\
8672 rtx %s;\n{\n\
8673 int uid = INSN_UID (%s);\n\
8674 int %s;\n\n",
8675 DFA_INSN_CODE_FUNC_NAME, DFA_INSN_CODE_FUNC_NAME,
8676 INSN_PARAMETER_NAME, INSN_PARAMETER_NAME,
8677 INSN_PARAMETER_NAME,
8678 INTERNAL_INSN_CODE_NAME);
8680 fprintf (output_file,
8681 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8682 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8683 fprintf (output_file, " %s = %s[uid];\n",
8684 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8685 fprintf (output_file, "\
8686 if (%s < 0)\n\
8687 {\n\
8688 %s = %s (%s);\n\
8689 %s[uid] = %s;\n\
8690 }\n",
8691 INTERNAL_INSN_CODE_NAME,
8692 INTERNAL_INSN_CODE_NAME,
8693 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8694 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8695 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8698 /* The function outputs PHR interface function `state_transition'. */
8699 static void
8700 output_trans_func ()
8702 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8703 TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8704 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8705 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8706 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8707 INTERNAL_INSN_CODE_NAME, -1);
8708 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8709 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8712 /* The function outputs a code for evaluation of alternative states
8713 number for insns which have reservations in given AUTOMATA_LIST. */
8714 static void
8715 output_automata_list_state_alts_code (automata_list)
8716 automata_list_el_t automata_list;
8718 automata_list_el_t el;
8719 automaton_t automaton;
8721 fprintf (output_file, " {\n");
8722 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8723 if (comb_vect_p (el->automaton->state_alts_table))
8725 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8726 break;
8728 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8730 automaton = el->automaton;
8731 if (comb_vect_p (automaton->state_alts_table))
8733 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8734 output_state_alts_base_vect_name (output_file, automaton);
8735 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8736 output_chip_member_name (output_file, automaton);
8737 fprintf (output_file, "] + ");
8738 output_translate_vect_name (output_file, automaton);
8739 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8740 fprintf (output_file, " if (");
8741 output_state_alts_check_vect_name (output_file, automaton);
8742 fprintf (output_file, " [%s] != %s->",
8743 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8744 output_chip_member_name (output_file, automaton);
8745 fprintf (output_file, ")\n");
8746 fprintf (output_file, " return 0;\n");
8747 fprintf (output_file, " else\n");
8748 fprintf (output_file,
8749 (el == automata_list
8750 ? " %s = " : " %s += "),
8751 RESULT_VARIABLE_NAME);
8752 output_state_alts_comb_vect_name (output_file, automaton);
8753 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8755 else
8757 fprintf (output_file,
8758 (el == automata_list
8759 ? "\n %s = " : " %s += "),
8760 RESULT_VARIABLE_NAME);
8761 output_state_alts_full_vect_name (output_file, automaton);
8762 fprintf (output_file, " [");
8763 output_translate_vect_name (output_file, automaton);
8764 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8765 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8766 output_chip_member_name (output_file, automaton);
8767 fprintf (output_file, " * %d];\n",
8768 automaton->insn_equiv_classes_num);
8771 fprintf (output_file, " break;\n }\n\n");
8774 /* Output function `internal_state_alts'. */
8775 static void
8776 output_internal_state_alts_func ()
8778 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8779 INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8780 fprintf (output_file,
8781 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8782 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8783 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8784 CHIP_PARAMETER_NAME);
8785 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8786 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8787 output_insn_code_cases (output_automata_list_state_alts_code);
8788 fprintf (output_file,
8789 "\n default:\n %s = 0;\n break;\n }\n",
8790 RESULT_VARIABLE_NAME);
8791 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8792 fprintf (output_file, "}\n\n");
8795 /* The function outputs PHR interface function `state_alts'. */
8796 static void
8797 output_state_alts_func ()
8799 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8800 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8801 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8802 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8803 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8804 INTERNAL_INSN_CODE_NAME, 0);
8805 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8806 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8809 /* Output function `min_issue_delay'. */
8810 static void
8811 output_min_issue_delay_func ()
8813 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8814 MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8815 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8816 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8817 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8818 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8819 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8820 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8821 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8822 fprintf (output_file, " }\n else\n %s = %s;\n",
8823 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8824 fprintf (output_file, "\n return %s (%s, %s);\n",
8825 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8826 STATE_NAME);
8827 fprintf (output_file, "}\n\n");
8830 /* Output function `internal_dead_lock'. */
8831 static void
8832 output_internal_dead_lock_func ()
8834 automaton_t automaton;
8836 fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8837 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8838 fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8839 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8840 CHIP_PARAMETER_NAME);
8841 fprintf (output_file, "{\n");
8842 for (automaton = description->first_automaton;
8843 automaton != NULL;
8844 automaton = automaton->next_automaton)
8846 fprintf (output_file, " if (");
8847 output_dead_lock_vect_name (output_file, automaton);
8848 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8849 output_chip_member_name (output_file, automaton);
8850 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8852 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8855 /* The function outputs PHR interface function `state_dead_lock_p'. */
8856 static void
8857 output_dead_lock_func ()
8859 fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8860 DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8861 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8862 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8865 /* Output function `internal_reset'. */
8866 static void
8867 output_internal_reset_func ()
8869 fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8870 INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8871 fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8872 INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8873 CHIP_NAME, CHIP_PARAMETER_NAME);
8874 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8875 CHIP_PARAMETER_NAME, CHIP_NAME);
8878 /* The function outputs PHR interface function `state_size'. */
8879 static void
8880 output_size_func ()
8882 fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8883 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8886 /* The function outputs PHR interface function `state_reset'. */
8887 static void
8888 output_reset_func ()
8890 fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8891 RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8892 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8893 STATE_NAME);
8896 /* Output function `min_insn_conflict_delay'. */
8897 static void
8898 output_min_insn_conflict_delay_func ()
8900 fprintf (output_file,
8901 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8902 MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8903 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8904 STATE_TYPE_NAME, STATE_NAME,
8905 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8906 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8907 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8908 INTERNAL_INSN2_CODE_NAME);
8909 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8910 INTERNAL_INSN_CODE_NAME, 0);
8911 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8912 INTERNAL_INSN2_CODE_NAME, 0);
8913 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8914 CHIP_NAME, STATE_NAME, CHIP_NAME);
8915 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8916 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8917 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8918 fprintf (output_file, " return %s (%s, &%s);\n",
8919 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8920 CHIP_NAME);
8921 fprintf (output_file, "}\n\n");
8924 /* Output function `internal_insn_latency'. */
8925 static void
8926 output_internal_insn_latency_func ()
8928 decl_t decl;
8929 struct bypass_decl *bypass;
8930 int i, j, col;
8931 const char *tabletype = "unsigned char";
8933 /* Find the smallest integer type that can hold all the default
8934 latency values. */
8935 for (i = 0; i < description->decls_num; i++)
8936 if (description->decls[i]->mode == dm_insn_reserv)
8938 decl = description->decls[i];
8939 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8940 && tabletype[0] != 'i') /* don't shrink it */
8941 tabletype = "unsigned short";
8942 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8943 tabletype = "int";
8946 fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8947 INTERNAL_INSN_LATENCY_FUNC_NAME);
8948 fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8949 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8950 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8951 INSN2_PARAMETER_NAME);
8952 fprintf (output_file,
8953 "\n\tint %s ATTRIBUTE_UNUSED;\n\tint %s ATTRIBUTE_UNUSED;\n",
8954 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8955 fprintf (output_file,
8956 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n{\n",
8957 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8959 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8961 fputs (" return 0;\n}\n\n", output_file);
8962 return;
8965 fprintf (output_file, " static const %s default_latencies[] =\n {",
8966 tabletype);
8968 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8969 if (description->decls[i]->mode == dm_insn_reserv
8970 && description->decls[i] != advance_cycle_insn_decl)
8972 if ((col = (col+1) % 8) == 0)
8973 fputs ("\n ", output_file);
8974 decl = description->decls[i];
8975 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
8976 abort ();
8977 fprintf (output_file, "% 4d,",
8978 DECL_INSN_RESERV (decl)->default_latency);
8980 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8981 abort ();
8982 fputs ("\n };\n", output_file);
8984 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8985 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8986 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8988 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8989 for (i = 0; i < description->decls_num; i++)
8990 if (description->decls[i]->mode == dm_insn_reserv
8991 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8993 decl = description->decls [i];
8994 fprintf (output_file,
8995 " case %d:\n switch (%s)\n {\n",
8996 DECL_INSN_RESERV (decl)->insn_num,
8997 INTERNAL_INSN2_CODE_NAME);
8998 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8999 bypass != NULL;
9000 bypass = bypass->next)
9002 if (bypass->in_insn_reserv->insn_num
9003 == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
9004 abort ();
9005 fprintf (output_file, " case %d:\n",
9006 bypass->in_insn_reserv->insn_num);
9007 if (bypass->bypass_guard_name == NULL)
9008 fprintf (output_file, " return %d;\n",
9009 bypass->latency);
9010 else
9012 fprintf (output_file,
9013 " if (%s (%s, %s))\n",
9014 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
9015 INSN2_PARAMETER_NAME);
9016 fprintf (output_file,
9017 " return %d;\n break;\n",
9018 bypass->latency);
9021 fputs (" }\n break;\n", output_file);
9024 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
9025 INTERNAL_INSN_CODE_NAME);
9028 /* The function outputs PHR interface function `insn_latency'. */
9029 static void
9030 output_insn_latency_func ()
9032 fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
9033 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
9034 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
9035 fprintf (output_file, "{\n int %s, %s;\n",
9036 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
9037 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
9038 INTERNAL_INSN_CODE_NAME, 0);
9039 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
9040 INTERNAL_INSN2_CODE_NAME, 0);
9041 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
9042 INTERNAL_INSN_LATENCY_FUNC_NAME,
9043 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
9044 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
9047 /* The function outputs PHR interface function `print_reservation'. */
9048 static void
9049 output_print_reservation_func ()
9051 decl_t decl;
9052 int i, j;
9054 fprintf (output_file,
9055 "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s ATTRIBUTE_UNUSED;\n{\n",
9056 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
9057 INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
9058 INSN_PARAMETER_NAME);
9060 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
9062 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
9063 NOTHING_NAME, FILE_PARAMETER_NAME);
9064 return;
9068 fputs (" static const char *const reservation_names[] =\n {",
9069 output_file);
9071 for (i = 0, j = 0; i < description->decls_num; i++)
9073 decl = description->decls [i];
9074 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9076 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
9077 abort ();
9078 fprintf (output_file, "\n \"%s\",",
9079 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
9080 finish_regexp_representation ();
9083 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
9084 abort ();
9086 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
9087 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
9089 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
9090 INSN_PARAMETER_NAME,
9091 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
9092 fprintf (output_file, " else\n\
9093 {\n\
9094 %s = %s (%s);\n\
9095 if (%s > %s)\n\
9096 %s = %s;\n\
9097 }\n",
9098 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
9099 INSN_PARAMETER_NAME,
9100 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
9101 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
9103 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
9104 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
9107 /* The following function is used to sort unit declaration by their
9108 names. */
9109 static int
9110 units_cmp (unit1, unit2)
9111 const void *unit1, *unit2;
9113 const unit_decl_t u1 = *(unit_decl_t *) unit1;
9114 const unit_decl_t u2 = *(unit_decl_t *) unit2;
9116 return strcmp (u1->name, u2->name);
9119 /* The following macro value is name of struct containing unit name
9120 and unit code. */
9121 #define NAME_CODE_STRUCT_NAME "name_code"
9123 /* The following macro value is name of table of struct name_code. */
9124 #define NAME_CODE_TABLE_NAME "name_code_table"
9126 /* The following macro values are member names for struct name_code. */
9127 #define NAME_MEMBER_NAME "name"
9128 #define CODE_MEMBER_NAME "code"
9130 /* The following macro values are local variable names for function
9131 `get_cpu_unit_code'. */
9132 #define CMP_VARIABLE_NAME "cmp"
9133 #define LOW_VARIABLE_NAME "l"
9134 #define MIDDLE_VARIABLE_NAME "m"
9135 #define HIGH_VARIABLE_NAME "h"
9137 /* The following function outputs function to obtain internal cpu unit
9138 code by the cpu unit name. */
9139 static void
9140 output_get_cpu_unit_code_func ()
9142 int i;
9143 unit_decl_t *units;
9145 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
9146 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
9147 CPU_UNIT_NAME_PARAMETER_NAME);
9148 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
9149 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
9150 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
9151 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
9152 fprintf (output_file, " static struct %s %s [] =\n {\n",
9153 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
9154 units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
9155 * description->units_num);
9156 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
9157 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
9158 for (i = 0; i < description->units_num; i++)
9159 if (units [i]->query_p)
9160 fprintf (output_file, " {\"%s\", %d},\n",
9161 units[i]->name, units[i]->query_num);
9162 fprintf (output_file, " };\n\n");
9163 fprintf (output_file, " /* The following is binary search: */\n");
9164 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
9165 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
9166 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
9167 fprintf (output_file, " while (%s <= %s)\n {\n",
9168 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
9169 fprintf (output_file, " %s = (%s + %s) / 2;\n",
9170 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
9171 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
9172 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
9173 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
9174 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
9175 fprintf (output_file, " %s = %s - 1;\n",
9176 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
9177 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
9178 fprintf (output_file, " %s = %s + 1;\n",
9179 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
9180 fprintf (output_file, " else\n");
9181 fprintf (output_file, " return %s [%s].%s;\n }\n",
9182 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
9183 fprintf (output_file, " return -1;\n}\n\n");
9184 free (units);
9187 /* The following function outputs function to check reservation of cpu
9188 unit (its internal code will be passed as the function argument) in
9189 given cpu state. */
9190 static void
9191 output_cpu_unit_reservation_p ()
9193 automaton_t automaton;
9195 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
9196 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
9197 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
9198 CPU_CODE_PARAMETER_NAME);
9199 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
9200 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
9201 description->query_units_num);
9202 for (automaton = description->first_automaton;
9203 automaton != NULL;
9204 automaton = automaton->next_automaton)
9206 fprintf (output_file, " if ((");
9207 output_reserved_units_table_name (output_file, automaton);
9208 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
9209 output_chip_member_name (output_file, automaton);
9210 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
9211 (description->query_units_num + 7) / 8,
9212 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
9213 fprintf (output_file, " return 1;\n");
9215 fprintf (output_file, " return 0;\n}\n\n");
9218 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
9219 static void
9220 output_dfa_clean_insn_cache_func ()
9222 fprintf (output_file,
9223 "void\n%s ()\n{\n int %s;\n\n",
9224 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
9225 fprintf (output_file,
9226 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
9227 I_VARIABLE_NAME, I_VARIABLE_NAME,
9228 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
9229 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
9232 /* The function outputs PHR interface function `dfa_start'. */
9233 static void
9234 output_dfa_start_func ()
9236 fprintf (output_file,
9237 "void\n%s ()\n{\n %s = get_max_uid ();\n",
9238 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9239 fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
9240 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9241 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
9244 /* The function outputs PHR interface function `dfa_finish'. */
9245 static void
9246 output_dfa_finish_func ()
9248 fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
9249 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
9254 /* The page contains code for output description file (readable
9255 representation of original description and generated DFA(s). */
9257 /* The function outputs string representation of IR reservation. */
9258 static void
9259 output_regexp (regexp)
9260 regexp_t regexp;
9262 fprintf (output_description_file, "%s", regexp_representation (regexp));
9263 finish_regexp_representation ();
9266 /* Output names of units in LIST separated by comma. */
9267 static void
9268 output_unit_set_el_list (list)
9269 unit_set_el_t list;
9271 unit_set_el_t el;
9273 for (el = list; el != NULL; el = el->next_unit_set_el)
9275 if (el != list)
9276 fprintf (output_description_file, ", ");
9277 fprintf (output_description_file, "%s", el->unit_decl->name);
9281 /* Output patterns in LIST separated by comma. */
9282 static void
9283 output_pattern_set_el_list (list)
9284 pattern_set_el_t list;
9286 pattern_set_el_t el;
9287 int i;
9289 for (el = list; el != NULL; el = el->next_pattern_set_el)
9291 if (el != list)
9292 fprintf (output_description_file, ", ");
9293 for (i = 0; i < el->units_num; i++)
9294 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
9295 el->unit_decls [i]->name);
9299 /* The function outputs string representation of IR define_reservation
9300 and define_insn_reservation. */
9301 static void
9302 output_description ()
9304 decl_t decl;
9305 int i;
9307 for (i = 0; i < description->decls_num; i++)
9309 decl = description->decls [i];
9310 if (decl->mode == dm_unit)
9312 if (DECL_UNIT (decl)->excl_list != NULL)
9314 fprintf (output_description_file, "unit %s exlusion_set: ",
9315 DECL_UNIT (decl)->name);
9316 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
9317 fprintf (output_description_file, "\n");
9319 if (DECL_UNIT (decl)->presence_list != NULL)
9321 fprintf (output_description_file, "unit %s presence_set: ",
9322 DECL_UNIT (decl)->name);
9323 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
9324 fprintf (output_description_file, "\n");
9326 if (DECL_UNIT (decl)->final_presence_list != NULL)
9328 fprintf (output_description_file, "unit %s final_presence_set: ",
9329 DECL_UNIT (decl)->name);
9330 output_pattern_set_el_list
9331 (DECL_UNIT (decl)->final_presence_list);
9332 fprintf (output_description_file, "\n");
9334 if (DECL_UNIT (decl)->absence_list != NULL)
9336 fprintf (output_description_file, "unit %s absence_set: ",
9337 DECL_UNIT (decl)->name);
9338 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
9339 fprintf (output_description_file, "\n");
9341 if (DECL_UNIT (decl)->final_absence_list != NULL)
9343 fprintf (output_description_file, "unit %s final_absence_set: ",
9344 DECL_UNIT (decl)->name);
9345 output_pattern_set_el_list
9346 (DECL_UNIT (decl)->final_absence_list);
9347 fprintf (output_description_file, "\n");
9351 fprintf (output_description_file, "\n");
9352 for (i = 0; i < description->decls_num; i++)
9354 decl = description->decls [i];
9355 if (decl->mode == dm_reserv)
9357 fprintf (output_description_file, "reservation ");
9358 fprintf (output_description_file, DECL_RESERV (decl)->name);
9359 fprintf (output_description_file, ": ");
9360 output_regexp (DECL_RESERV (decl)->regexp);
9361 fprintf (output_description_file, "\n");
9363 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9365 fprintf (output_description_file, "insn reservation %s ",
9366 DECL_INSN_RESERV (decl)->name);
9367 print_rtl (output_description_file,
9368 DECL_INSN_RESERV (decl)->condexp);
9369 fprintf (output_description_file, ": ");
9370 output_regexp (DECL_INSN_RESERV (decl)->regexp);
9371 fprintf (output_description_file, "\n");
9373 else if (decl->mode == dm_bypass)
9374 fprintf (output_description_file, "bypass %d %s %s\n",
9375 DECL_BYPASS (decl)->latency,
9376 DECL_BYPASS (decl)->out_insn_name,
9377 DECL_BYPASS (decl)->in_insn_name);
9379 fprintf (output_description_file, "\n\f\n");
9382 /* The function outputs name of AUTOMATON. */
9383 static void
9384 output_automaton_name (f, automaton)
9385 FILE *f;
9386 automaton_t automaton;
9388 if (automaton->corresponding_automaton_decl == NULL)
9389 fprintf (f, "#%d", automaton->automaton_order_num);
9390 else
9391 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
9394 /* Maximal length of line for pretty printing into description
9395 file. */
9396 #define MAX_LINE_LENGTH 70
9398 /* The function outputs units name belonging to AUTOMATON. */
9399 static void
9400 output_automaton_units (automaton)
9401 automaton_t automaton;
9403 decl_t decl;
9404 char *name;
9405 int curr_line_length;
9406 int there_is_an_automaton_unit;
9407 int i;
9409 fprintf (output_description_file, "\n Coresponding units:\n");
9410 fprintf (output_description_file, " ");
9411 curr_line_length = 4;
9412 there_is_an_automaton_unit = 0;
9413 for (i = 0; i < description->decls_num; i++)
9415 decl = description->decls [i];
9416 if (decl->mode == dm_unit
9417 && (DECL_UNIT (decl)->corresponding_automaton_num
9418 == automaton->automaton_order_num))
9420 there_is_an_automaton_unit = 1;
9421 name = DECL_UNIT (decl)->name;
9422 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
9424 curr_line_length = strlen (name) + 4;
9425 fprintf (output_description_file, "\n ");
9427 else
9429 curr_line_length += strlen (name) + 1;
9430 fprintf (output_description_file, " ");
9432 fprintf (output_description_file, name);
9435 if (!there_is_an_automaton_unit)
9436 fprintf (output_description_file, "<None>");
9437 fprintf (output_description_file, "\n\n");
9440 /* The following variable is used for forming array of all possible cpu unit
9441 reservations described by the current DFA state. */
9442 static vla_ptr_t state_reservs;
9444 /* The function forms `state_reservs' for STATE. */
9445 static void
9446 add_state_reservs (state)
9447 state_t state;
9449 alt_state_t curr_alt_state;
9450 reserv_sets_t reservs;
9452 if (state->component_states != NULL)
9453 for (curr_alt_state = state->component_states;
9454 curr_alt_state != NULL;
9455 curr_alt_state = curr_alt_state->next_sorted_alt_state)
9456 add_state_reservs (curr_alt_state->state);
9457 else
9459 reservs = state->reservs;
9460 VLA_PTR_ADD (state_reservs, reservs);
9464 /* The function outputs readable representation of all out arcs of
9465 STATE. */
9466 static void
9467 output_state_arcs (state)
9468 state_t state;
9470 arc_t arc;
9471 ainsn_t ainsn;
9472 char *insn_name;
9473 int curr_line_length;
9475 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
9477 ainsn = arc->insn;
9478 if (!ainsn->first_insn_with_same_reservs)
9479 abort ();
9480 fprintf (output_description_file, " ");
9481 curr_line_length = 7;
9482 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
9485 insn_name = ainsn->insn_reserv_decl->name;
9486 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
9488 if (ainsn != arc->insn)
9490 fprintf (output_description_file, ",\n ");
9491 curr_line_length = strlen (insn_name) + 6;
9493 else
9494 curr_line_length += strlen (insn_name);
9496 else
9498 curr_line_length += strlen (insn_name);
9499 if (ainsn != arc->insn)
9501 curr_line_length += 2;
9502 fprintf (output_description_file, ", ");
9505 fprintf (output_description_file, insn_name);
9506 ainsn = ainsn->next_same_reservs_insn;
9508 while (ainsn != NULL);
9509 fprintf (output_description_file, " %d (%d)\n",
9510 arc->to_state->order_state_num, arc->state_alts);
9512 fprintf (output_description_file, "\n");
9515 /* The following function is used for sorting possible cpu unit
9516 reservation of a DFA state. */
9517 static int
9518 state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
9519 const void *reservs_ptr_1;
9520 const void *reservs_ptr_2;
9522 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9523 *(reserv_sets_t *) reservs_ptr_2);
9526 /* The following function is used for sorting possible cpu unit
9527 reservation of a DFA state. */
9528 static void
9529 remove_state_duplicate_reservs ()
9531 reserv_sets_t *reservs_ptr;
9532 reserv_sets_t *last_formed_reservs_ptr;
9534 last_formed_reservs_ptr = NULL;
9535 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9536 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9537 reservs_ptr++)
9538 if (last_formed_reservs_ptr == NULL)
9539 last_formed_reservs_ptr = reservs_ptr;
9540 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9542 ++last_formed_reservs_ptr;
9543 *last_formed_reservs_ptr = *reservs_ptr;
9545 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9548 /* The following function output readable representation of DFA(s)
9549 state used for fast recognition of pipeline hazards. State is
9550 described by possible (current and scheduled) cpu unit
9551 reservations. */
9552 static void
9553 output_state (state)
9554 state_t state;
9556 reserv_sets_t *reservs_ptr;
9558 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9559 fprintf (output_description_file, " State #%d", state->order_state_num);
9560 fprintf (output_description_file,
9561 state->new_cycle_p ? " (new cycle)\n" : "\n");
9562 add_state_reservs (state);
9563 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9564 sizeof (reserv_sets_t), state_reservs_cmp);
9565 remove_state_duplicate_reservs ();
9566 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9567 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9568 reservs_ptr++)
9570 fprintf (output_description_file, " ");
9571 output_reserv_sets (output_description_file, *reservs_ptr);
9572 fprintf (output_description_file, "\n");
9574 fprintf (output_description_file, "\n");
9575 output_state_arcs (state);
9576 VLA_PTR_DELETE (state_reservs);
9579 /* The following function output readable representation of
9580 DFAs used for fast recognition of pipeline hazards. */
9581 static void
9582 output_automaton_descriptions ()
9584 automaton_t automaton;
9586 for (automaton = description->first_automaton;
9587 automaton != NULL;
9588 automaton = automaton->next_automaton)
9590 fprintf (output_description_file, "\nAutomaton ");
9591 output_automaton_name (output_description_file, automaton);
9592 fprintf (output_description_file, "\n");
9593 output_automaton_units (automaton);
9594 pass_states (automaton, output_state);
9600 /* The page contains top level function for generation DFA(s) used for
9601 PHR. */
9603 /* The function outputs statistics about work of different phases of
9604 DFA generator. */
9605 static void
9606 output_statistics (f)
9607 FILE *f;
9609 automaton_t automaton;
9610 int states_num;
9611 #ifndef NDEBUG
9612 int transition_comb_vect_els = 0;
9613 int transition_full_vect_els = 0;
9614 int state_alts_comb_vect_els = 0;
9615 int state_alts_full_vect_els = 0;
9616 int min_issue_delay_vect_els = 0;
9617 #endif
9619 for (automaton = description->first_automaton;
9620 automaton != NULL;
9621 automaton = automaton->next_automaton)
9623 fprintf (f, "\nAutomaton ");
9624 output_automaton_name (f, automaton);
9625 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9626 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9627 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9628 automaton->DFA_states_num, automaton->DFA_arcs_num);
9629 states_num = automaton->DFA_states_num;
9630 if (!no_minimization_flag)
9632 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9633 automaton->minimal_DFA_states_num,
9634 automaton->minimal_DFA_arcs_num);
9635 states_num = automaton->minimal_DFA_states_num;
9637 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9638 description->insns_num, automaton->insn_equiv_classes_num);
9639 #ifndef NDEBUG
9640 fprintf
9641 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9642 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9643 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9644 (comb_vect_p (automaton->trans_table)
9645 ? "use comb vect" : "use simple vect"));
9646 fprintf
9647 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9648 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9649 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9650 (comb_vect_p (automaton->state_alts_table)
9651 ? "use comb vect" : "use simple vect"));
9652 fprintf
9653 (f, "%5ld min delay table els, compression factor %d\n",
9654 (long) states_num * automaton->insn_equiv_classes_num,
9655 automaton->min_issue_delay_table_compression_factor);
9656 transition_comb_vect_els
9657 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9658 transition_full_vect_els
9659 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9660 state_alts_comb_vect_els
9661 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9662 state_alts_full_vect_els
9663 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9664 min_issue_delay_vect_els
9665 += states_num * automaton->insn_equiv_classes_num;
9666 #endif
9668 #ifndef NDEBUG
9669 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9670 allocated_states_num, allocated_arcs_num);
9671 fprintf (f, "%5d all allocated alternative states\n",
9672 allocated_alt_states_num);
9673 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9674 transition_comb_vect_els, transition_full_vect_els);
9675 fprintf
9676 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9677 state_alts_comb_vect_els, state_alts_full_vect_els);
9678 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9679 fprintf (f, "%5d locked states num\n", locked_states_num);
9680 #endif
9683 /* The function output times of work of different phases of DFA
9684 generator. */
9685 static void
9686 output_time_statistics (f)
9687 FILE *f;
9689 fprintf (f, "\n transformation: ");
9690 print_active_time (f, transform_time);
9691 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9692 print_active_time (f, NDFA_time);
9693 if (ndfa_flag)
9695 fprintf (f, ", NDFA -> DFA: ");
9696 print_active_time (f, NDFA_to_DFA_time);
9698 fprintf (f, "\n DFA minimization: ");
9699 print_active_time (f, minimize_time);
9700 fprintf (f, ", making insn equivalence: ");
9701 print_active_time (f, equiv_time);
9702 fprintf (f, "\n all automaton generation: ");
9703 print_active_time (f, automaton_generation_time);
9704 fprintf (f, ", output: ");
9705 print_active_time (f, output_time);
9706 fprintf (f, "\n");
9709 /* The function generates DFA (deterministic finite state automaton)
9710 for fast recognition of pipeline hazards. No errors during
9711 checking must be fixed before this function call. */
9712 static void
9713 generate ()
9715 automata_num = split_argument;
9716 if (description->units_num < automata_num)
9717 automata_num = description->units_num;
9718 initiate_states ();
9719 initiate_arcs ();
9720 initiate_automata_lists ();
9721 initiate_pass_states ();
9722 initiate_excl_sets ();
9723 initiate_presence_absence_pattern_sets ();
9724 automaton_generation_time = create_ticker ();
9725 create_automata ();
9726 ticker_off (&automaton_generation_time);
9731 /* The following function creates insn attribute whose values are
9732 number alternatives in insn reservations. */
9733 static void
9734 make_insn_alts_attr ()
9736 int i, insn_num;
9737 decl_t decl;
9738 rtx condexp;
9740 condexp = rtx_alloc (COND);
9741 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9742 XEXP (condexp, 1) = make_numeric_value (0);
9743 for (i = insn_num = 0; i < description->decls_num; i++)
9745 decl = description->decls [i];
9746 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9748 XVECEXP (condexp, 0, 2 * insn_num)
9749 = DECL_INSN_RESERV (decl)->condexp;
9750 XVECEXP (condexp, 0, 2 * insn_num + 1)
9751 = make_numeric_value
9752 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9753 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9754 ->transformed_regexp)->regexps_num);
9755 insn_num++;
9758 if (description->insns_num != insn_num + 1)
9759 abort ();
9760 make_internal_attr (attr_printf (sizeof ("*")
9761 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9762 "*%s", INSN_ALTS_FUNC_NAME),
9763 condexp, 0);
9768 /* The following function creates attribute which is order number of
9769 insn in pipeline hazard description translator. */
9770 static void
9771 make_internal_dfa_insn_code_attr ()
9773 int i, insn_num;
9774 decl_t decl;
9775 rtx condexp;
9777 condexp = rtx_alloc (COND);
9778 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9779 XEXP (condexp, 1)
9780 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9781 ->insn_num + 1);
9782 for (i = insn_num = 0; i < description->decls_num; i++)
9784 decl = description->decls [i];
9785 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9787 XVECEXP (condexp, 0, 2 * insn_num)
9788 = DECL_INSN_RESERV (decl)->condexp;
9789 XVECEXP (condexp, 0, 2 * insn_num + 1)
9790 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9791 insn_num++;
9794 if (description->insns_num != insn_num + 1)
9795 abort ();
9796 make_internal_attr
9797 (attr_printf (sizeof ("*")
9798 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9799 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9800 condexp, 0);
9805 /* The following function creates attribute which order number of insn
9806 in pipeline hazard description translator. */
9807 static void
9808 make_default_insn_latency_attr ()
9810 int i, insn_num;
9811 decl_t decl;
9812 rtx condexp;
9814 condexp = rtx_alloc (COND);
9815 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9816 XEXP (condexp, 1) = make_numeric_value (0);
9817 for (i = insn_num = 0; i < description->decls_num; i++)
9819 decl = description->decls [i];
9820 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9822 XVECEXP (condexp, 0, 2 * insn_num)
9823 = DECL_INSN_RESERV (decl)->condexp;
9824 XVECEXP (condexp, 0, 2 * insn_num + 1)
9825 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9826 insn_num++;
9829 if (description->insns_num != insn_num + 1)
9830 abort ();
9831 make_internal_attr (attr_printf (sizeof ("*")
9832 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9833 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9834 condexp, 0);
9839 /* The following function creates attribute which returns 1 if given
9840 output insn has bypassing and 0 otherwise. */
9841 static void
9842 make_bypass_attr ()
9844 int i, bypass_insn;
9845 int bypass_insns_num = 0;
9846 decl_t decl;
9847 rtx result_rtx;
9849 for (i = 0; i < description->decls_num; i++)
9851 decl = description->decls [i];
9852 if (decl->mode == dm_insn_reserv
9853 && DECL_INSN_RESERV (decl)->condexp != NULL
9854 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9855 bypass_insns_num++;
9857 if (bypass_insns_num == 0)
9858 result_rtx = make_numeric_value (0);
9859 else
9861 result_rtx = rtx_alloc (COND);
9862 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9863 XEXP (result_rtx, 1) = make_numeric_value (0);
9865 for (i = bypass_insn = 0; i < description->decls_num; i++)
9867 decl = description->decls [i];
9868 if (decl->mode == dm_insn_reserv
9869 && DECL_INSN_RESERV (decl)->condexp != NULL
9870 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9872 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9873 = DECL_INSN_RESERV (decl)->condexp;
9874 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9875 = make_numeric_value (1);
9876 bypass_insn++;
9880 make_internal_attr (attr_printf (sizeof ("*")
9881 + strlen (BYPASS_P_FUNC_NAME) + 1,
9882 "*%s", BYPASS_P_FUNC_NAME),
9883 result_rtx, 0);
9888 /* This page mainly contains top level functions of pipeline hazards
9889 description translator. */
9891 /* The following macro value is suffix of name of description file of
9892 pipeline hazards description translator. */
9893 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9895 /* The function returns suffix of given file name. The returned
9896 string can not be changed. */
9897 static const char *
9898 file_name_suffix (file_name)
9899 const char *file_name;
9901 const char *last_period;
9903 for (last_period = NULL; *file_name != '\0'; file_name++)
9904 if (*file_name == '.')
9905 last_period = file_name;
9906 return (last_period == NULL ? file_name : last_period);
9909 /* The function returns base name of given file name, i.e. pointer to
9910 first char after last `/' (or `\' for WIN32) in given file name,
9911 given file name itself if the directory name is absent. The
9912 returned string can not be changed. */
9913 static const char *
9914 base_file_name (file_name)
9915 const char *file_name;
9917 int directory_name_length;
9919 directory_name_length = strlen (file_name);
9920 #ifdef WIN32
9921 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9922 && file_name[directory_name_length] != '\\')
9923 #else
9924 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9925 #endif
9926 directory_name_length--;
9927 return file_name + directory_name_length + 1;
9930 /* The following is top level function to initialize the work of
9931 pipeline hazards description translator. */
9932 void
9933 initiate_automaton_gen (argc, argv)
9934 int argc;
9935 char **argv;
9937 const char *base_name;
9938 int i;
9940 ndfa_flag = 0;
9941 split_argument = 0; /* default value */
9942 no_minimization_flag = 0;
9943 time_flag = 0;
9944 v_flag = 0;
9945 w_flag = 0;
9946 for (i = 2; i < argc; i++)
9947 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9948 no_minimization_flag = 1;
9949 else if (strcmp (argv [i], TIME_OPTION) == 0)
9950 time_flag = 1;
9951 else if (strcmp (argv [i], V_OPTION) == 0)
9952 v_flag = 1;
9953 else if (strcmp (argv [i], W_OPTION) == 0)
9954 w_flag = 1;
9955 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9956 ndfa_flag = 1;
9957 else if (strcmp (argv [i], "-split") == 0)
9959 if (i + 1 >= argc)
9960 fatal ("-split has no argument.");
9961 fatal ("option `-split' has not been implemented yet\n");
9962 /* split_argument = atoi (argument_vect [i + 1]); */
9964 VLA_PTR_CREATE (decls, 150, "decls");
9965 /* Initialize IR storage. */
9966 obstack_init (&irp);
9967 initiate_automaton_decl_table ();
9968 initiate_insn_decl_table ();
9969 initiate_decl_table ();
9970 output_file = stdout;
9971 output_description_file = NULL;
9972 base_name = base_file_name (argv[1]);
9973 obstack_grow (&irp, base_name,
9974 strlen (base_name) - strlen (file_name_suffix (base_name)));
9975 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9976 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9977 obstack_1grow (&irp, '\0');
9978 output_description_file_name = obstack_base (&irp);
9979 obstack_finish (&irp);
9982 /* The following function checks existence at least one arc marked by
9983 each insn. */
9984 static void
9985 check_automata_insn_issues ()
9987 automaton_t automaton;
9988 ainsn_t ainsn, reserv_ainsn;
9990 for (automaton = description->first_automaton;
9991 automaton != NULL;
9992 automaton = automaton->next_automaton)
9994 for (ainsn = automaton->ainsn_list;
9995 ainsn != NULL;
9996 ainsn = ainsn->next_ainsn)
9997 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9999 for (reserv_ainsn = ainsn;
10000 reserv_ainsn != NULL;
10001 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
10002 if (automaton->corresponding_automaton_decl != NULL)
10004 if (!w_flag)
10005 error ("Automaton `%s': Insn `%s' will never be issued",
10006 automaton->corresponding_automaton_decl->name,
10007 reserv_ainsn->insn_reserv_decl->name);
10008 else
10009 warning
10010 ("Automaton `%s': Insn `%s' will never be issued",
10011 automaton->corresponding_automaton_decl->name,
10012 reserv_ainsn->insn_reserv_decl->name);
10014 else
10016 if (!w_flag)
10017 error ("Insn `%s' will never be issued",
10018 reserv_ainsn->insn_reserv_decl->name);
10019 else
10020 warning ("Insn `%s' will never be issued",
10021 reserv_ainsn->insn_reserv_decl->name);
10027 /* The following vla is used for storing pointers to all achieved
10028 states. */
10029 static vla_ptr_t automaton_states;
10031 /* This function is called by function pass_states to add an achieved
10032 STATE. */
10033 static void
10034 add_automaton_state (state)
10035 state_t state;
10037 VLA_PTR_ADD (automaton_states, state);
10040 /* The following function forms list of important automata (whose
10041 states may be changed after the insn issue) for each insn. */
10042 static void
10043 form_important_insn_automata_lists ()
10045 automaton_t automaton;
10046 state_t *state_ptr;
10047 decl_t decl;
10048 ainsn_t ainsn;
10049 arc_t arc;
10050 int i;
10052 VLA_PTR_CREATE (automaton_states, 1500,
10053 "automaton states for forming important insn automata sets");
10054 /* Mark important ainsns. */
10055 for (automaton = description->first_automaton;
10056 automaton != NULL;
10057 automaton = automaton->next_automaton)
10059 VLA_PTR_NULLIFY (automaton_states);
10060 pass_states (automaton, add_automaton_state);
10061 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
10062 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
10063 state_ptr++)
10065 for (arc = first_out_arc (*state_ptr);
10066 arc != NULL;
10067 arc = next_out_arc (arc))
10068 if (arc->to_state != *state_ptr)
10070 if (!arc->insn->first_insn_with_same_reservs)
10071 abort ();
10072 for (ainsn = arc->insn;
10073 ainsn != NULL;
10074 ainsn = ainsn->next_same_reservs_insn)
10075 ainsn->important_p = TRUE;
10079 VLA_PTR_DELETE (automaton_states);
10080 /* Create automata sets for the insns. */
10081 for (i = 0; i < description->decls_num; i++)
10083 decl = description->decls [i];
10084 if (decl->mode == dm_insn_reserv)
10086 automata_list_start ();
10087 for (automaton = description->first_automaton;
10088 automaton != NULL;
10089 automaton = automaton->next_automaton)
10090 for (ainsn = automaton->ainsn_list;
10091 ainsn != NULL;
10092 ainsn = ainsn->next_ainsn)
10093 if (ainsn->important_p
10094 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
10096 automata_list_add (automaton);
10097 break;
10099 DECL_INSN_RESERV (decl)->important_automata_list
10100 = automata_list_finish ();
10106 /* The following is top level function to generate automat(a,on) for
10107 fast recognition of pipeline hazards. */
10108 void
10109 expand_automata ()
10111 int i;
10113 description = create_node (sizeof (struct description)
10114 /* One entry for cycle advancing insn. */
10115 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
10116 description->decls_num = VLA_PTR_LENGTH (decls);
10117 description->query_units_num = 0;
10118 for (i = 0; i < description->decls_num; i++)
10120 description->decls [i] = VLA_PTR (decls, i);
10121 if (description->decls [i]->mode == dm_unit
10122 && DECL_UNIT (description->decls [i])->query_p)
10123 DECL_UNIT (description->decls [i])->query_num
10124 = description->query_units_num++;
10126 all_time = create_ticker ();
10127 check_time = create_ticker ();
10128 fprintf (stderr, "Check description...");
10129 fflush (stderr);
10130 check_all_description ();
10131 fprintf (stderr, "done\n");
10132 ticker_off (&check_time);
10133 generation_time = create_ticker ();
10134 if (!have_error)
10136 transform_insn_regexps ();
10137 check_unit_distributions_to_automata ();
10139 if (!have_error)
10141 generate ();
10142 check_automata_insn_issues ();
10144 if (!have_error)
10146 form_important_insn_automata_lists ();
10147 fprintf (stderr, "Generation of attributes...");
10148 fflush (stderr);
10149 make_internal_dfa_insn_code_attr ();
10150 make_insn_alts_attr ();
10151 make_default_insn_latency_attr ();
10152 make_bypass_attr ();
10153 fprintf (stderr, "done\n");
10155 ticker_off (&generation_time);
10156 ticker_off (&all_time);
10157 fprintf (stderr, "All other genattrtab stuff...");
10158 fflush (stderr);
10161 /* The following is top level function to output PHR and to finish
10162 work with pipeline description translator. */
10163 void
10164 write_automata ()
10166 fprintf (stderr, "done\n");
10167 if (have_error)
10168 fatal ("Errors in DFA description");
10169 ticker_on (&all_time);
10170 output_time = create_ticker ();
10171 fprintf (stderr, "Forming and outputing automata tables...");
10172 fflush (stderr);
10173 output_dfa_max_issue_rate ();
10174 output_tables ();
10175 fprintf (stderr, "done\n");
10176 fprintf (stderr, "Output functions to work with automata...");
10177 fflush (stderr);
10178 output_chip_definitions ();
10179 output_max_insn_queue_index_def ();
10180 output_internal_min_issue_delay_func ();
10181 output_internal_trans_func ();
10182 /* Cache of insn dfa codes: */
10183 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
10184 fprintf (output_file, "\nstatic int %s;\n\n",
10185 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
10186 output_dfa_insn_code_func ();
10187 output_trans_func ();
10188 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
10189 output_internal_state_alts_func ();
10190 output_state_alts_func ();
10191 fprintf (output_file, "\n#endif /* #if %s */\n\n",
10192 AUTOMATON_STATE_ALTS_MACRO_NAME);
10193 output_min_issue_delay_func ();
10194 output_internal_dead_lock_func ();
10195 output_dead_lock_func ();
10196 output_size_func ();
10197 output_internal_reset_func ();
10198 output_reset_func ();
10199 output_min_insn_conflict_delay_func ();
10200 output_internal_insn_latency_func ();
10201 output_insn_latency_func ();
10202 output_print_reservation_func ();
10203 /* Output function get_cpu_unit_code. */
10204 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
10205 output_get_cpu_unit_code_func ();
10206 output_cpu_unit_reservation_p ();
10207 fprintf (output_file, "\n#endif /* #if %s */\n\n",
10208 CPU_UNITS_QUERY_MACRO_NAME);
10209 output_dfa_clean_insn_cache_func ();
10210 output_dfa_start_func ();
10211 output_dfa_finish_func ();
10212 fprintf (stderr, "done\n");
10213 if (v_flag)
10215 output_description_file = fopen (output_description_file_name, "w");
10216 if (output_description_file == NULL)
10218 perror (output_description_file_name);
10219 exit (FATAL_EXIT_CODE);
10221 fprintf (stderr, "Output automata description...");
10222 fflush (stderr);
10223 output_description ();
10224 output_automaton_descriptions ();
10225 fprintf (stderr, "done\n");
10226 output_statistics (output_description_file);
10228 output_statistics (stderr);
10229 ticker_off (&output_time);
10230 output_time_statistics (stderr);
10231 finish_states ();
10232 finish_arcs ();
10233 finish_automata_lists ();
10234 if (time_flag)
10236 fprintf (stderr, "Summary:\n");
10237 fprintf (stderr, " check time ");
10238 print_active_time (stderr, check_time);
10239 fprintf (stderr, ", generation time ");
10240 print_active_time (stderr, generation_time);
10241 fprintf (stderr, ", all time ");
10242 print_active_time (stderr, all_time);
10243 fprintf (stderr, "\n");
10245 /* Finish all work. */
10246 if (output_description_file != NULL)
10248 fflush (output_description_file);
10249 if (ferror (stdout) != 0)
10250 fatal ("Error in writing DFA description file %s",
10251 output_description_file_name);
10252 fclose (output_description_file);
10254 finish_automaton_decl_table ();
10255 finish_insn_decl_table ();
10256 finish_decl_table ();
10257 obstack_free (&irp, NULL);
10258 if (have_error && output_description_file != NULL)
10259 remove (output_description_file_name);