This commit was manufactured by cvs2svn to create branch
[official-gcc.git] / gcc / genautomata.c
blobb68c63c60b51be980e535ee4fb43bf5aa8e718ec
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004 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 (size_t);
219 static void *copy_node (const void *, size_t);
220 static char *check_name (char *, pos_t);
221 static char *next_sep_el (char **, int, int);
222 static int n_sep_els (char *, int, int);
223 static char **get_str_vect (char *, int *, int, int);
224 static void gen_presence_absence_set (rtx, int, int);
225 static regexp_t gen_regexp_el (char *);
226 static regexp_t gen_regexp_repeat (char *);
227 static regexp_t gen_regexp_allof (char *);
228 static regexp_t gen_regexp_oneof (char *);
229 static regexp_t gen_regexp_sequence (char *);
230 static regexp_t gen_regexp (char *);
232 static unsigned string_hash (const char *);
233 static unsigned automaton_decl_hash (const void *);
234 static int automaton_decl_eq_p (const void *,
235 const void *);
236 static decl_t insert_automaton_decl (decl_t);
237 static decl_t find_automaton_decl (char *);
238 static void initiate_automaton_decl_table (void);
239 static void finish_automaton_decl_table (void);
241 static hashval_t insn_decl_hash (const void *);
242 static int insn_decl_eq_p (const void *,
243 const void *);
244 static decl_t insert_insn_decl (decl_t);
245 static decl_t find_insn_decl (char *);
246 static void initiate_insn_decl_table (void);
247 static void finish_insn_decl_table (void);
249 static hashval_t decl_hash (const void *);
250 static int decl_eq_p (const void *,
251 const void *);
252 static decl_t insert_decl (decl_t);
253 static decl_t find_decl (char *);
254 static void initiate_decl_table (void);
255 static void finish_decl_table (void);
257 static unit_set_el_t process_excls (char **, int, pos_t);
258 static void add_excls (unit_set_el_t, unit_set_el_t,
259 pos_t);
260 static unit_set_el_t process_presence_absence_names
261 (char **, int, pos_t,
262 int, int);
263 static pattern_set_el_t process_presence_absence_patterns
264 (char ***, int, pos_t,
265 int, int);
266 static void add_presence_absence (unit_set_el_t,
267 pattern_set_el_t,
268 pos_t, int, int);
269 static void process_decls (void);
270 static struct bypass_decl *find_bypass (struct bypass_decl *,
271 struct insn_reserv_decl *);
272 static void check_automaton_usage (void);
273 static regexp_t process_regexp (regexp_t);
274 static void process_regexp_decls (void);
275 static void check_usage (void);
276 static int loop_in_regexp (regexp_t, decl_t);
277 static void check_loops_in_regexps (void);
278 static void process_regexp_cycles (regexp_t, int, int,
279 int *, int *);
280 static void evaluate_max_reserv_cycles (void);
281 static void check_all_description (void);
283 static ticker_t create_ticker (void);
284 static void ticker_off (ticker_t *);
285 static void ticker_on (ticker_t *);
286 static int active_time (ticker_t);
287 static void print_active_time (FILE *, ticker_t);
289 static void add_advance_cycle_insn_decl (void);
291 static alt_state_t get_free_alt_state (void);
292 static void free_alt_state (alt_state_t);
293 static void free_alt_states (alt_state_t);
294 static int alt_state_cmp (const void *alt_state_ptr_1,
295 const void *alt_state_ptr_2);
296 static alt_state_t uniq_sort_alt_states (alt_state_t);
297 static int alt_states_eq (alt_state_t, alt_state_t);
298 static void initiate_alt_states (void);
299 static void finish_alt_states (void);
301 static reserv_sets_t alloc_empty_reserv_sets (void);
302 static unsigned reserv_sets_hash_value (reserv_sets_t);
303 static int reserv_sets_cmp (reserv_sets_t, reserv_sets_t);
304 static int reserv_sets_eq (reserv_sets_t, reserv_sets_t);
305 static void set_unit_reserv (reserv_sets_t, int, int);
306 static int test_unit_reserv (reserv_sets_t, int, int);
307 static int it_is_empty_reserv_sets (reserv_sets_t)
308 ATTRIBUTE_UNUSED;
309 static int reserv_sets_are_intersected (reserv_sets_t, reserv_sets_t);
310 static void reserv_sets_shift (reserv_sets_t, reserv_sets_t);
311 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
312 reserv_sets_t);
313 static void reserv_sets_and (reserv_sets_t, reserv_sets_t,
314 reserv_sets_t)
315 ATTRIBUTE_UNUSED;
316 static void output_cycle_reservs (FILE *, reserv_sets_t,
317 int, int);
318 static void output_reserv_sets (FILE *, reserv_sets_t);
319 static state_t get_free_state (int, automaton_t);
320 static void free_state (state_t);
321 static hashval_t state_hash (const void *);
322 static int state_eq_p (const void *, const void *);
323 static state_t insert_state (state_t);
324 static void set_state_reserv (state_t, int, int);
325 static int intersected_state_reservs_p (state_t, state_t);
326 static state_t states_union (state_t, state_t, reserv_sets_t);
327 static state_t state_shift (state_t, reserv_sets_t);
328 static void initiate_states (void);
329 static void finish_states (void);
331 static void free_arc (arc_t);
332 static void remove_arc (state_t, arc_t);
333 static arc_t find_arc (state_t, state_t, ainsn_t);
334 static arc_t add_arc (state_t, state_t, ainsn_t, int);
335 static arc_t first_out_arc (state_t);
336 static arc_t next_out_arc (arc_t);
337 static void initiate_arcs (void);
338 static void finish_arcs (void);
340 static automata_list_el_t get_free_automata_list_el (void);
341 static void free_automata_list_el (automata_list_el_t);
342 static void free_automata_list (automata_list_el_t);
343 static hashval_t automata_list_hash (const void *);
344 static int automata_list_eq_p (const void *, const void *);
345 static void initiate_automata_lists (void);
346 static void automata_list_start (void);
347 static void automata_list_add (automaton_t);
348 static automata_list_el_t automata_list_finish (void);
349 static void finish_automata_lists (void);
351 static void initiate_excl_sets (void);
352 static reserv_sets_t get_excl_set (reserv_sets_t);
354 static pattern_reserv_t form_reserv_sets_list (pattern_set_el_t);
355 static void initiate_presence_absence_pattern_sets (void);
356 static int check_presence_pattern_sets (reserv_sets_t,
357 reserv_sets_t, int);
358 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
359 int);
361 static regexp_t copy_insn_regexp (regexp_t);
362 static regexp_t transform_1 (regexp_t);
363 static regexp_t transform_2 (regexp_t);
364 static regexp_t transform_3 (regexp_t);
365 static regexp_t regexp_transform_func
366 (regexp_t, regexp_t (*) (regexp_t));
367 static regexp_t transform_regexp (regexp_t);
368 static void transform_insn_regexps (void);
370 static void store_alt_unit_usage (regexp_t, regexp_t, int, int);
371 static void check_regexp_units_distribution (const char *, regexp_t);
372 static void check_unit_distributions_to_automata (void);
374 static int process_seq_for_forming_states (regexp_t, automaton_t,
375 int);
376 static void finish_forming_alt_state (alt_state_t,
377 automaton_t);
378 static void process_alts_for_forming_states (regexp_t,
379 automaton_t, int);
380 static void create_alt_states (automaton_t);
382 static void form_ainsn_with_same_reservs (automaton_t);
384 static reserv_sets_t form_reservs_matter (automaton_t);
385 static void make_automaton (automaton_t);
386 static void form_arcs_marked_by_insn (state_t);
387 static int create_composed_state (state_t, arc_t, vla_ptr_t *);
388 static void NDFA_to_DFA (automaton_t);
389 static void pass_state_graph (state_t, void (*) (state_t));
390 static void pass_states (automaton_t,
391 void (*) (state_t));
392 static void initiate_pass_states (void);
393 static void add_achieved_state (state_t);
394 static int set_out_arc_insns_equiv_num (state_t, int);
395 static void clear_arc_insns_equiv_num (state_t);
396 static void copy_equiv_class (vla_ptr_t *to,
397 const vla_ptr_t *from);
398 static int first_cycle_unit_presence (state_t, int);
399 static int state_is_differed (state_t, state_t, int, int);
400 static state_t init_equiv_class (state_t *states, int);
401 static int partition_equiv_class (state_t *, int,
402 vla_ptr_t *, int *);
403 static void evaluate_equiv_classes (automaton_t, vla_ptr_t *);
404 static void merge_states (automaton_t, vla_ptr_t *);
405 static void set_new_cycle_flags (state_t);
406 static void minimize_DFA (automaton_t);
407 static void incr_states_and_arcs_nums (state_t);
408 static void count_states_and_arcs (automaton_t, int *, int *);
409 static void build_automaton (automaton_t);
411 static void set_order_state_num (state_t);
412 static void enumerate_states (automaton_t);
414 static ainsn_t insert_ainsn_into_equiv_class (ainsn_t, ainsn_t);
415 static void delete_ainsn_from_equiv_class (ainsn_t);
416 static void process_insn_equiv_class (ainsn_t, arc_t *);
417 static void process_state_for_insn_equiv_partition (state_t);
418 static void set_insn_equiv_classes (automaton_t);
420 static double estimate_one_automaton_bound (void);
421 static int compare_max_occ_cycle_nums (const void *,
422 const void *);
423 static void units_to_automata_heuristic_distr (void);
424 static ainsn_t create_ainsns (void);
425 static void units_to_automata_distr (void);
426 static void create_automata (void);
428 static void form_regexp (regexp_t);
429 static const char *regexp_representation (regexp_t);
430 static void finish_regexp_representation (void);
432 static void output_range_type (FILE *, long int, long int);
433 static int longest_path_length (state_t);
434 static void process_state_longest_path_length (state_t);
435 static void output_dfa_max_issue_rate (void);
436 static void output_vect (vect_el_t *, int);
437 static void output_chip_member_name (FILE *, automaton_t);
438 static void output_temp_chip_member_name (FILE *, automaton_t);
439 static void output_translate_vect_name (FILE *, automaton_t);
440 static void output_trans_full_vect_name (FILE *, automaton_t);
441 static void output_trans_comb_vect_name (FILE *, automaton_t);
442 static void output_trans_check_vect_name (FILE *, automaton_t);
443 static void output_trans_base_vect_name (FILE *, automaton_t);
444 static void output_state_alts_full_vect_name (FILE *, automaton_t);
445 static void output_state_alts_comb_vect_name (FILE *, automaton_t);
446 static void output_state_alts_check_vect_name (FILE *, automaton_t);
447 static void output_state_alts_base_vect_name (FILE *, automaton_t);
448 static void output_min_issue_delay_vect_name (FILE *, automaton_t);
449 static void output_dead_lock_vect_name (FILE *, automaton_t);
450 static void output_reserved_units_table_name (FILE *, automaton_t);
451 static void output_state_member_type (FILE *, automaton_t);
452 static void output_chip_definitions (void);
453 static void output_translate_vect (automaton_t);
454 static int comb_vect_p (state_ainsn_table_t);
455 static state_ainsn_table_t create_state_ainsn_table (automaton_t);
456 static void output_state_ainsn_table
457 (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 (state_ainsn_table_t,
461 int, vect_el_t *, int);
462 static int out_state_arcs_num (state_t);
463 static int compare_transition_els_num (const void *, const void *);
464 static void add_vect_el (vla_hwint_t *,
465 ainsn_t, int);
466 static void add_states_vect_el (state_t);
467 static void output_trans_table (automaton_t);
468 static void output_state_alts_table (automaton_t);
469 static int min_issue_delay_pass_states (state_t, ainsn_t);
470 static int min_issue_delay (state_t, ainsn_t);
471 static void initiate_min_issue_delay_pass_states (void);
472 static void output_min_issue_delay_table (automaton_t);
473 static void output_dead_lock_vect (automaton_t);
474 static void output_reserved_units_table (automaton_t);
475 static void output_tables (void);
476 static void output_max_insn_queue_index_def (void);
477 static void output_insn_code_cases (void (*) (automata_list_el_t));
478 static void output_automata_list_min_issue_delay_code (automata_list_el_t);
479 static void output_internal_min_issue_delay_func (void);
480 static void output_automata_list_transition_code (automata_list_el_t);
481 static void output_internal_trans_func (void);
482 static void output_internal_insn_code_evaluation (const char *,
483 const char *, int);
484 static void output_dfa_insn_code_func (void);
485 static void output_trans_func (void);
486 static void output_automata_list_state_alts_code (automata_list_el_t);
487 static void output_internal_state_alts_func (void);
488 static void output_state_alts_func (void);
489 static void output_min_issue_delay_func (void);
490 static void output_internal_dead_lock_func (void);
491 static void output_dead_lock_func (void);
492 static void output_internal_reset_func (void);
493 static void output_size_func (void);
494 static void output_reset_func (void);
495 static void output_min_insn_conflict_delay_func (void);
496 static void output_internal_insn_latency_func (void);
497 static void output_insn_latency_func (void);
498 static void output_print_reservation_func (void);
499 static int units_cmp (const void *,
500 const void *);
501 static void output_get_cpu_unit_code_func (void);
502 static void output_cpu_unit_reservation_p (void);
503 static void output_dfa_clean_insn_cache_func (void);
504 static void output_dfa_start_func (void);
505 static void output_dfa_finish_func (void);
507 static void output_regexp (regexp_t );
508 static void output_unit_set_el_list (unit_set_el_t);
509 static void output_pattern_set_el_list (pattern_set_el_t);
510 static void output_description (void);
511 static void output_automaton_name (FILE *, automaton_t);
512 static void output_automaton_units (automaton_t);
513 static void add_state_reservs (state_t);
514 static void output_state_arcs (state_t);
515 static int state_reservs_cmp (const void *,
516 const void *);
517 static void remove_state_duplicate_reservs (void);
518 static void output_state (state_t);
519 static void output_automaton_descriptions (void);
520 static void output_statistics (FILE *);
521 static void output_time_statistics (FILE *);
522 static void generate (void);
524 static void make_insn_alts_attr (void);
525 static void make_internal_dfa_insn_code_attr (void);
526 static void make_default_insn_latency_attr (void);
527 static void make_bypass_attr (void);
528 static const char *file_name_suffix (const char *);
529 static const char *base_file_name (const char *);
530 static void check_automata_insn_issues (void);
531 static void add_automaton_state (state_t);
532 static void form_important_insn_automata_lists (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 #define PROGRESS_OPTION "-progress"
663 /* The following flags are set up by function `initiate_automaton_gen'. */
665 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
666 static int ndfa_flag;
668 /* Do not make minimization of DFA (`-no-minimization'). */
669 static int no_minimization_flag;
671 /* Value of this variable is number of automata being generated. The
672 actual number of automata may be less this value if there is not
673 sufficient number of units. This value is defined by argument of
674 option `-split' or by constructions automaton if the value is zero
675 (it is default value of the argument). */
676 static int split_argument;
678 /* Flag of output time statistics (`-time'). */
679 static int time_flag;
681 /* Flag of creation of description file which contains description of
682 result automaton and statistics information (`-v'). */
683 static int v_flag;
685 /* Flag of output of a progress bar showing how many states were
686 generated so far for automaton being processed (`-progress'). */
687 static int progress_flag;
689 /* Flag of generating warning instead of error for non-critical errors
690 (`-w'). */
691 static int w_flag;
694 /* Output file for pipeline hazard recognizer (PHR) being generated.
695 The value is NULL if the file is not defined. */
696 static FILE *output_file;
698 /* Description file of PHR. The value is NULL if the file is not
699 created. */
700 static FILE *output_description_file;
702 /* PHR description file name. */
703 static char *output_description_file_name;
705 /* Value of the following variable is node representing description
706 being processed. This is start point of IR. */
707 static struct description *description;
711 /* This page contains description of IR structure (nodes). */
713 enum decl_mode
715 dm_unit,
716 dm_bypass,
717 dm_automaton,
718 dm_excl,
719 dm_presence,
720 dm_absence,
721 dm_reserv,
722 dm_insn_reserv
725 /* This describes define_cpu_unit and define_query_cpu_unit (see file
726 rtl.def). */
727 struct unit_decl
729 char *name;
730 /* NULL if the automaton name is absent. */
731 char *automaton_name;
732 /* If the following value is not zero, the cpu unit reservation is
733 described in define_query_cpu_unit. */
734 char query_p;
736 /* The following fields are defined by checker. */
738 /* The following field value is nonzero if the unit is used in an
739 regexp. */
740 char unit_is_used;
742 /* The following field value is order number (0, 1, ...) of given
743 unit. */
744 int unit_num;
745 /* The following field value is corresponding declaration of
746 automaton which was given in description. If the field value is
747 NULL then automaton in the unit declaration was absent. */
748 struct automaton_decl *automaton_decl;
749 /* The following field value is maximal cycle number (1, ...) on
750 which given unit occurs in insns. Zero value means that given
751 unit is not used in insns. */
752 int max_occ_cycle_num;
753 /* The following field value is minimal cycle number (0, ...) on
754 which given unit occurs in insns. -1 value means that given
755 unit is not used in insns. */
756 int min_occ_cycle_num;
757 /* The following list contains units which conflict with given
758 unit. */
759 unit_set_el_t excl_list;
760 /* The following list contains patterns which are required to
761 reservation of given unit. */
762 pattern_set_el_t presence_list;
763 pattern_set_el_t final_presence_list;
764 /* The following list contains patterns which should be not present
765 in reservation for given unit. */
766 pattern_set_el_t absence_list;
767 pattern_set_el_t final_absence_list;
768 /* The following is used only when `query_p' has nonzero value.
769 This is query number for the unit. */
770 int query_num;
771 /* The following is the last cycle on which the unit was checked for
772 correct distributions of units to automata in a regexp. */
773 int last_distribution_check_cycle;
775 /* The following fields are defined by automaton generator. */
777 /* The following field value is number of the automaton to which
778 given unit belongs. */
779 int corresponding_automaton_num;
780 /* If the following value is not zero, the cpu unit is present in a
781 `exclusion_set' or in right part of a `presence_set',
782 `final_presence_set', `absence_set', and
783 `final_absence_set'define_query_cpu_unit. */
784 char in_set_p;
787 /* This describes define_bypass (see file rtl.def). */
788 struct bypass_decl
790 int latency;
791 char *out_insn_name;
792 char *in_insn_name;
793 char *bypass_guard_name;
795 /* The following fields are defined by checker. */
797 /* output and input insns of given bypass. */
798 struct insn_reserv_decl *out_insn_reserv;
799 struct insn_reserv_decl *in_insn_reserv;
800 /* The next bypass for given output insn. */
801 struct bypass_decl *next;
804 /* This describes define_automaton (see file rtl.def). */
805 struct automaton_decl
807 char *name;
809 /* The following fields are defined by automaton generator. */
811 /* The following field value is nonzero if the automaton is used in
812 an regexp definition. */
813 char automaton_is_used;
815 /* The following fields are defined by checker. */
817 /* The following field value is the corresponding automaton. This
818 field is not NULL only if the automaton is present in unit
819 declarations and the automatic partition on automata is not
820 used. */
821 automaton_t corresponding_automaton;
824 /* This describes exclusion relations: exclusion_set (see file
825 rtl.def). */
826 struct excl_rel_decl
828 int all_names_num;
829 int first_list_length;
830 char *names [1];
833 /* This describes unit relations: [final_]presence_set or
834 [final_]absence_set (see file rtl.def). */
835 struct unit_pattern_rel_decl
837 int final_p;
838 int names_num;
839 int patterns_num;
840 char **names;
841 char ***patterns;
844 /* This describes define_reservation (see file rtl.def). */
845 struct reserv_decl
847 char *name;
848 regexp_t regexp;
850 /* The following fields are defined by checker. */
852 /* The following field value is nonzero if the unit is used in an
853 regexp. */
854 char reserv_is_used;
855 /* The following field is used to check up cycle in expression
856 definition. */
857 int loop_pass_num;
860 /* This describes define_insn_reservation (see file rtl.def). */
861 struct insn_reserv_decl
863 rtx condexp;
864 int default_latency;
865 regexp_t regexp;
866 char *name;
868 /* The following fields are defined by checker. */
870 /* The following field value is order number (0, 1, ...) of given
871 insn. */
872 int insn_num;
873 /* The following field value is list of bypasses in which given insn
874 is output insn. */
875 struct bypass_decl *bypass_list;
877 /* The following fields are defined by automaton generator. */
879 /* The following field is the insn regexp transformed that
880 the regexp has not optional regexp, repetition regexp, and an
881 reservation name (i.e. reservation identifiers are changed by the
882 corresponding regexp) and all alternations are the topest level
883 of the regexp. The value can be NULL only if it is special
884 insn `cycle advancing'. */
885 regexp_t transformed_regexp;
886 /* The following field value is list of arcs marked given
887 insn. The field is used in transformation NDFA -> DFA. */
888 arc_t arcs_marked_by_insn;
889 /* The two following fields are used during minimization of a finite state
890 automaton. */
891 /* The field value is number of equivalence class of state into
892 which arc marked by given insn enters from a state (fixed during
893 an automaton minimization). */
894 int equiv_class_num;
895 /* The field value is state_alts of arc leaving a state (fixed
896 during an automaton minimization) and marked by given insn
897 enters. */
898 int state_alts;
899 /* The following member value is the list to automata which can be
900 changed by the insn issue. */
901 automata_list_el_t important_automata_list;
902 /* The following member is used to process insn once for output. */
903 int processed_p;
906 /* This contains a declaration mentioned above. */
907 struct decl
909 /* What node in the union? */
910 enum decl_mode mode;
911 pos_t pos;
912 union
914 struct unit_decl unit;
915 struct bypass_decl bypass;
916 struct automaton_decl automaton;
917 struct excl_rel_decl excl;
918 struct unit_pattern_rel_decl presence;
919 struct unit_pattern_rel_decl absence;
920 struct reserv_decl reserv;
921 struct insn_reserv_decl insn_reserv;
922 } decl;
925 /* The following structures represent parsed reservation strings. */
926 enum regexp_mode
928 rm_unit,
929 rm_reserv,
930 rm_nothing,
931 rm_sequence,
932 rm_repeat,
933 rm_allof,
934 rm_oneof
937 /* Cpu unit in reservation. */
938 struct unit_regexp
940 char *name;
941 unit_decl_t unit_decl;
944 /* Define_reservation in a reservation. */
945 struct reserv_regexp
947 char *name;
948 struct reserv_decl *reserv_decl;
951 /* Absence of reservation (represented by string `nothing'). */
952 struct nothing_regexp
954 /* This used to be empty but ISO C doesn't allow that. */
955 char unused;
958 /* Representation of reservations separated by ',' (see file
959 rtl.def). */
960 struct sequence_regexp
962 int regexps_num;
963 regexp_t regexps [1];
966 /* Representation of construction `repeat' (see file rtl.def). */
967 struct repeat_regexp
969 int repeat_num;
970 regexp_t regexp;
973 /* Representation of reservations separated by '+' (see file
974 rtl.def). */
975 struct allof_regexp
977 int regexps_num;
978 regexp_t regexps [1];
981 /* Representation of reservations separated by '|' (see file
982 rtl.def). */
983 struct oneof_regexp
985 int regexps_num;
986 regexp_t regexps [1];
989 /* Representation of a reservation string. */
990 struct regexp
992 /* What node in the union? */
993 enum regexp_mode mode;
994 pos_t pos;
995 union
997 struct unit_regexp unit;
998 struct reserv_regexp reserv;
999 struct nothing_regexp nothing;
1000 struct sequence_regexp sequence;
1001 struct repeat_regexp repeat;
1002 struct allof_regexp allof;
1003 struct oneof_regexp oneof;
1004 } regexp;
1007 /* Represents description of pipeline hazard description based on
1008 NDFA. */
1009 struct description
1011 int decls_num;
1013 /* The following fields are defined by checker. */
1015 /* The following fields values are correspondingly number of all
1016 units, query units, and insns in the description. */
1017 int units_num;
1018 int query_units_num;
1019 int insns_num;
1020 /* The following field value is max length (in cycles) of
1021 reservations of insns. The field value is defined only for
1022 correct programs. */
1023 int max_insn_reserv_cycles;
1025 /* The following fields are defined by automaton generator. */
1027 /* The following field value is the first automaton. */
1028 automaton_t first_automaton;
1030 /* The following field is created by pipeline hazard parser and
1031 contains all declarations. We allocate additional entry for
1032 special insn "cycle advancing" which is added by the automaton
1033 generator. */
1034 decl_t decls [1];
1038 /* The following nodes are created in automaton checker. */
1040 /* The following nodes represent exclusion set for cpu units. Each
1041 element is accessed through only one excl_list. */
1042 struct unit_set_el
1044 unit_decl_t unit_decl;
1045 unit_set_el_t next_unit_set_el;
1048 /* The following nodes represent presence or absence pattern for cpu
1049 units. Each element is accessed through only one presence_list or
1050 absence_list. */
1051 struct pattern_set_el
1053 /* The number of units in unit_decls. */
1054 int units_num;
1055 /* The units forming the pattern. */
1056 struct unit_decl **unit_decls;
1057 pattern_set_el_t next_pattern_set_el;
1061 /* The following nodes are created in automaton generator. */
1064 /* The following nodes represent presence or absence pattern for cpu
1065 units. Each element is accessed through only one element of
1066 unit_presence_set_table or unit_absence_set_table. */
1067 struct pattern_reserv
1069 reserv_sets_t reserv;
1070 pattern_reserv_t next_pattern_reserv;
1073 /* The following node type describes state automaton. The state may
1074 be deterministic or non-deterministic. Non-deterministic state has
1075 several component states which represent alternative cpu units
1076 reservations. The state also is used for describing a
1077 deterministic reservation of automaton insn. */
1078 struct state
1080 /* The following member value is nonzero if there is a transition by
1081 cycle advancing. */
1082 int new_cycle_p;
1083 /* The following field is list of processor unit reservations on
1084 each cycle. */
1085 reserv_sets_t reservs;
1086 /* The following field is unique number of given state between other
1087 states. */
1088 int unique_num;
1089 /* The following field value is automaton to which given state
1090 belongs. */
1091 automaton_t automaton;
1092 /* The following field value is the first arc output from given
1093 state. */
1094 arc_t first_out_arc;
1095 /* The following field is used to form NDFA. */
1096 char it_was_placed_in_stack_for_NDFA_forming;
1097 /* The following field is used to form DFA. */
1098 char it_was_placed_in_stack_for_DFA_forming;
1099 /* The following field is used to transform NDFA to DFA and DFA
1100 minimization. The field value is not NULL if the state is a
1101 compound state. In this case the value of field `unit_sets_list'
1102 is NULL. All states in the list are in the hash table. The list
1103 is formed through field `next_sorted_alt_state'. We should
1104 support only one level of nesting state. */
1105 alt_state_t component_states;
1106 /* The following field is used for passing graph of states. */
1107 int pass_num;
1108 /* The list of states belonging to one equivalence class is formed
1109 with the aid of the following field. */
1110 state_t next_equiv_class_state;
1111 /* The two following fields are used during minimization of a finite
1112 state automaton. */
1113 int equiv_class_num_1, equiv_class_num_2;
1114 /* The following field is used during minimization of a finite state
1115 automaton. The field value is state corresponding to equivalence
1116 class to which given state belongs. */
1117 state_t equiv_class_state;
1118 /* The following field value is the order number of given state.
1119 The states in final DFA is enumerated with the aid of the
1120 following field. */
1121 int order_state_num;
1122 /* This member is used for passing states for searching minimal
1123 delay time. */
1124 int state_pass_num;
1125 /* The following member is used to evaluate min issue delay of insn
1126 for a state. */
1127 int min_insn_issue_delay;
1128 /* The following member is used to evaluate max issue rate of the
1129 processor. The value of the member is maximal length of the path
1130 from given state no containing arcs marked by special insn `cycle
1131 advancing'. */
1132 int longest_path_length;
1135 /* The following macro is an initial value of member
1136 `longest_path_length' of a state. */
1137 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1139 /* Automaton arc. */
1140 struct arc
1142 /* The following field refers for the state into which given arc
1143 enters. */
1144 state_t to_state;
1145 /* The following field describes that the insn issue (with cycle
1146 advancing for special insn `cycle advancing' and without cycle
1147 advancing for others) makes transition from given state to
1148 another given state. */
1149 ainsn_t insn;
1150 /* The following field value is the next arc output from the same
1151 state. */
1152 arc_t next_out_arc;
1153 /* List of arcs marked given insn is formed with the following
1154 field. The field is used in transformation NDFA -> DFA. */
1155 arc_t next_arc_marked_by_insn;
1156 /* The following field is defined if NDFA_FLAG is zero. The member
1157 value is number of alternative reservations which can be used for
1158 transition for given state by given insn. */
1159 int state_alts;
1162 /* The following node type describes a deterministic alternative in
1163 non-deterministic state which characterizes cpu unit reservations
1164 of automaton insn or which is part of NDFA. */
1165 struct alt_state
1167 /* The following field is a deterministic state which characterizes
1168 unit reservations of the instruction. */
1169 state_t state;
1170 /* The following field refers to the next state which characterizes
1171 unit reservations of the instruction. */
1172 alt_state_t next_alt_state;
1173 /* The following field refers to the next state in sorted list. */
1174 alt_state_t next_sorted_alt_state;
1177 /* The following node type describes insn of automaton. They are
1178 labels of FA arcs. */
1179 struct ainsn
1181 /* The following field value is the corresponding insn declaration
1182 of description. */
1183 struct insn_reserv_decl *insn_reserv_decl;
1184 /* The following field value is the next insn declaration for an
1185 automaton. */
1186 ainsn_t next_ainsn;
1187 /* The following field is states which characterize automaton unit
1188 reservations of the instruction. The value can be NULL only if it
1189 is special insn `cycle advancing'. */
1190 alt_state_t alt_states;
1191 /* The following field is sorted list of states which characterize
1192 automaton unit reservations of the instruction. The value can be
1193 NULL only if it is special insn `cycle advancing'. */
1194 alt_state_t sorted_alt_states;
1195 /* The following field refers the next automaton insn with
1196 the same reservations. */
1197 ainsn_t next_same_reservs_insn;
1198 /* The following field is flag of the first automaton insn with the
1199 same reservations in the declaration list. Only arcs marked such
1200 insn is present in the automaton. This significantly decreases
1201 memory requirements especially when several automata are
1202 formed. */
1203 char first_insn_with_same_reservs;
1204 /* The following member has nonzero value if there is arc from state of
1205 the automaton marked by the ainsn. */
1206 char arc_exists_p;
1207 /* Cyclic list of insns of an equivalence class is formed with the
1208 aid of the following field. */
1209 ainsn_t next_equiv_class_insn;
1210 /* The following field value is nonzero if the insn declaration is
1211 the first insn declaration with given equivalence number. */
1212 char first_ainsn_with_given_equialence_num;
1213 /* The following field is number of class of equivalence of insns.
1214 It is necessary because many insns may be equivalent with the
1215 point of view of pipeline hazards. */
1216 int insn_equiv_class_num;
1217 /* The following member value is TRUE if there is an arc in the
1218 automaton marked by the insn into another state. In other
1219 words, the insn can change the state of the automaton. */
1220 int important_p;
1223 /* The following describes an automaton for PHR. */
1224 struct automaton
1226 /* The following field value is the list of insn declarations for
1227 given automaton. */
1228 ainsn_t ainsn_list;
1229 /* The following field value is the corresponding automaton
1230 declaration. This field is not NULL only if the automatic
1231 partition on automata is not used. */
1232 struct automaton_decl *corresponding_automaton_decl;
1233 /* The following field value is the next automaton. */
1234 automaton_t next_automaton;
1235 /* The following field is start state of FA. There are not unit
1236 reservations in the state. */
1237 state_t start_state;
1238 /* The following field value is number of equivalence classes of
1239 insns (see field `insn_equiv_class_num' in
1240 `insn_reserv_decl'). */
1241 int insn_equiv_classes_num;
1242 /* The following field value is number of states of final DFA. */
1243 int achieved_states_num;
1244 /* The following field value is the order number (0, 1, ...) of
1245 given automaton. */
1246 int automaton_order_num;
1247 /* The following fields contain statistics information about
1248 building automaton. */
1249 int NDFA_states_num, DFA_states_num;
1250 /* The following field value is defined only if minimization of DFA
1251 is used. */
1252 int minimal_DFA_states_num;
1253 int NDFA_arcs_num, DFA_arcs_num;
1254 /* The following field value is defined only if minimization of DFA
1255 is used. */
1256 int minimal_DFA_arcs_num;
1257 /* The following two members refer for two table state x ainsn ->
1258 int. */
1259 state_ainsn_table_t trans_table;
1260 state_ainsn_table_t state_alts_table;
1261 /* The following member value is maximal value of min issue delay
1262 for insns of the automaton. */
1263 int max_min_delay;
1264 /* Usually min issue delay is small and we can place several (2, 4,
1265 8) elements in one vector element. So the compression factor can
1266 be 1 (no compression), 2, 4, 8. */
1267 int min_issue_delay_table_compression_factor;
1270 /* The following is the element of the list of automata. */
1271 struct automata_list_el
1273 /* The automaton itself. */
1274 automaton_t automaton;
1275 /* The next automata set element. */
1276 automata_list_el_t next_automata_list_el;
1279 /* The following structure describes a table state X ainsn -> int(>= 0). */
1280 struct state_ainsn_table
1282 /* Automaton to which given table belongs. */
1283 automaton_t automaton;
1284 /* The following tree vectors for comb vector implementation of the
1285 table. */
1286 vla_hwint_t comb_vect;
1287 vla_hwint_t check_vect;
1288 vla_hwint_t base_vect;
1289 /* This is simple implementation of the table. */
1290 vla_hwint_t full_vect;
1291 /* Minimal and maximal values of the previous vectors. */
1292 int min_comb_vect_el_value, max_comb_vect_el_value;
1293 int min_base_vect_el_value, max_base_vect_el_value;
1296 /* Macros to access members of unions. Use only them for access to
1297 union members of declarations and regexps. */
1299 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1301 #define DECL_UNIT(d) __extension__ \
1302 (({ struct decl *const _decl = (d); \
1303 if (_decl->mode != dm_unit) \
1304 decl_mode_check_failed (_decl->mode, "dm_unit", \
1305 __FILE__, __LINE__, __FUNCTION__); \
1306 &(_decl)->decl.unit; }))
1308 #define DECL_BYPASS(d) __extension__ \
1309 (({ struct decl *const _decl = (d); \
1310 if (_decl->mode != dm_bypass) \
1311 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1312 __FILE__, __LINE__, __FUNCTION__); \
1313 &(_decl)->decl.bypass; }))
1315 #define DECL_AUTOMATON(d) __extension__ \
1316 (({ struct decl *const _decl = (d); \
1317 if (_decl->mode != dm_automaton) \
1318 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1319 __FILE__, __LINE__, __FUNCTION__); \
1320 &(_decl)->decl.automaton; }))
1322 #define DECL_EXCL(d) __extension__ \
1323 (({ struct decl *const _decl = (d); \
1324 if (_decl->mode != dm_excl) \
1325 decl_mode_check_failed (_decl->mode, "dm_excl", \
1326 __FILE__, __LINE__, __FUNCTION__); \
1327 &(_decl)->decl.excl; }))
1329 #define DECL_PRESENCE(d) __extension__ \
1330 (({ struct decl *const _decl = (d); \
1331 if (_decl->mode != dm_presence) \
1332 decl_mode_check_failed (_decl->mode, "dm_presence", \
1333 __FILE__, __LINE__, __FUNCTION__); \
1334 &(_decl)->decl.presence; }))
1336 #define DECL_ABSENCE(d) __extension__ \
1337 (({ struct decl *const _decl = (d); \
1338 if (_decl->mode != dm_absence) \
1339 decl_mode_check_failed (_decl->mode, "dm_absence", \
1340 __FILE__, __LINE__, __FUNCTION__); \
1341 &(_decl)->decl.absence; }))
1343 #define DECL_RESERV(d) __extension__ \
1344 (({ struct decl *const _decl = (d); \
1345 if (_decl->mode != dm_reserv) \
1346 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1347 __FILE__, __LINE__, __FUNCTION__); \
1348 &(_decl)->decl.reserv; }))
1350 #define DECL_INSN_RESERV(d) __extension__ \
1351 (({ struct decl *const _decl = (d); \
1352 if (_decl->mode != dm_insn_reserv) \
1353 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1354 __FILE__, __LINE__, __FUNCTION__); \
1355 &(_decl)->decl.insn_reserv; }))
1357 static const char *decl_name (enum decl_mode);
1358 static void decl_mode_check_failed (enum decl_mode, const char *,
1359 const char *, int, const char *);
1361 /* Return string representation of declaration mode MODE. */
1362 static const char *
1363 decl_name (enum decl_mode mode)
1365 static char str [100];
1367 if (mode == dm_unit)
1368 return "dm_unit";
1369 else if (mode == dm_bypass)
1370 return "dm_bypass";
1371 else if (mode == dm_automaton)
1372 return "dm_automaton";
1373 else if (mode == dm_excl)
1374 return "dm_excl";
1375 else if (mode == dm_presence)
1376 return "dm_presence";
1377 else if (mode == dm_absence)
1378 return "dm_absence";
1379 else if (mode == dm_reserv)
1380 return "dm_reserv";
1381 else if (mode == dm_insn_reserv)
1382 return "dm_insn_reserv";
1383 else
1384 sprintf (str, "unknown (%d)", (int) mode);
1385 return str;
1388 /* The function prints message about unexpected declaration and finish
1389 the program. */
1390 static void
1391 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
1392 const char *file, int line, const char *func)
1394 fprintf
1395 (stderr,
1396 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1397 file, line, func, expected_mode_str, decl_name (mode));
1398 exit (1);
1402 #define REGEXP_UNIT(r) __extension__ \
1403 (({ struct regexp *const _regexp = (r); \
1404 if (_regexp->mode != rm_unit) \
1405 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1406 __FILE__, __LINE__, __FUNCTION__); \
1407 &(_regexp)->regexp.unit; }))
1409 #define REGEXP_RESERV(r) __extension__ \
1410 (({ struct regexp *const _regexp = (r); \
1411 if (_regexp->mode != rm_reserv) \
1412 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1413 __FILE__, __LINE__, __FUNCTION__); \
1414 &(_regexp)->regexp.reserv; }))
1416 #define REGEXP_SEQUENCE(r) __extension__ \
1417 (({ struct regexp *const _regexp = (r); \
1418 if (_regexp->mode != rm_sequence) \
1419 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1420 __FILE__, __LINE__, __FUNCTION__); \
1421 &(_regexp)->regexp.sequence; }))
1423 #define REGEXP_REPEAT(r) __extension__ \
1424 (({ struct regexp *const _regexp = (r); \
1425 if (_regexp->mode != rm_repeat) \
1426 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1427 __FILE__, __LINE__, __FUNCTION__); \
1428 &(_regexp)->regexp.repeat; }))
1430 #define REGEXP_ALLOF(r) __extension__ \
1431 (({ struct regexp *const _regexp = (r); \
1432 if (_regexp->mode != rm_allof) \
1433 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1434 __FILE__, __LINE__, __FUNCTION__); \
1435 &(_regexp)->regexp.allof; }))
1437 #define REGEXP_ONEOF(r) __extension__ \
1438 (({ struct regexp *const _regexp = (r); \
1439 if (_regexp->mode != rm_oneof) \
1440 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1441 __FILE__, __LINE__, __FUNCTION__); \
1442 &(_regexp)->regexp.oneof; }))
1444 static const char *regexp_name (enum regexp_mode);
1445 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1446 const char *, int,
1447 const char *);
1450 /* Return string representation of regexp mode MODE. */
1451 static const char *
1452 regexp_name (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 (enum regexp_mode mode,
1479 const char *expected_mode_str,
1480 const char *file, int line, const char *func)
1482 fprintf
1483 (stderr,
1484 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1485 file, line, func, expected_mode_str, regexp_name (mode));
1486 exit (1);
1489 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1491 #define DECL_UNIT(d) (&(d)->decl.unit)
1492 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1493 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1494 #define DECL_EXCL(d) (&(d)->decl.excl)
1495 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1496 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1497 #define DECL_RESERV(d) (&(d)->decl.reserv)
1498 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1500 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1501 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1502 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1503 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1504 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1505 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1507 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1509 /* Create IR structure (node). */
1510 static void *
1511 create_node (size_t size)
1513 void *result;
1515 obstack_blank (&irp, size);
1516 result = obstack_base (&irp);
1517 obstack_finish (&irp);
1518 /* Default values of members are NULL and zero. */
1519 memset (result, 0, size);
1520 return result;
1523 /* Copy IR structure (node). */
1524 static void *
1525 copy_node (const void *from, size_t size)
1527 void *const result = create_node (size);
1528 memcpy (result, from, size);
1529 return result;
1532 /* The function checks that NAME does not contain quotes (`"'). */
1533 static char *
1534 check_name (char * name, pos_t pos ATTRIBUTE_UNUSED)
1536 const char *str;
1538 for (str = name; *str != '\0'; str++)
1539 if (*str == '\"')
1540 error ("Name `%s' contains quotes", name);
1541 return name;
1544 /* Pointers to all declarations during IR generation are stored in the
1545 following. */
1546 static vla_ptr_t decls;
1548 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1549 string containing the next separated element, taking parentheses
1550 into account if PAR_FLAG has nonzero value. Advance the pointer to
1551 after the string scanned, or the end-of-string. Return NULL if at
1552 end of string. */
1553 static char *
1554 next_sep_el (char **pstr, int sep, int par_flag)
1556 char *out_str;
1557 char *p;
1558 int pars_num;
1559 int n_spaces;
1561 /* Remove leading whitespaces. */
1562 while (ISSPACE ((int) **pstr))
1563 (*pstr)++;
1565 if (**pstr == '\0')
1566 return NULL;
1568 n_spaces = 0;
1569 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1571 if (par_flag && *p == '(')
1572 pars_num++;
1573 else if (par_flag && *p == ')')
1574 pars_num--;
1575 else if (pars_num == 0 && *p == sep)
1576 break;
1577 if (pars_num == 0 && ISSPACE ((int) *p))
1578 n_spaces++;
1579 else
1581 for (; n_spaces != 0; n_spaces--)
1582 obstack_1grow (&irp, p [-n_spaces]);
1583 obstack_1grow (&irp, *p);
1586 obstack_1grow (&irp, '\0');
1587 out_str = obstack_base (&irp);
1588 obstack_finish (&irp);
1590 *pstr = p;
1591 if (**pstr == sep)
1592 (*pstr)++;
1594 return out_str;
1597 /* Given a string and a separator, return the number of separated
1598 elements in it, taking parentheses into account if PAR_FLAG has
1599 nonzero value. Return 0 for the null string, -1 if parentheses is
1600 not balanced. */
1601 static int
1602 n_sep_els (char *s, int sep, int par_flag)
1604 int n;
1605 int pars_num;
1607 if (*s == '\0')
1608 return 0;
1610 for (pars_num = 0, n = 1; *s; s++)
1611 if (par_flag && *s == '(')
1612 pars_num++;
1613 else if (par_flag && *s == ')')
1614 pars_num--;
1615 else if (pars_num == 0 && *s == sep)
1616 n++;
1618 return (pars_num != 0 ? -1 : n);
1621 /* Given a string and a separator, return vector of strings which are
1622 elements in the string and number of elements through els_num.
1623 Take parentheses into account if PAREN_P has nonzero value. The
1624 function also inserts the end marker NULL at the end of vector.
1625 Return 0 for the null string, -1 if parentheses are not balanced. */
1626 static char **
1627 get_str_vect (char *str, int *els_num, int sep, int paren_p)
1629 int i;
1630 char **vect;
1631 char **pstr;
1633 *els_num = n_sep_els (str, sep, paren_p);
1634 if (*els_num <= 0)
1635 return NULL;
1636 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1637 vect = (char **) obstack_base (&irp);
1638 obstack_finish (&irp);
1639 pstr = &str;
1640 for (i = 0; i < *els_num; i++)
1641 vect [i] = next_sep_el (pstr, sep, paren_p);
1642 if (next_sep_el (pstr, sep, paren_p) != NULL)
1643 abort ();
1644 vect [i] = NULL;
1645 return vect;
1648 /* Process a DEFINE_CPU_UNIT.
1650 This gives information about a unit contained in CPU. We fill a
1651 struct unit_decl with information used later by `expand_automata'. */
1652 void
1653 gen_cpu_unit (rtx def)
1655 decl_t decl;
1656 char **str_cpu_units;
1657 int vect_length;
1658 int i;
1660 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1661 FALSE);
1662 if (str_cpu_units == NULL)
1663 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1664 for (i = 0; i < vect_length; i++)
1666 decl = create_node (sizeof (struct decl));
1667 decl->mode = dm_unit;
1668 decl->pos = 0;
1669 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1670 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1671 DECL_UNIT (decl)->query_p = 0;
1672 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1673 DECL_UNIT (decl)->in_set_p = 0;
1674 VLA_PTR_ADD (decls, decl);
1675 num_dfa_decls++;
1679 /* Process a DEFINE_QUERY_CPU_UNIT.
1681 This gives information about a unit contained in CPU. We fill a
1682 struct unit_decl with information used later by `expand_automata'. */
1683 void
1684 gen_query_cpu_unit (rtx def)
1686 decl_t decl;
1687 char **str_cpu_units;
1688 int vect_length;
1689 int i;
1691 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1692 FALSE);
1693 if (str_cpu_units == NULL)
1694 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1695 for (i = 0; i < vect_length; i++)
1697 decl = create_node (sizeof (struct decl));
1698 decl->mode = dm_unit;
1699 decl->pos = 0;
1700 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1701 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1702 DECL_UNIT (decl)->query_p = 1;
1703 VLA_PTR_ADD (decls, decl);
1704 num_dfa_decls++;
1708 /* Process a DEFINE_BYPASS.
1710 This gives information about a unit contained in the CPU. We fill
1711 in a struct bypass_decl with information used later by
1712 `expand_automata'. */
1713 void
1714 gen_bypass (rtx def)
1716 decl_t decl;
1717 char **out_insns;
1718 int out_length;
1719 char **in_insns;
1720 int in_length;
1721 int i, j;
1723 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', FALSE);
1724 if (out_insns == NULL)
1725 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1726 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', FALSE);
1727 if (in_insns == NULL)
1728 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1729 for (i = 0; i < out_length; i++)
1730 for (j = 0; j < in_length; j++)
1732 decl = create_node (sizeof (struct decl));
1733 decl->mode = dm_bypass;
1734 decl->pos = 0;
1735 DECL_BYPASS (decl)->latency = XINT (def, 0);
1736 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1737 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1738 DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
1739 VLA_PTR_ADD (decls, decl);
1740 num_dfa_decls++;
1744 /* Process an EXCLUSION_SET.
1746 This gives information about a cpu unit conflicts. We fill a
1747 struct excl_rel_decl (excl) with information used later by
1748 `expand_automata'. */
1749 void
1750 gen_excl_set (rtx def)
1752 decl_t decl;
1753 char **first_str_cpu_units;
1754 char **second_str_cpu_units;
1755 int first_vect_length;
1756 int length;
1757 int i;
1759 first_str_cpu_units
1760 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', FALSE);
1761 if (first_str_cpu_units == NULL)
1762 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1763 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1764 FALSE);
1765 if (second_str_cpu_units == NULL)
1766 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1767 length += first_vect_length;
1768 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1769 decl->mode = dm_excl;
1770 decl->pos = 0;
1771 DECL_EXCL (decl)->all_names_num = length;
1772 DECL_EXCL (decl)->first_list_length = first_vect_length;
1773 for (i = 0; i < length; i++)
1774 if (i < first_vect_length)
1775 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1776 else
1777 DECL_EXCL (decl)->names [i]
1778 = second_str_cpu_units [i - first_vect_length];
1779 VLA_PTR_ADD (decls, decl);
1780 num_dfa_decls++;
1783 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1784 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1786 This gives information about a cpu unit reservation requirements.
1787 We fill a struct unit_pattern_rel_decl with information used later
1788 by `expand_automata'. */
1789 static void
1790 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1792 decl_t decl;
1793 char **str_cpu_units;
1794 char ***str_patterns;
1795 int cpu_units_length;
1796 int length;
1797 int patterns_length;
1798 int i;
1800 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &cpu_units_length, ',',
1801 FALSE);
1802 if (str_cpu_units == NULL)
1803 fatal ((presence_p
1804 ? (final_p
1805 ? "invalid first string `%s' in final_presence_set"
1806 : "invalid first string `%s' in presence_set")
1807 : (final_p
1808 ? "invalid first string `%s' in final_absence_set"
1809 : "invalid first string `%s' in absence_set")),
1810 XSTR (def, 0));
1811 str_patterns = (char ***) get_str_vect ((char *) XSTR (def, 1),
1812 &patterns_length, ',', FALSE);
1813 if (str_patterns == NULL)
1814 fatal ((presence_p
1815 ? (final_p
1816 ? "invalid second string `%s' in final_presence_set"
1817 : "invalid second string `%s' in presence_set")
1818 : (final_p
1819 ? "invalid second string `%s' in final_absence_set"
1820 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1821 for (i = 0; i < patterns_length; i++)
1823 str_patterns [i] = get_str_vect ((char *) str_patterns [i], &length, ' ',
1824 FALSE);
1825 if (str_patterns [i] == NULL)
1826 abort ();
1828 decl = create_node (sizeof (struct decl));
1829 decl->pos = 0;
1830 if (presence_p)
1832 decl->mode = dm_presence;
1833 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1834 DECL_PRESENCE (decl)->names = str_cpu_units;
1835 DECL_PRESENCE (decl)->patterns = str_patterns;
1836 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1837 DECL_PRESENCE (decl)->final_p = final_p;
1839 else
1841 decl->mode = dm_absence;
1842 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1843 DECL_ABSENCE (decl)->names = str_cpu_units;
1844 DECL_ABSENCE (decl)->patterns = str_patterns;
1845 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1846 DECL_ABSENCE (decl)->final_p = final_p;
1848 VLA_PTR_ADD (decls, decl);
1849 num_dfa_decls++;
1852 /* Process a PRESENCE_SET.
1854 This gives information about a cpu unit reservation requirements.
1855 We fill a struct unit_pattern_rel_decl (presence) with information
1856 used later by `expand_automata'. */
1857 void
1858 gen_presence_set (rtx def)
1860 gen_presence_absence_set (def, TRUE, FALSE);
1863 /* Process a FINAL_PRESENCE_SET.
1865 This gives information about a cpu unit reservation requirements.
1866 We fill a struct unit_pattern_rel_decl (presence) with information
1867 used later by `expand_automata'. */
1868 void
1869 gen_final_presence_set (rtx def)
1871 gen_presence_absence_set (def, TRUE, TRUE);
1874 /* Process an ABSENCE_SET.
1876 This gives information about a cpu unit reservation requirements.
1877 We fill a struct unit_pattern_rel_decl (absence) with information
1878 used later by `expand_automata'. */
1879 void
1880 gen_absence_set (rtx def)
1882 gen_presence_absence_set (def, FALSE, FALSE);
1885 /* Process a FINAL_ABSENCE_SET.
1887 This gives information about a cpu unit reservation requirements.
1888 We fill a struct unit_pattern_rel_decl (absence) with information
1889 used later by `expand_automata'. */
1890 void
1891 gen_final_absence_set (rtx def)
1893 gen_presence_absence_set (def, FALSE, TRUE);
1896 /* Process a DEFINE_AUTOMATON.
1898 This gives information about a finite state automaton used for
1899 recognizing pipeline hazards. We fill a struct automaton_decl
1900 with information used later by `expand_automata'. */
1901 void
1902 gen_automaton (rtx def)
1904 decl_t decl;
1905 char **str_automata;
1906 int vect_length;
1907 int i;
1909 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1910 FALSE);
1911 if (str_automata == NULL)
1912 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1913 for (i = 0; i < vect_length; i++)
1915 decl = create_node (sizeof (struct decl));
1916 decl->mode = dm_automaton;
1917 decl->pos = 0;
1918 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1919 VLA_PTR_ADD (decls, decl);
1920 num_dfa_decls++;
1924 /* Process an AUTOMATA_OPTION.
1926 This gives information how to generate finite state automaton used
1927 for recognizing pipeline hazards. */
1928 void
1929 gen_automata_option (rtx def)
1931 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1932 no_minimization_flag = 1;
1933 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1934 time_flag = 1;
1935 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1936 v_flag = 1;
1937 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1938 w_flag = 1;
1939 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1940 ndfa_flag = 1;
1941 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1942 progress_flag = 1;
1943 else
1944 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1947 /* Name in reservation to denote absence reservation. */
1948 #define NOTHING_NAME "nothing"
1950 /* The following string contains original reservation string being
1951 parsed. */
1952 static char *reserv_str;
1954 /* Parse an element in STR. */
1955 static regexp_t
1956 gen_regexp_el (char *str)
1958 regexp_t regexp;
1959 int len;
1961 if (*str == '(')
1963 len = strlen (str);
1964 if (str [len - 1] != ')')
1965 fatal ("garbage after ) in reservation `%s'", reserv_str);
1966 str [len - 1] = '\0';
1967 regexp = gen_regexp_sequence (str + 1);
1969 else if (strcmp (str, NOTHING_NAME) == 0)
1971 regexp = create_node (sizeof (struct decl));
1972 regexp->mode = rm_nothing;
1974 else
1976 regexp = create_node (sizeof (struct decl));
1977 regexp->mode = rm_unit;
1978 REGEXP_UNIT (regexp)->name = str;
1980 return regexp;
1983 /* Parse construction `repeat' in STR. */
1984 static regexp_t
1985 gen_regexp_repeat (char *str)
1987 regexp_t regexp;
1988 regexp_t repeat;
1989 char **repeat_vect;
1990 int els_num;
1991 int i;
1993 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1994 if (repeat_vect == NULL)
1995 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1996 if (els_num > 1)
1998 regexp = gen_regexp_el (repeat_vect [0]);
1999 for (i = 1; i < els_num; i++)
2001 repeat = create_node (sizeof (struct regexp));
2002 repeat->mode = rm_repeat;
2003 REGEXP_REPEAT (repeat)->regexp = regexp;
2004 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
2005 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
2006 fatal ("repetition `%s' <= 1 in reservation `%s'",
2007 str, reserv_str);
2008 regexp = repeat;
2010 return regexp;
2012 else
2013 return gen_regexp_el (str);
2016 /* Parse reservation STR which possibly contains separator '+'. */
2017 static regexp_t
2018 gen_regexp_allof (char *str)
2020 regexp_t allof;
2021 char **allof_vect;
2022 int els_num;
2023 int i;
2025 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
2026 if (allof_vect == NULL)
2027 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2028 if (els_num > 1)
2030 allof = create_node (sizeof (struct regexp)
2031 + sizeof (regexp_t) * (els_num - 1));
2032 allof->mode = rm_allof;
2033 REGEXP_ALLOF (allof)->regexps_num = els_num;
2034 for (i = 0; i < els_num; i++)
2035 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
2036 return allof;
2038 else
2039 return gen_regexp_repeat (str);
2042 /* Parse reservation STR which possibly contains separator '|'. */
2043 static regexp_t
2044 gen_regexp_oneof (char *str)
2046 regexp_t oneof;
2047 char **oneof_vect;
2048 int els_num;
2049 int i;
2051 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
2052 if (oneof_vect == NULL)
2053 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2054 if (els_num > 1)
2056 oneof = create_node (sizeof (struct regexp)
2057 + sizeof (regexp_t) * (els_num - 1));
2058 oneof->mode = rm_oneof;
2059 REGEXP_ONEOF (oneof)->regexps_num = els_num;
2060 for (i = 0; i < els_num; i++)
2061 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
2062 return oneof;
2064 else
2065 return gen_regexp_allof (str);
2068 /* Parse reservation STR which possibly contains separator ','. */
2069 static regexp_t
2070 gen_regexp_sequence (char *str)
2072 regexp_t sequence;
2073 char **sequence_vect;
2074 int els_num;
2075 int i;
2077 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
2078 if (els_num > 1)
2080 sequence = create_node (sizeof (struct regexp)
2081 + sizeof (regexp_t) * (els_num - 1));
2082 sequence->mode = rm_sequence;
2083 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2084 for (i = 0; i < els_num; i++)
2085 REGEXP_SEQUENCE (sequence)->regexps [i]
2086 = gen_regexp_oneof (sequence_vect [i]);
2087 return sequence;
2089 else
2090 return gen_regexp_oneof (str);
2093 /* Parse construction reservation STR. */
2094 static regexp_t
2095 gen_regexp (char *str)
2097 reserv_str = str;
2098 return gen_regexp_sequence (str);;
2101 /* Process a DEFINE_RESERVATION.
2103 This gives information about a reservation of cpu units. We fill
2104 in a struct reserv_decl with information used later by
2105 `expand_automata'. */
2106 void
2107 gen_reserv (rtx def)
2109 decl_t decl;
2111 decl = create_node (sizeof (struct decl));
2112 decl->mode = dm_reserv;
2113 decl->pos = 0;
2114 DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2115 DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2116 VLA_PTR_ADD (decls, decl);
2117 num_dfa_decls++;
2120 /* Process a DEFINE_INSN_RESERVATION.
2122 This gives information about the reservation of cpu units by an
2123 insn. We fill a struct insn_reserv_decl with information used
2124 later by `expand_automata'. */
2125 void
2126 gen_insn_reserv (rtx def)
2128 decl_t decl;
2130 decl = create_node (sizeof (struct decl));
2131 decl->mode = dm_insn_reserv;
2132 decl->pos = 0;
2133 DECL_INSN_RESERV (decl)->name
2134 = check_name ((char *) XSTR (def, 0), decl->pos);
2135 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2136 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2137 DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2138 VLA_PTR_ADD (decls, decl);
2139 num_dfa_decls++;
2144 /* The function evaluates hash value (0..UINT_MAX) of string. */
2145 static unsigned
2146 string_hash (const char *string)
2148 unsigned result, i;
2150 for (result = i = 0;*string++ != '\0'; i++)
2151 result += ((unsigned char) *string << (i % CHAR_BIT));
2152 return result;
2157 /* This page contains abstract data `table of automaton declarations'.
2158 Elements of the table is nodes representing automaton declarations.
2159 Key of the table elements is name of given automaton. Remember
2160 that automaton names have own space. */
2162 /* The function evaluates hash value of an automaton declaration. The
2163 function is used by abstract data `hashtab'. The function returns
2164 hash value (0..UINT_MAX) of given automaton declaration. */
2165 static hashval_t
2166 automaton_decl_hash (const void *automaton_decl)
2168 const decl_t decl = (decl_t) automaton_decl;
2170 if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
2171 abort ();
2172 return string_hash (DECL_AUTOMATON (decl)->name);
2175 /* The function tests automaton declarations on equality of their
2176 keys. The function is used by abstract data `hashtab'. The
2177 function returns 1 if the declarations have the same key, 0
2178 otherwise. */
2179 static int
2180 automaton_decl_eq_p (const void* automaton_decl_1,
2181 const void* automaton_decl_2)
2183 const decl_t decl1 = (decl_t) automaton_decl_1;
2184 const decl_t decl2 = (decl_t) automaton_decl_2;
2186 if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
2187 || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
2188 abort ();
2189 return strcmp (DECL_AUTOMATON (decl1)->name,
2190 DECL_AUTOMATON (decl2)->name) == 0;
2193 /* The automaton declaration table itself is represented by the
2194 following variable. */
2195 static htab_t automaton_decl_table;
2197 /* The function inserts automaton declaration into the table. The
2198 function does nothing if an automaton declaration with the same key
2199 exists already in the table. The function returns automaton
2200 declaration node in the table with the same key as given automaton
2201 declaration node. */
2202 static decl_t
2203 insert_automaton_decl (decl_t automaton_decl)
2205 void **entry_ptr;
2207 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
2208 if (*entry_ptr == NULL)
2209 *entry_ptr = (void *) automaton_decl;
2210 return (decl_t) *entry_ptr;
2213 /* The following variable value is node representing automaton
2214 declaration. The node used for searching automaton declaration
2215 with given name. */
2216 static struct decl work_automaton_decl;
2218 /* The function searches for automaton declaration in the table with
2219 the same key as node representing name of the automaton
2220 declaration. The function returns node found in the table, NULL if
2221 such node does not exist in the table. */
2222 static decl_t
2223 find_automaton_decl (char *name)
2225 void *entry;
2227 work_automaton_decl.mode = dm_automaton;
2228 DECL_AUTOMATON (&work_automaton_decl)->name = name;
2229 entry = htab_find (automaton_decl_table, &work_automaton_decl);
2230 return (decl_t) entry;
2233 /* The function creates empty automaton declaration table and node
2234 representing automaton declaration and used for searching automaton
2235 declaration with given name. The function must be called only once
2236 before any work with the automaton declaration table. */
2237 static void
2238 initiate_automaton_decl_table (void)
2240 work_automaton_decl.mode = dm_automaton;
2241 automaton_decl_table = htab_create (10, automaton_decl_hash,
2242 automaton_decl_eq_p, (htab_del) 0);
2245 /* The function deletes the automaton declaration table. Only call of
2246 function `initiate_automaton_decl_table' is possible immediately
2247 after this function call. */
2248 static void
2249 finish_automaton_decl_table (void)
2251 htab_delete (automaton_decl_table);
2256 /* This page contains abstract data `table of insn declarations'.
2257 Elements of the table is nodes representing insn declarations. Key
2258 of the table elements is name of given insn (in corresponding
2259 define_insn_reservation). Remember that insn names have own
2260 space. */
2262 /* The function evaluates hash value of an insn declaration. The
2263 function is used by abstract data `hashtab'. The function returns
2264 hash value (0..UINT_MAX) of given insn declaration. */
2265 static hashval_t
2266 insn_decl_hash (const void *insn_decl)
2268 const decl_t decl = (decl_t) insn_decl;
2270 if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
2271 abort ();
2272 return string_hash (DECL_INSN_RESERV (decl)->name);
2275 /* The function tests insn declarations on equality of their keys.
2276 The function is used by abstract data `hashtab'. The function
2277 returns 1 if declarations have the same key, 0 otherwise. */
2278 static int
2279 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
2281 const decl_t decl1 = (decl_t) insn_decl_1;
2282 const decl_t decl2 = (decl_t) insn_decl_2;
2284 if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
2285 || decl2->mode != dm_insn_reserv
2286 || DECL_INSN_RESERV (decl2)->name == NULL)
2287 abort ();
2288 return strcmp (DECL_INSN_RESERV (decl1)->name,
2289 DECL_INSN_RESERV (decl2)->name) == 0;
2292 /* The insn declaration table itself is represented by the following
2293 variable. The table does not contain insn reservation
2294 declarations. */
2295 static htab_t insn_decl_table;
2297 /* The function inserts insn declaration into the table. The function
2298 does nothing if an insn declaration with the same key exists
2299 already in the table. The function returns insn declaration node
2300 in the table with the same key as given insn declaration node. */
2301 static decl_t
2302 insert_insn_decl (decl_t insn_decl)
2304 void **entry_ptr;
2306 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2307 if (*entry_ptr == NULL)
2308 *entry_ptr = (void *) insn_decl;
2309 return (decl_t) *entry_ptr;
2312 /* The following variable value is node representing insn reservation
2313 declaration. The node used for searching insn reservation
2314 declaration with given name. */
2315 static struct decl work_insn_decl;
2317 /* The function searches for insn reservation declaration in the table
2318 with the same key as node representing name of the insn reservation
2319 declaration. The function returns node found in the table, NULL if
2320 such node does not exist in the table. */
2321 static decl_t
2322 find_insn_decl (char *name)
2324 void *entry;
2326 work_insn_decl.mode = dm_insn_reserv;
2327 DECL_INSN_RESERV (&work_insn_decl)->name = name;
2328 entry = htab_find (insn_decl_table, &work_insn_decl);
2329 return (decl_t) entry;
2332 /* The function creates empty insn declaration table and node
2333 representing insn declaration and used for searching insn
2334 declaration with given name. The function must be called only once
2335 before any work with the insn declaration table. */
2336 static void
2337 initiate_insn_decl_table (void)
2339 work_insn_decl.mode = dm_insn_reserv;
2340 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2341 (htab_del) 0);
2344 /* The function deletes the insn declaration table. Only call of
2345 function `initiate_insn_decl_table' is possible immediately after
2346 this function call. */
2347 static void
2348 finish_insn_decl_table (void)
2350 htab_delete (insn_decl_table);
2355 /* This page contains abstract data `table of declarations'. Elements
2356 of the table is nodes representing declarations (of units and
2357 reservations). Key of the table elements is names of given
2358 declarations. */
2360 /* The function evaluates hash value of a declaration. The function
2361 is used by abstract data `hashtab'. The function returns hash
2362 value (0..UINT_MAX) of given declaration. */
2363 static hashval_t
2364 decl_hash (const void *decl)
2366 const decl_t d = (const decl_t) decl;
2368 if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
2369 && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
2370 abort ();
2371 return string_hash (d->mode == dm_unit
2372 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
2375 /* The function tests declarations on equality of their keys. The
2376 function is used by abstract data `hashtab'. The function
2377 returns 1 if the declarations have the same key, 0 otherwise. */
2378 static int
2379 decl_eq_p (const void *decl_1, const void *decl_2)
2381 const decl_t d1 = (const decl_t) decl_1;
2382 const decl_t d2 = (const decl_t) decl_2;
2384 if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
2385 && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
2386 || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
2387 && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
2388 abort ();
2389 return strcmp ((d1->mode == dm_unit
2390 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
2391 (d2->mode == dm_unit
2392 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2395 /* The declaration table itself is represented by the following
2396 variable. */
2397 static htab_t decl_table;
2399 /* The function inserts declaration into the table. The function does
2400 nothing if a declaration with the same key exists already in the
2401 table. The function returns declaration node in the table with the
2402 same key as given declaration node. */
2404 static decl_t
2405 insert_decl (decl_t decl)
2407 void **entry_ptr;
2409 entry_ptr = htab_find_slot (decl_table, decl, 1);
2410 if (*entry_ptr == NULL)
2411 *entry_ptr = (void *) decl;
2412 return (decl_t) *entry_ptr;
2415 /* The following variable value is node representing declaration. The
2416 node used for searching declaration with given name. */
2417 static struct decl work_decl;
2419 /* The function searches for declaration in the table with the same
2420 key as node representing name of the declaration. The function
2421 returns node found in the table, NULL if such node does not exist
2422 in the table. */
2423 static decl_t
2424 find_decl (char *name)
2426 void *entry;
2428 work_decl.mode = dm_unit;
2429 DECL_UNIT (&work_decl)->name = name;
2430 entry = htab_find (decl_table, &work_decl);
2431 return (decl_t) entry;
2434 /* The function creates empty declaration table and node representing
2435 declaration and used for searching declaration with given name.
2436 The function must be called only once before any work with the
2437 declaration table. */
2438 static void
2439 initiate_decl_table (void)
2441 work_decl.mode = dm_unit;
2442 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2445 /* The function deletes the declaration table. Only call of function
2446 `initiate_declaration_table' is possible immediately after this
2447 function call. */
2448 static void
2449 finish_decl_table (void)
2451 htab_delete (decl_table);
2456 /* This page contains checker of pipeline hazard description. */
2458 /* Checking NAMES in an exclusion clause vector and returning formed
2459 unit_set_el_list. */
2460 static unit_set_el_t
2461 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2463 unit_set_el_t el_list;
2464 unit_set_el_t last_el;
2465 unit_set_el_t new_el;
2466 decl_t decl_in_table;
2467 int i;
2469 el_list = NULL;
2470 last_el = NULL;
2471 for (i = 0; i < num; i++)
2473 decl_in_table = find_decl (names [i]);
2474 if (decl_in_table == NULL)
2475 error ("unit `%s' in exclusion is not declared", names [i]);
2476 else if (decl_in_table->mode != dm_unit)
2477 error ("`%s' in exclusion is not unit", names [i]);
2478 else
2480 new_el = create_node (sizeof (struct unit_set_el));
2481 new_el->unit_decl = DECL_UNIT (decl_in_table);
2482 new_el->next_unit_set_el = NULL;
2483 if (last_el == NULL)
2484 el_list = last_el = new_el;
2485 else
2487 last_el->next_unit_set_el = new_el;
2488 last_el = last_el->next_unit_set_el;
2492 return el_list;
2495 /* The function adds each element from SOURCE_LIST to the exclusion
2496 list of the each element from DEST_LIST. Checking situation "unit
2497 excludes itself". */
2498 static void
2499 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2500 pos_t excl_pos ATTRIBUTE_UNUSED)
2502 unit_set_el_t dst;
2503 unit_set_el_t src;
2504 unit_set_el_t curr_el;
2505 unit_set_el_t prev_el;
2506 unit_set_el_t copy;
2508 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2509 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2511 if (dst->unit_decl == src->unit_decl)
2513 error ("unit `%s' excludes itself", src->unit_decl->name);
2514 continue;
2516 if (dst->unit_decl->automaton_name != NULL
2517 && src->unit_decl->automaton_name != NULL
2518 && strcmp (dst->unit_decl->automaton_name,
2519 src->unit_decl->automaton_name) != 0)
2521 error ("units `%s' and `%s' in exclusion set belong to different automata",
2522 src->unit_decl->name, dst->unit_decl->name);
2523 continue;
2525 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2526 curr_el != NULL;
2527 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2528 if (curr_el->unit_decl == src->unit_decl)
2529 break;
2530 if (curr_el == NULL)
2532 /* Element not found - insert. */
2533 copy = copy_node (src, sizeof (*src));
2534 copy->next_unit_set_el = NULL;
2535 if (prev_el == NULL)
2536 dst->unit_decl->excl_list = copy;
2537 else
2538 prev_el->next_unit_set_el = copy;
2543 /* Checking NAMES in presence/absence clause and returning the
2544 formed unit_set_el_list. The function is called only after
2545 processing all exclusion sets. */
2546 static unit_set_el_t
2547 process_presence_absence_names (char **names, int num,
2548 pos_t req_pos ATTRIBUTE_UNUSED,
2549 int presence_p, int final_p)
2551 unit_set_el_t el_list;
2552 unit_set_el_t last_el;
2553 unit_set_el_t new_el;
2554 decl_t decl_in_table;
2555 int i;
2557 el_list = NULL;
2558 last_el = NULL;
2559 for (i = 0; i < num; i++)
2561 decl_in_table = find_decl (names [i]);
2562 if (decl_in_table == NULL)
2563 error ((presence_p
2564 ? (final_p
2565 ? "unit `%s' in final presence set is not declared"
2566 : "unit `%s' in presence set is not declared")
2567 : (final_p
2568 ? "unit `%s' in final absence set is not declared"
2569 : "unit `%s' in absence set is not declared")), names [i]);
2570 else if (decl_in_table->mode != dm_unit)
2571 error ((presence_p
2572 ? (final_p
2573 ? "`%s' in final presence set is not unit"
2574 : "`%s' in presence set is not unit")
2575 : (final_p
2576 ? "`%s' in final absence set is not unit"
2577 : "`%s' in absence set is not unit")), names [i]);
2578 else
2580 new_el = create_node (sizeof (struct unit_set_el));
2581 new_el->unit_decl = DECL_UNIT (decl_in_table);
2582 new_el->next_unit_set_el = NULL;
2583 if (last_el == NULL)
2584 el_list = last_el = new_el;
2585 else
2587 last_el->next_unit_set_el = new_el;
2588 last_el = last_el->next_unit_set_el;
2592 return el_list;
2595 /* Checking NAMES in patterns of a presence/absence clause and
2596 returning the formed pattern_set_el_list. The function is called
2597 only after processing all exclusion sets. */
2598 static pattern_set_el_t
2599 process_presence_absence_patterns (char ***patterns, int num,
2600 pos_t req_pos ATTRIBUTE_UNUSED,
2601 int presence_p, int final_p)
2603 pattern_set_el_t el_list;
2604 pattern_set_el_t last_el;
2605 pattern_set_el_t new_el;
2606 decl_t decl_in_table;
2607 int i, j;
2609 el_list = NULL;
2610 last_el = NULL;
2611 for (i = 0; i < num; i++)
2613 for (j = 0; patterns [i] [j] != NULL; j++)
2615 new_el = create_node (sizeof (struct pattern_set_el)
2616 + sizeof (struct unit_decl *) * j);
2617 new_el->unit_decls
2618 = (struct unit_decl **) ((char *) new_el
2619 + sizeof (struct pattern_set_el));
2620 new_el->next_pattern_set_el = NULL;
2621 if (last_el == NULL)
2622 el_list = last_el = new_el;
2623 else
2625 last_el->next_pattern_set_el = new_el;
2626 last_el = last_el->next_pattern_set_el;
2628 new_el->units_num = 0;
2629 for (j = 0; patterns [i] [j] != NULL; j++)
2631 decl_in_table = find_decl (patterns [i] [j]);
2632 if (decl_in_table == NULL)
2633 error ((presence_p
2634 ? (final_p
2635 ? "unit `%s' in final presence set is not declared"
2636 : "unit `%s' in presence set is not declared")
2637 : (final_p
2638 ? "unit `%s' in final absence set is not declared"
2639 : "unit `%s' in absence set is not declared")),
2640 patterns [i] [j]);
2641 else if (decl_in_table->mode != dm_unit)
2642 error ((presence_p
2643 ? (final_p
2644 ? "`%s' in final presence set is not unit"
2645 : "`%s' in presence set is not unit")
2646 : (final_p
2647 ? "`%s' in final absence set is not unit"
2648 : "`%s' in absence set is not unit")),
2649 patterns [i] [j]);
2650 else
2652 new_el->unit_decls [new_el->units_num]
2653 = DECL_UNIT (decl_in_table);
2654 new_el->units_num++;
2658 return el_list;
2661 /* The function adds each element from PATTERN_LIST to presence (if
2662 PRESENCE_P) or absence list of the each element from DEST_LIST.
2663 Checking situations "unit requires own absence", and "unit excludes
2664 and requires presence of ...", "unit requires absence and presence
2665 of ...", "units in (final) presence set belong to different
2666 automata", and "units in (final) absence set belong to different
2667 automata". Remember that we process absence sets only after all
2668 presence sets. */
2669 static void
2670 add_presence_absence (unit_set_el_t dest_list,
2671 pattern_set_el_t pattern_list,
2672 pos_t req_pos ATTRIBUTE_UNUSED,
2673 int presence_p, int final_p)
2675 unit_set_el_t dst;
2676 pattern_set_el_t pat;
2677 struct unit_decl *unit;
2678 unit_set_el_t curr_excl_el;
2679 pattern_set_el_t curr_pat_el;
2680 pattern_set_el_t prev_el;
2681 pattern_set_el_t copy;
2682 int i;
2683 int no_error_flag;
2685 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2686 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2688 for (i = 0; i < pat->units_num; i++)
2690 unit = pat->unit_decls [i];
2691 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2693 error ("unit `%s' requires own absence", unit->name);
2694 continue;
2696 if (dst->unit_decl->automaton_name != NULL
2697 && unit->automaton_name != NULL
2698 && strcmp (dst->unit_decl->automaton_name,
2699 unit->automaton_name) != 0)
2701 error ((presence_p
2702 ? (final_p
2703 ? "units `%s' and `%s' in final presence set belong to different automata"
2704 : "units `%s' and `%s' in presence set belong to different automata")
2705 : (final_p
2706 ? "units `%s' and `%s' in final absence set belong to different automata"
2707 : "units `%s' and `%s' in absence set belong to different automata")),
2708 unit->name, dst->unit_decl->name);
2709 continue;
2711 no_error_flag = 1;
2712 if (presence_p)
2713 for (curr_excl_el = dst->unit_decl->excl_list;
2714 curr_excl_el != NULL;
2715 curr_excl_el = curr_excl_el->next_unit_set_el)
2717 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2719 if (!w_flag)
2721 error ("unit `%s' excludes and requires presence of `%s'",
2722 dst->unit_decl->name, unit->name);
2723 no_error_flag = 0;
2725 else
2726 warning
2727 ("unit `%s' excludes and requires presence of `%s'",
2728 dst->unit_decl->name, unit->name);
2731 else if (pat->units_num == 1)
2732 for (curr_pat_el = dst->unit_decl->presence_list;
2733 curr_pat_el != NULL;
2734 curr_pat_el = curr_pat_el->next_pattern_set_el)
2735 if (curr_pat_el->units_num == 1
2736 && unit == curr_pat_el->unit_decls [0])
2738 if (!w_flag)
2740 error
2741 ("unit `%s' requires absence and presence of `%s'",
2742 dst->unit_decl->name, unit->name);
2743 no_error_flag = 0;
2745 else
2746 warning
2747 ("unit `%s' requires absence and presence of `%s'",
2748 dst->unit_decl->name, unit->name);
2750 if (no_error_flag)
2752 for (prev_el = (presence_p
2753 ? (final_p
2754 ? dst->unit_decl->final_presence_list
2755 : dst->unit_decl->final_presence_list)
2756 : (final_p
2757 ? dst->unit_decl->final_absence_list
2758 : dst->unit_decl->absence_list));
2759 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2760 prev_el = prev_el->next_pattern_set_el)
2762 copy = copy_node (pat, sizeof (*pat));
2763 copy->next_pattern_set_el = NULL;
2764 if (prev_el == NULL)
2766 if (presence_p)
2768 if (final_p)
2769 dst->unit_decl->final_presence_list = copy;
2770 else
2771 dst->unit_decl->presence_list = copy;
2773 else if (final_p)
2774 dst->unit_decl->final_absence_list = copy;
2775 else
2776 dst->unit_decl->absence_list = copy;
2778 else
2779 prev_el->next_pattern_set_el = copy;
2786 /* The function searches for bypass with given IN_INSN_RESERV in given
2787 BYPASS_LIST. */
2788 static struct bypass_decl *
2789 find_bypass (struct bypass_decl *bypass_list,
2790 struct insn_reserv_decl *in_insn_reserv)
2792 struct bypass_decl *bypass;
2794 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2795 if (bypass->in_insn_reserv == in_insn_reserv)
2796 break;
2797 return bypass;
2800 /* The function processes pipeline description declarations, checks
2801 their correctness, and forms exclusion/presence/absence sets. */
2802 static void
2803 process_decls (void)
2805 decl_t decl;
2806 decl_t automaton_decl;
2807 decl_t decl_in_table;
2808 decl_t out_insn_reserv;
2809 decl_t in_insn_reserv;
2810 struct bypass_decl *bypass;
2811 int automaton_presence;
2812 int i;
2814 /* Checking repeated automata declarations. */
2815 automaton_presence = 0;
2816 for (i = 0; i < description->decls_num; i++)
2818 decl = description->decls [i];
2819 if (decl->mode == dm_automaton)
2821 automaton_presence = 1;
2822 decl_in_table = insert_automaton_decl (decl);
2823 if (decl_in_table != decl)
2825 if (!w_flag)
2826 error ("repeated declaration of automaton `%s'",
2827 DECL_AUTOMATON (decl)->name);
2828 else
2829 warning ("repeated declaration of automaton `%s'",
2830 DECL_AUTOMATON (decl)->name);
2834 /* Checking undeclared automata, repeated declarations (except for
2835 automata) and correctness of their attributes (insn latency times
2836 etc.). */
2837 for (i = 0; i < description->decls_num; i++)
2839 decl = description->decls [i];
2840 if (decl->mode == dm_insn_reserv)
2842 DECL_INSN_RESERV (decl)->condexp
2843 = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
2844 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2845 error ("define_insn_reservation `%s' has negative latency time",
2846 DECL_INSN_RESERV (decl)->name);
2847 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2848 description->insns_num++;
2849 decl_in_table = insert_insn_decl (decl);
2850 if (decl_in_table != decl)
2851 error ("`%s' is already used as insn reservation name",
2852 DECL_INSN_RESERV (decl)->name);
2854 else if (decl->mode == dm_bypass)
2856 if (DECL_BYPASS (decl)->latency < 0)
2857 error ("define_bypass `%s - %s' has negative latency time",
2858 DECL_BYPASS (decl)->out_insn_name,
2859 DECL_BYPASS (decl)->in_insn_name);
2861 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2863 if (decl->mode == dm_unit)
2865 DECL_UNIT (decl)->automaton_decl = NULL;
2866 if (DECL_UNIT (decl)->automaton_name != NULL)
2868 automaton_decl
2869 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2870 if (automaton_decl == NULL)
2871 error ("automaton `%s' is not declared",
2872 DECL_UNIT (decl)->automaton_name);
2873 else
2875 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2876 DECL_UNIT (decl)->automaton_decl
2877 = DECL_AUTOMATON (automaton_decl);
2880 else if (automaton_presence)
2881 error ("define_unit `%s' without automaton when one defined",
2882 DECL_UNIT (decl)->name);
2883 DECL_UNIT (decl)->unit_num = description->units_num;
2884 description->units_num++;
2885 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2887 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2888 continue;
2890 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2892 else
2894 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2896 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2897 continue;
2899 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2901 if (decl_in_table == NULL)
2902 decl_in_table = insert_decl (decl);
2903 else
2905 if (decl->mode == dm_unit)
2906 error ("repeated declaration of unit `%s'",
2907 DECL_UNIT (decl)->name);
2908 else
2909 error ("repeated declaration of reservation `%s'",
2910 DECL_RESERV (decl)->name);
2914 /* Check bypasses and form list of bypasses for each (output)
2915 insn. */
2916 for (i = 0; i < description->decls_num; i++)
2918 decl = description->decls [i];
2919 if (decl->mode == dm_bypass)
2921 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2922 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2923 if (out_insn_reserv == NULL)
2924 error ("there is no insn reservation `%s'",
2925 DECL_BYPASS (decl)->out_insn_name);
2926 else if (in_insn_reserv == NULL)
2927 error ("there is no insn reservation `%s'",
2928 DECL_BYPASS (decl)->in_insn_name);
2929 else
2931 DECL_BYPASS (decl)->out_insn_reserv
2932 = DECL_INSN_RESERV (out_insn_reserv);
2933 DECL_BYPASS (decl)->in_insn_reserv
2934 = DECL_INSN_RESERV (in_insn_reserv);
2935 bypass
2936 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2937 DECL_BYPASS (decl)->in_insn_reserv);
2938 if (bypass != NULL)
2940 if (DECL_BYPASS (decl)->latency == bypass->latency)
2942 if (!w_flag)
2943 error
2944 ("the same bypass `%s - %s' is already defined",
2945 DECL_BYPASS (decl)->out_insn_name,
2946 DECL_BYPASS (decl)->in_insn_name);
2947 else
2948 warning
2949 ("the same bypass `%s - %s' is already defined",
2950 DECL_BYPASS (decl)->out_insn_name,
2951 DECL_BYPASS (decl)->in_insn_name);
2953 else
2954 error ("bypass `%s - %s' is already defined",
2955 DECL_BYPASS (decl)->out_insn_name,
2956 DECL_BYPASS (decl)->in_insn_name);
2958 else
2960 DECL_BYPASS (decl)->next
2961 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2962 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2963 = DECL_BYPASS (decl);
2969 /* Check exclusion set declarations and form exclusion sets. */
2970 for (i = 0; i < description->decls_num; i++)
2972 decl = description->decls [i];
2973 if (decl->mode == dm_excl)
2975 unit_set_el_t unit_set_el_list;
2976 unit_set_el_t unit_set_el_list_2;
2978 unit_set_el_list
2979 = process_excls (DECL_EXCL (decl)->names,
2980 DECL_EXCL (decl)->first_list_length, decl->pos);
2981 unit_set_el_list_2
2982 = process_excls (&DECL_EXCL (decl)->names
2983 [DECL_EXCL (decl)->first_list_length],
2984 DECL_EXCL (decl)->all_names_num
2985 - DECL_EXCL (decl)->first_list_length,
2986 decl->pos);
2987 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2988 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2992 /* Check presence set declarations and form presence sets. */
2993 for (i = 0; i < description->decls_num; i++)
2995 decl = description->decls [i];
2996 if (decl->mode == dm_presence)
2998 unit_set_el_t unit_set_el_list;
2999 pattern_set_el_t pattern_set_el_list;
3001 unit_set_el_list
3002 = process_presence_absence_names
3003 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
3004 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
3005 pattern_set_el_list
3006 = process_presence_absence_patterns
3007 (DECL_PRESENCE (decl)->patterns,
3008 DECL_PRESENCE (decl)->patterns_num,
3009 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
3010 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3011 decl->pos, TRUE,
3012 DECL_PRESENCE (decl)->final_p);
3016 /* Check absence set declarations and form absence sets. */
3017 for (i = 0; i < description->decls_num; i++)
3019 decl = description->decls [i];
3020 if (decl->mode == dm_absence)
3022 unit_set_el_t unit_set_el_list;
3023 pattern_set_el_t pattern_set_el_list;
3025 unit_set_el_list
3026 = process_presence_absence_names
3027 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
3028 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3029 pattern_set_el_list
3030 = process_presence_absence_patterns
3031 (DECL_ABSENCE (decl)->patterns,
3032 DECL_ABSENCE (decl)->patterns_num,
3033 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3034 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3035 decl->pos, FALSE,
3036 DECL_ABSENCE (decl)->final_p);
3041 /* The following function checks that declared automaton is used. If
3042 the automaton is not used, the function fixes error/warning. The
3043 following function must be called only after `process_decls'. */
3044 static void
3045 check_automaton_usage (void)
3047 decl_t decl;
3048 int i;
3050 for (i = 0; i < description->decls_num; i++)
3052 decl = description->decls [i];
3053 if (decl->mode == dm_automaton
3054 && !DECL_AUTOMATON (decl)->automaton_is_used)
3056 if (!w_flag)
3057 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
3058 else
3059 warning ("automaton `%s' is not used",
3060 DECL_AUTOMATON (decl)->name);
3065 /* The following recursive function processes all regexp in order to
3066 fix usage of units or reservations and to fix errors of undeclared
3067 name. The function may change unit_regexp onto reserv_regexp.
3068 Remember that reserv_regexp does not exist before the function
3069 call. */
3070 static regexp_t
3071 process_regexp (regexp_t regexp)
3073 decl_t decl_in_table;
3074 regexp_t new_regexp;
3075 int i;
3077 if (regexp->mode == rm_unit)
3079 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
3080 if (decl_in_table == NULL)
3081 error ("undeclared unit or reservation `%s'",
3082 REGEXP_UNIT (regexp)->name);
3083 else if (decl_in_table->mode == dm_unit)
3085 DECL_UNIT (decl_in_table)->unit_is_used = 1;
3086 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
3088 else if (decl_in_table->mode == dm_reserv)
3090 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
3091 new_regexp = create_node (sizeof (struct regexp));
3092 new_regexp->mode = rm_reserv;
3093 new_regexp->pos = regexp->pos;
3094 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
3095 REGEXP_RESERV (new_regexp)->reserv_decl
3096 = DECL_RESERV (decl_in_table);
3097 regexp = new_regexp;
3099 else
3100 abort ();
3102 else if (regexp->mode == rm_sequence)
3103 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3104 REGEXP_SEQUENCE (regexp)->regexps [i]
3105 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
3106 else if (regexp->mode == rm_allof)
3107 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3108 REGEXP_ALLOF (regexp)->regexps [i]
3109 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
3110 else if (regexp->mode == rm_oneof)
3111 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3112 REGEXP_ONEOF (regexp)->regexps [i]
3113 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
3114 else if (regexp->mode == rm_repeat)
3115 REGEXP_REPEAT (regexp)->regexp
3116 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
3117 else if (regexp->mode != rm_nothing)
3118 abort ();
3119 return regexp;
3122 /* The following function processes regexp of define_reservation and
3123 define_insn_reservation with the aid of function
3124 `process_regexp'. */
3125 static void
3126 process_regexp_decls (void)
3128 decl_t decl;
3129 int i;
3131 for (i = 0; i < description->decls_num; i++)
3133 decl = description->decls [i];
3134 if (decl->mode == dm_reserv)
3135 DECL_RESERV (decl)->regexp
3136 = process_regexp (DECL_RESERV (decl)->regexp);
3137 else if (decl->mode == dm_insn_reserv)
3138 DECL_INSN_RESERV (decl)->regexp
3139 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3143 /* The following function checks that declared unit is used. If the
3144 unit is not used, the function fixes errors/warnings. The
3145 following function must be called only after `process_decls',
3146 `process_regexp_decls'. */
3147 static void
3148 check_usage (void)
3150 decl_t decl;
3151 int i;
3153 for (i = 0; i < description->decls_num; i++)
3155 decl = description->decls [i];
3156 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3158 if (!w_flag)
3159 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3160 else
3161 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3163 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3165 if (!w_flag)
3166 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3167 else
3168 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3173 /* The following variable value is number of reservation being
3174 processed on loop recognition. */
3175 static int curr_loop_pass_num;
3177 /* The following recursive function returns nonzero value if REGEXP
3178 contains given decl or reservations in given regexp refers for
3179 given decl. */
3180 static int
3181 loop_in_regexp (regexp_t regexp, decl_t start_decl)
3183 int i;
3185 if (regexp == NULL)
3186 return 0;
3187 if (regexp->mode == rm_unit)
3188 return 0;
3189 else if (regexp->mode == rm_reserv)
3191 if (start_decl->mode == dm_reserv
3192 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3193 return 1;
3194 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3195 == curr_loop_pass_num)
3196 /* declaration has been processed. */
3197 return 0;
3198 else
3200 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3201 = curr_loop_pass_num;
3202 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3203 start_decl);
3206 else if (regexp->mode == rm_sequence)
3208 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3209 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3210 return 1;
3211 return 0;
3213 else if (regexp->mode == rm_allof)
3215 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3216 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3217 return 1;
3218 return 0;
3220 else if (regexp->mode == rm_oneof)
3222 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3223 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3224 return 1;
3225 return 0;
3227 else if (regexp->mode == rm_repeat)
3228 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3229 else
3231 if (regexp->mode != rm_nothing)
3232 abort ();
3233 return 0;
3237 /* The following function fixes errors "cycle in definition ...". The
3238 function uses function `loop_in_regexp' for that. */
3239 static void
3240 check_loops_in_regexps (void)
3242 decl_t decl;
3243 int i;
3245 for (i = 0; i < description->decls_num; i++)
3247 decl = description->decls [i];
3248 if (decl->mode == dm_reserv)
3249 DECL_RESERV (decl)->loop_pass_num = 0;
3251 for (i = 0; i < description->decls_num; i++)
3253 decl = description->decls [i];
3254 curr_loop_pass_num = i;
3256 if (decl->mode == dm_reserv)
3258 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
3259 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3261 if (DECL_RESERV (decl)->regexp == NULL)
3262 abort ();
3263 error ("cycle in definition of reservation `%s'",
3264 DECL_RESERV (decl)->name);
3270 /* The function recursively processes IR of reservation and defines
3271 max and min cycle for reservation of unit. */
3272 static void
3273 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
3274 int min_start_cycle, int *max_finish_cycle,
3275 int *min_finish_cycle)
3277 int i;
3279 if (regexp->mode == rm_unit)
3281 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
3282 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
3283 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
3284 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
3285 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
3286 *max_finish_cycle = max_start_cycle;
3287 *min_finish_cycle = min_start_cycle;
3289 else if (regexp->mode == rm_reserv)
3290 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3291 max_start_cycle, min_start_cycle,
3292 max_finish_cycle, min_finish_cycle);
3293 else if (regexp->mode == rm_repeat)
3295 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3297 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3298 max_start_cycle, min_start_cycle,
3299 max_finish_cycle, min_finish_cycle);
3300 max_start_cycle = *max_finish_cycle + 1;
3301 min_start_cycle = *min_finish_cycle + 1;
3304 else if (regexp->mode == rm_sequence)
3306 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3308 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3309 max_start_cycle, min_start_cycle,
3310 max_finish_cycle, min_finish_cycle);
3311 max_start_cycle = *max_finish_cycle + 1;
3312 min_start_cycle = *min_finish_cycle + 1;
3315 else if (regexp->mode == rm_allof)
3317 int max_cycle = 0;
3318 int min_cycle = 0;
3320 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3322 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3323 max_start_cycle, min_start_cycle,
3324 max_finish_cycle, min_finish_cycle);
3325 if (max_cycle < *max_finish_cycle)
3326 max_cycle = *max_finish_cycle;
3327 if (i == 0 || min_cycle > *min_finish_cycle)
3328 min_cycle = *min_finish_cycle;
3330 *max_finish_cycle = max_cycle;
3331 *min_finish_cycle = min_cycle;
3333 else if (regexp->mode == rm_oneof)
3335 int max_cycle = 0;
3336 int min_cycle = 0;
3338 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3340 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3341 max_start_cycle, min_start_cycle,
3342 max_finish_cycle, min_finish_cycle);
3343 if (max_cycle < *max_finish_cycle)
3344 max_cycle = *max_finish_cycle;
3345 if (i == 0 || min_cycle > *min_finish_cycle)
3346 min_cycle = *min_finish_cycle;
3348 *max_finish_cycle = max_cycle;
3349 *min_finish_cycle = min_cycle;
3351 else
3353 if (regexp->mode != rm_nothing)
3354 abort ();
3355 *max_finish_cycle = max_start_cycle;
3356 *min_finish_cycle = min_start_cycle;
3360 /* The following function is called only for correct program. The
3361 function defines max reservation of insns in cycles. */
3362 static void
3363 evaluate_max_reserv_cycles (void)
3365 int max_insn_cycles_num;
3366 int min_insn_cycles_num;
3367 decl_t decl;
3368 int i;
3370 description->max_insn_reserv_cycles = 0;
3371 for (i = 0; i < description->decls_num; i++)
3373 decl = description->decls [i];
3374 if (decl->mode == dm_insn_reserv)
3376 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3377 &max_insn_cycles_num, &min_insn_cycles_num);
3378 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3379 description->max_insn_reserv_cycles = max_insn_cycles_num;
3382 description->max_insn_reserv_cycles++;
3385 /* The following function calls functions for checking all
3386 description. */
3387 static void
3388 check_all_description (void)
3390 process_decls ();
3391 check_automaton_usage ();
3392 process_regexp_decls ();
3393 check_usage ();
3394 check_loops_in_regexps ();
3395 if (!have_error)
3396 evaluate_max_reserv_cycles ();
3401 /* The page contains abstract data `ticker'. This data is used to
3402 report time of different phases of building automata. It is
3403 possibly to write a description for which automata will be built
3404 during several minutes even on fast machine. */
3406 /* The following function creates ticker and makes it active. */
3407 static ticker_t
3408 create_ticker (void)
3410 ticker_t ticker;
3412 ticker.modified_creation_time = get_run_time ();
3413 ticker.incremented_off_time = 0;
3414 return ticker;
3417 /* The following function switches off given ticker. */
3418 static void
3419 ticker_off (ticker_t *ticker)
3421 if (ticker->incremented_off_time == 0)
3422 ticker->incremented_off_time = get_run_time () + 1;
3425 /* The following function switches on given ticker. */
3426 static void
3427 ticker_on (ticker_t *ticker)
3429 if (ticker->incremented_off_time != 0)
3431 ticker->modified_creation_time
3432 += get_run_time () - ticker->incremented_off_time + 1;
3433 ticker->incremented_off_time = 0;
3437 /* The following function returns current time in milliseconds since
3438 the moment when given ticker was created. */
3439 static int
3440 active_time (ticker_t ticker)
3442 if (ticker.incremented_off_time != 0)
3443 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3444 else
3445 return get_run_time () - ticker.modified_creation_time;
3448 /* The following function returns string representation of active time
3449 of given ticker. The result is string representation of seconds
3450 with accuracy of 1/100 second. Only result of the last call of the
3451 function exists. Therefore the following code is not correct
3453 printf ("parser time: %s\ngeneration time: %s\n",
3454 active_time_string (parser_ticker),
3455 active_time_string (generation_ticker));
3457 Correct code has to be the following
3459 printf ("parser time: %s\n", active_time_string (parser_ticker));
3460 printf ("generation time: %s\n",
3461 active_time_string (generation_ticker));
3464 static void
3465 print_active_time (FILE *f, ticker_t ticker)
3467 int msecs;
3469 msecs = active_time (ticker);
3470 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3475 /* The following variable value is number of automaton which are
3476 really being created. This value is defined on the base of
3477 argument of option `-split'. If the variable has zero value the
3478 number of automata is defined by the constructions `%automaton'.
3479 This case occurs when option `-split' is absent or has zero
3480 argument. If constructions `define_automaton' is absent only one
3481 automaton is created. */
3482 static int automata_num;
3484 /* The following variable values are times of
3485 o transformation of regular expressions
3486 o building NDFA (DFA if !ndfa_flag)
3487 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3488 o DFA minimization
3489 o building insn equivalence classes
3490 o all previous ones
3491 o code output */
3492 static ticker_t transform_time;
3493 static ticker_t NDFA_time;
3494 static ticker_t NDFA_to_DFA_time;
3495 static ticker_t minimize_time;
3496 static ticker_t equiv_time;
3497 static ticker_t automaton_generation_time;
3498 static ticker_t output_time;
3500 /* The following variable values are times of
3501 all checking
3502 all generation
3503 all pipeline hazard translator work */
3504 static ticker_t check_time;
3505 static ticker_t generation_time;
3506 static ticker_t all_time;
3510 /* Pseudo insn decl which denotes advancing cycle. */
3511 static decl_t advance_cycle_insn_decl;
3512 static void
3513 add_advance_cycle_insn_decl (void)
3515 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3516 advance_cycle_insn_decl->mode = dm_insn_reserv;
3517 advance_cycle_insn_decl->pos = no_pos;
3518 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3519 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
3520 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3521 = description->insns_num;
3522 description->decls [description->decls_num] = advance_cycle_insn_decl;
3523 description->decls_num++;
3524 description->insns_num++;
3525 num_dfa_decls++;
3529 /* Abstract data `alternative states' which represents
3530 nondeterministic nature of the description (see comments for
3531 structures alt_state and state). */
3533 /* List of free states. */
3534 static alt_state_t first_free_alt_state;
3536 #ifndef NDEBUG
3537 /* The following variables is maximal number of allocated nodes
3538 alt_state. */
3539 static int allocated_alt_states_num = 0;
3540 #endif
3542 /* The following function returns free node alt_state. It may be new
3543 allocated node or node freed earlier. */
3544 static alt_state_t
3545 get_free_alt_state (void)
3547 alt_state_t result;
3549 if (first_free_alt_state != NULL)
3551 result = first_free_alt_state;
3552 first_free_alt_state = first_free_alt_state->next_alt_state;
3554 else
3556 #ifndef NDEBUG
3557 allocated_alt_states_num++;
3558 #endif
3559 result = create_node (sizeof (struct alt_state));
3561 result->state = NULL;
3562 result->next_alt_state = NULL;
3563 result->next_sorted_alt_state = NULL;
3564 return result;
3567 /* The function frees node ALT_STATE. */
3568 static void
3569 free_alt_state (alt_state_t alt_state)
3571 if (alt_state == NULL)
3572 return;
3573 alt_state->next_alt_state = first_free_alt_state;
3574 first_free_alt_state = alt_state;
3577 /* The function frees list started with node ALT_STATE_LIST. */
3578 static void
3579 free_alt_states (alt_state_t alt_states_list)
3581 alt_state_t curr_alt_state;
3582 alt_state_t next_alt_state;
3584 for (curr_alt_state = alt_states_list;
3585 curr_alt_state != NULL;
3586 curr_alt_state = next_alt_state)
3588 next_alt_state = curr_alt_state->next_alt_state;
3589 free_alt_state (curr_alt_state);
3593 /* The function compares unique numbers of alt states. */
3594 static int
3595 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3597 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3598 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3599 return 0;
3600 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3601 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3602 return -1;
3603 else
3604 return 1;
3607 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3608 states from the list. The comparison key is alt state unique
3609 number. */
3610 static alt_state_t
3611 uniq_sort_alt_states (alt_state_t alt_states_list)
3613 alt_state_t curr_alt_state;
3614 vla_ptr_t alt_states;
3615 size_t i;
3616 size_t prev_unique_state_ind;
3617 alt_state_t result;
3618 alt_state_t *result_ptr;
3620 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3621 for (curr_alt_state = alt_states_list;
3622 curr_alt_state != NULL;
3623 curr_alt_state = curr_alt_state->next_alt_state)
3624 VLA_PTR_ADD (alt_states, curr_alt_state);
3625 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3626 sizeof (alt_state_t), alt_state_cmp);
3627 if (VLA_PTR_LENGTH (alt_states) == 0)
3628 result = NULL;
3629 else
3631 result_ptr = VLA_PTR_BEGIN (alt_states);
3632 prev_unique_state_ind = 0;
3633 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3634 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3636 prev_unique_state_ind++;
3637 result_ptr [prev_unique_state_ind] = result_ptr [i];
3639 #if 0
3640 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3641 free_alt_state (result_ptr [i]);
3642 #endif
3643 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3644 result_ptr = VLA_PTR_BEGIN (alt_states);
3645 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3646 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3647 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3648 result = *result_ptr;
3650 VLA_PTR_DELETE (alt_states);
3651 return result;
3654 /* The function checks equality of alt state lists. Remember that the
3655 lists must be already sorted by the previous function. */
3656 static int
3657 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3659 while (alt_states_1 != NULL && alt_states_2 != NULL
3660 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3662 alt_states_1 = alt_states_1->next_sorted_alt_state;
3663 alt_states_2 = alt_states_2->next_sorted_alt_state;
3665 return alt_states_1 == alt_states_2;
3668 /* Initialization of the abstract data. */
3669 static void
3670 initiate_alt_states (void)
3672 first_free_alt_state = NULL;
3675 /* Finishing work with the abstract data. */
3676 static void
3677 finish_alt_states (void)
3683 /* The page contains macros for work with bits strings. We could use
3684 standard gcc bitmap or sbitmap but it would result in difficulties
3685 of building canadian cross. */
3687 /* Set bit number bitno in the bit string. The macro is not side
3688 effect proof. */
3689 #define SET_BIT(bitstring, bitno) \
3690 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3692 #define CLEAR_BIT(bitstring, bitno) \
3693 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3695 /* Test if bit number bitno in the bitstring is set. The macro is not
3696 side effect proof. */
3697 #define TEST_BIT(bitstring, bitno) \
3698 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3702 /* This page contains abstract data `state'. */
3704 /* Maximal length of reservations in cycles (>= 1). */
3705 static int max_cycles_num;
3707 /* Number of set elements (see type set_el_t) needed for
3708 representation of one cycle reservation. It is depended on units
3709 number. */
3710 static int els_in_cycle_reserv;
3712 /* Number of set elements (see type set_el_t) needed for
3713 representation of maximal length reservation. Deterministic
3714 reservation is stored as set (bit string) of length equal to the
3715 variable value * number of bits in set_el_t. */
3716 static int els_in_reservs;
3718 /* VLA for representation of array of pointers to unit
3719 declarations. */
3720 static vla_ptr_t units_container;
3722 /* The start address of the array. */
3723 static unit_decl_t *units_array;
3725 /* Temporary reservation of maximal length. */
3726 static reserv_sets_t temp_reserv;
3728 /* The state table itself is represented by the following variable. */
3729 static htab_t state_table;
3731 /* VLA for representation of array of pointers to free nodes
3732 `state'. */
3733 static vla_ptr_t free_states;
3735 static int curr_unique_state_num;
3737 #ifndef NDEBUG
3738 /* The following variables is maximal number of allocated nodes
3739 `state'. */
3740 static int allocated_states_num = 0;
3741 #endif
3743 /* Allocate new reservation set. */
3744 static reserv_sets_t
3745 alloc_empty_reserv_sets (void)
3747 reserv_sets_t result;
3749 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3750 result = (reserv_sets_t) obstack_base (&irp);
3751 obstack_finish (&irp);
3752 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3753 return result;
3756 /* Hash value of reservation set. */
3757 static unsigned
3758 reserv_sets_hash_value (reserv_sets_t reservs)
3760 set_el_t hash_value;
3761 unsigned result;
3762 int reservs_num, i;
3763 set_el_t *reserv_ptr;
3765 hash_value = 0;
3766 reservs_num = els_in_reservs;
3767 reserv_ptr = reservs;
3768 i = 0;
3769 while (reservs_num != 0)
3771 reservs_num--;
3772 hash_value += ((*reserv_ptr >> i)
3773 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3774 i++;
3775 if (i == sizeof (set_el_t) * CHAR_BIT)
3776 i = 0;
3777 reserv_ptr++;
3779 if (sizeof (set_el_t) <= sizeof (unsigned))
3780 return hash_value;
3781 result = 0;
3782 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3784 result += (unsigned) hash_value;
3785 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3787 return result;
3790 /* Comparison of given reservation sets. */
3791 static int
3792 reserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3794 int reservs_num;
3795 set_el_t *reserv_ptr_1;
3796 set_el_t *reserv_ptr_2;
3798 if (reservs_1 == NULL || reservs_2 == NULL)
3799 abort ();
3800 reservs_num = els_in_reservs;
3801 reserv_ptr_1 = reservs_1;
3802 reserv_ptr_2 = reservs_2;
3803 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3805 reservs_num--;
3806 reserv_ptr_1++;
3807 reserv_ptr_2++;
3809 if (reservs_num == 0)
3810 return 0;
3811 else if (*reserv_ptr_1 < *reserv_ptr_2)
3812 return -1;
3813 else
3814 return 1;
3817 /* The function checks equality of the reservation sets. */
3818 static int
3819 reserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3821 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3824 /* Set up in the reservation set that unit with UNIT_NUM is used on
3825 CYCLE_NUM. */
3826 static void
3827 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3829 if (cycle_num >= max_cycles_num)
3830 abort ();
3831 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3832 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3835 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3836 used on CYCLE_NUM. */
3837 static int
3838 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3840 if (cycle_num >= max_cycles_num)
3841 abort ();
3842 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3843 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3846 /* The function checks that the reservation set represents no one unit
3847 reservation. */
3848 static int
3849 it_is_empty_reserv_sets (reserv_sets_t operand)
3851 set_el_t *reserv_ptr;
3852 int reservs_num;
3854 if (operand == NULL)
3855 abort ();
3856 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3857 reservs_num != 0;
3858 reserv_ptr++, reservs_num--)
3859 if (*reserv_ptr != 0)
3860 return 0;
3861 return 1;
3864 /* The function checks that the reservation sets are intersected,
3865 i.e. there is a unit reservation on a cycle in both reservation
3866 sets. */
3867 static int
3868 reserv_sets_are_intersected (reserv_sets_t operand_1,
3869 reserv_sets_t operand_2)
3871 set_el_t *el_ptr_1;
3872 set_el_t *el_ptr_2;
3873 set_el_t *cycle_ptr_1;
3874 set_el_t *cycle_ptr_2;
3876 if (operand_1 == NULL || operand_2 == NULL)
3877 abort ();
3878 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3879 el_ptr_1 < operand_1 + els_in_reservs;
3880 el_ptr_1++, el_ptr_2++)
3881 if (*el_ptr_1 & *el_ptr_2)
3882 return 1;
3883 reserv_sets_or (temp_reserv, operand_1, operand_2);
3884 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3885 cycle_ptr_1 < operand_1 + els_in_reservs;
3886 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3888 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3889 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3890 el_ptr_1++, el_ptr_2++)
3891 if (*el_ptr_1 & *el_ptr_2)
3892 return 1;
3893 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3894 return 1;
3895 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3896 - operand_2),
3897 cycle_ptr_2, TRUE))
3898 return 1;
3899 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3900 return 1;
3901 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3902 cycle_ptr_2, TRUE))
3903 return 1;
3905 return 0;
3908 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3909 cpu cycle. The remaining bits of OPERAND (representing the last
3910 cycle unit reservations) are not changed. */
3911 static void
3912 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3914 int i;
3916 if (result == NULL || operand == NULL || result == operand)
3917 abort ();
3918 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3919 result [i - els_in_cycle_reserv] = operand [i];
3922 /* OR of the reservation sets. */
3923 static void
3924 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3925 reserv_sets_t operand_2)
3927 set_el_t *el_ptr_1;
3928 set_el_t *el_ptr_2;
3929 set_el_t *result_set_el_ptr;
3931 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3932 abort ();
3933 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3934 el_ptr_1 < operand_1 + els_in_reservs;
3935 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3936 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3939 /* AND of the reservation sets. */
3940 static void
3941 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3942 reserv_sets_t operand_2)
3944 set_el_t *el_ptr_1;
3945 set_el_t *el_ptr_2;
3946 set_el_t *result_set_el_ptr;
3948 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3949 abort ();
3950 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3951 el_ptr_1 < operand_1 + els_in_reservs;
3952 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3953 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3956 /* The function outputs string representation of units reservation on
3957 cycle START_CYCLE in the reservation set. The function uses repeat
3958 construction if REPETITION_NUM > 1. */
3959 static void
3960 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3961 int repetition_num)
3963 int unit_num;
3964 int reserved_units_num;
3966 reserved_units_num = 0;
3967 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3968 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3969 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3970 reserved_units_num++;
3971 if (repetition_num <= 0)
3972 abort ();
3973 if (repetition_num != 1 && reserved_units_num > 1)
3974 fprintf (f, "(");
3975 reserved_units_num = 0;
3976 for (unit_num = 0;
3977 unit_num < description->units_num;
3978 unit_num++)
3979 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3980 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3982 if (reserved_units_num != 0)
3983 fprintf (f, "+");
3984 reserved_units_num++;
3985 fprintf (f, "%s", units_array [unit_num]->name);
3987 if (reserved_units_num == 0)
3988 fprintf (f, NOTHING_NAME);
3989 if (repetition_num <= 0)
3990 abort ();
3991 if (repetition_num != 1 && reserved_units_num > 1)
3992 fprintf (f, ")");
3993 if (repetition_num != 1)
3994 fprintf (f, "*%d", repetition_num);
3997 /* The function outputs string representation of units reservation in
3998 the reservation set. */
3999 static void
4000 output_reserv_sets (FILE *f, reserv_sets_t reservs)
4002 int start_cycle = 0;
4003 int cycle;
4004 int repetition_num;
4006 repetition_num = 0;
4007 for (cycle = 0; cycle < max_cycles_num; cycle++)
4008 if (repetition_num == 0)
4010 repetition_num++;
4011 start_cycle = cycle;
4013 else if (memcmp
4014 ((char *) reservs + start_cycle * els_in_cycle_reserv
4015 * sizeof (set_el_t),
4016 (char *) reservs + cycle * els_in_cycle_reserv
4017 * sizeof (set_el_t),
4018 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
4019 repetition_num++;
4020 else
4022 if (start_cycle != 0)
4023 fprintf (f, ", ");
4024 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
4025 repetition_num = 1;
4026 start_cycle = cycle;
4028 if (start_cycle < max_cycles_num)
4030 if (start_cycle != 0)
4031 fprintf (f, ", ");
4032 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
4036 /* The following function returns free node state for AUTOMATON. It
4037 may be new allocated node or node freed earlier. The function also
4038 allocates reservation set if WITH_RESERVS has nonzero value. */
4039 static state_t
4040 get_free_state (int with_reservs, automaton_t automaton)
4042 state_t result;
4044 if (max_cycles_num <= 0 || automaton == NULL)
4045 abort ();
4046 if (VLA_PTR_LENGTH (free_states) != 0)
4048 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
4049 VLA_PTR_SHORTEN (free_states, 1);
4050 result->automaton = automaton;
4051 result->first_out_arc = NULL;
4052 result->it_was_placed_in_stack_for_NDFA_forming = 0;
4053 result->it_was_placed_in_stack_for_DFA_forming = 0;
4054 result->component_states = NULL;
4055 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
4057 else
4059 #ifndef NDEBUG
4060 allocated_states_num++;
4061 #endif
4062 result = create_node (sizeof (struct state));
4063 result->automaton = automaton;
4064 result->first_out_arc = NULL;
4065 result->unique_num = curr_unique_state_num;
4066 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
4067 curr_unique_state_num++;
4069 if (with_reservs)
4071 if (result->reservs == NULL)
4072 result->reservs = alloc_empty_reserv_sets ();
4073 else
4074 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
4076 return result;
4079 /* The function frees node STATE. */
4080 static void
4081 free_state (state_t state)
4083 free_alt_states (state->component_states);
4084 VLA_PTR_ADD (free_states, state);
4087 /* Hash value of STATE. If STATE represents deterministic state it is
4088 simply hash value of the corresponding reservation set. Otherwise
4089 it is formed from hash values of the component deterministic
4090 states. One more key is order number of state automaton. */
4091 static hashval_t
4092 state_hash (const void *state)
4094 unsigned int hash_value;
4095 alt_state_t alt_state;
4097 if (((state_t) state)->component_states == NULL)
4098 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
4099 else
4101 hash_value = 0;
4102 for (alt_state = ((state_t) state)->component_states;
4103 alt_state != NULL;
4104 alt_state = alt_state->next_sorted_alt_state)
4105 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4106 | (hash_value << CHAR_BIT))
4107 + alt_state->state->unique_num);
4109 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4110 | (hash_value << CHAR_BIT))
4111 + ((state_t) state)->automaton->automaton_order_num);
4112 return hash_value;
4115 /* Return nonzero value if the states are the same. */
4116 static int
4117 state_eq_p (const void *state_1, const void *state_2)
4119 alt_state_t alt_state_1;
4120 alt_state_t alt_state_2;
4122 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
4123 return 0;
4124 else if (((state_t) state_1)->component_states == NULL
4125 && ((state_t) state_2)->component_states == NULL)
4126 return reserv_sets_eq (((state_t) state_1)->reservs,
4127 ((state_t) state_2)->reservs);
4128 else if (((state_t) state_1)->component_states != NULL
4129 && ((state_t) state_2)->component_states != NULL)
4131 for (alt_state_1 = ((state_t) state_1)->component_states,
4132 alt_state_2 = ((state_t) state_2)->component_states;
4133 alt_state_1 != NULL && alt_state_2 != NULL;
4134 alt_state_1 = alt_state_1->next_sorted_alt_state,
4135 alt_state_2 = alt_state_2->next_sorted_alt_state)
4136 /* All state in the list must be already in the hash table.
4137 Also the lists must be sorted. */
4138 if (alt_state_1->state != alt_state_2->state)
4139 return 0;
4140 return alt_state_1 == alt_state_2;
4142 else
4143 return 0;
4146 /* Insert STATE into the state table. */
4147 static state_t
4148 insert_state (state_t state)
4150 void **entry_ptr;
4152 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
4153 if (*entry_ptr == NULL)
4154 *entry_ptr = (void *) state;
4155 return (state_t) *entry_ptr;
4158 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4159 deterministic STATE. */
4160 static void
4161 set_state_reserv (state_t state, int cycle_num, int unit_num)
4163 set_unit_reserv (state->reservs, cycle_num, unit_num);
4166 /* Return nonzero value if the deterministic states contains a
4167 reservation of the same cpu unit on the same cpu cycle. */
4168 static int
4169 intersected_state_reservs_p (state_t state1, state_t state2)
4171 if (state1->automaton != state2->automaton)
4172 abort ();
4173 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
4176 /* Return deterministic state (inserted into the table) which
4177 representing the automaton state which is union of reservations of
4178 the deterministic states masked by RESERVS. */
4179 static state_t
4180 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
4182 state_t result;
4183 state_t state_in_table;
4185 if (state1->automaton != state2->automaton)
4186 abort ();
4187 result = get_free_state (1, state1->automaton);
4188 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
4189 reserv_sets_and (result->reservs, result->reservs, reservs);
4190 state_in_table = insert_state (result);
4191 if (result != state_in_table)
4193 free_state (result);
4194 result = state_in_table;
4196 return result;
4199 /* Return deterministic state (inserted into the table) which
4200 represent the automaton state is obtained from deterministic STATE
4201 by advancing cpu cycle and masking by RESERVS. */
4202 static state_t
4203 state_shift (state_t state, reserv_sets_t reservs)
4205 state_t result;
4206 state_t state_in_table;
4208 result = get_free_state (1, state->automaton);
4209 reserv_sets_shift (result->reservs, state->reservs);
4210 reserv_sets_and (result->reservs, result->reservs, reservs);
4211 state_in_table = insert_state (result);
4212 if (result != state_in_table)
4214 free_state (result);
4215 result = state_in_table;
4217 return result;
4220 /* Initialization of the abstract data. */
4221 static void
4222 initiate_states (void)
4224 decl_t decl;
4225 int i;
4227 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
4228 units_array
4229 = (description->decls_num && description->units_num
4230 ? VLA_PTR_BEGIN (units_container) : NULL);
4231 for (i = 0; i < description->decls_num; i++)
4233 decl = description->decls [i];
4234 if (decl->mode == dm_unit)
4235 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
4237 max_cycles_num = description->max_insn_reserv_cycles;
4238 els_in_cycle_reserv
4239 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
4240 / (sizeof (set_el_t) * CHAR_BIT));
4241 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
4242 curr_unique_state_num = 0;
4243 initiate_alt_states ();
4244 VLA_PTR_CREATE (free_states, 1500, "free states");
4245 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
4246 temp_reserv = alloc_empty_reserv_sets ();
4249 /* Finishing work with the abstract data. */
4250 static void
4251 finish_states (void)
4253 VLA_PTR_DELETE (units_container);
4254 htab_delete (state_table);
4255 VLA_PTR_DELETE (free_states);
4256 finish_alt_states ();
4261 /* Abstract data `arcs'. */
4263 /* List of free arcs. */
4264 static arc_t first_free_arc;
4266 #ifndef NDEBUG
4267 /* The following variables is maximal number of allocated nodes
4268 `arc'. */
4269 static int allocated_arcs_num = 0;
4270 #endif
4272 /* The function frees node ARC. */
4273 static void
4274 free_arc (arc_t arc)
4276 arc->next_out_arc = first_free_arc;
4277 first_free_arc = arc;
4280 /* The function removes and frees ARC staring from FROM_STATE. */
4281 static void
4282 remove_arc (state_t from_state, arc_t arc)
4284 arc_t prev_arc;
4285 arc_t curr_arc;
4287 if (arc == NULL)
4288 abort ();
4289 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
4290 curr_arc != NULL;
4291 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4292 if (curr_arc == arc)
4293 break;
4294 if (curr_arc == NULL)
4295 abort ();
4296 if (prev_arc == NULL)
4297 from_state->first_out_arc = arc->next_out_arc;
4298 else
4299 prev_arc->next_out_arc = arc->next_out_arc;
4300 free_arc (arc);
4303 /* The functions returns arc with given characteristics (or NULL if
4304 the arc does not exist). */
4305 static arc_t
4306 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
4308 arc_t arc;
4310 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4311 if (arc->to_state == to_state && arc->insn == insn)
4312 return arc;
4313 return NULL;
4316 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4317 and with given STATE_ALTS. The function returns added arc (or
4318 already existing arc). */
4319 static arc_t
4320 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn,
4321 int state_alts)
4323 arc_t new_arc;
4325 new_arc = find_arc (from_state, to_state, ainsn);
4326 if (new_arc != NULL)
4327 return new_arc;
4328 if (first_free_arc == NULL)
4330 #ifndef NDEBUG
4331 allocated_arcs_num++;
4332 #endif
4333 new_arc = create_node (sizeof (struct arc));
4334 new_arc->to_state = NULL;
4335 new_arc->insn = NULL;
4336 new_arc->next_out_arc = NULL;
4338 else
4340 new_arc = first_free_arc;
4341 first_free_arc = first_free_arc->next_out_arc;
4343 new_arc->to_state = to_state;
4344 new_arc->insn = ainsn;
4345 ainsn->arc_exists_p = 1;
4346 new_arc->next_out_arc = from_state->first_out_arc;
4347 from_state->first_out_arc = new_arc;
4348 new_arc->next_arc_marked_by_insn = NULL;
4349 new_arc->state_alts = state_alts;
4350 return new_arc;
4353 /* The function returns the first arc starting from STATE. */
4354 static arc_t
4355 first_out_arc (state_t state)
4357 return state->first_out_arc;
4360 /* The function returns next out arc after ARC. */
4361 static arc_t
4362 next_out_arc (arc_t arc)
4364 return arc->next_out_arc;
4367 /* Initialization of the abstract data. */
4368 static void
4369 initiate_arcs (void)
4371 first_free_arc = NULL;
4374 /* Finishing work with the abstract data. */
4375 static void
4376 finish_arcs (void)
4382 /* Abstract data `automata lists'. */
4384 /* List of free states. */
4385 static automata_list_el_t first_free_automata_list_el;
4387 /* The list being formed. */
4388 static automata_list_el_t current_automata_list;
4390 /* Hash table of automata lists. */
4391 static htab_t automata_list_table;
4393 /* The following function returns free automata list el. It may be
4394 new allocated node or node freed earlier. */
4395 static automata_list_el_t
4396 get_free_automata_list_el (void)
4398 automata_list_el_t result;
4400 if (first_free_automata_list_el != NULL)
4402 result = first_free_automata_list_el;
4403 first_free_automata_list_el
4404 = first_free_automata_list_el->next_automata_list_el;
4406 else
4407 result = create_node (sizeof (struct automata_list_el));
4408 result->automaton = NULL;
4409 result->next_automata_list_el = NULL;
4410 return result;
4413 /* The function frees node AUTOMATA_LIST_EL. */
4414 static void
4415 free_automata_list_el (automata_list_el_t automata_list_el)
4417 if (automata_list_el == NULL)
4418 return;
4419 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4420 first_free_automata_list_el = automata_list_el;
4423 /* The function frees list AUTOMATA_LIST. */
4424 static void
4425 free_automata_list (automata_list_el_t automata_list)
4427 automata_list_el_t curr_automata_list_el;
4428 automata_list_el_t next_automata_list_el;
4430 for (curr_automata_list_el = automata_list;
4431 curr_automata_list_el != NULL;
4432 curr_automata_list_el = next_automata_list_el)
4434 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4435 free_automata_list_el (curr_automata_list_el);
4439 /* Hash value of AUTOMATA_LIST. */
4440 static hashval_t
4441 automata_list_hash (const void *automata_list)
4443 unsigned int hash_value;
4444 automata_list_el_t curr_automata_list_el;
4446 hash_value = 0;
4447 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4448 curr_automata_list_el != NULL;
4449 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4450 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4451 | (hash_value << CHAR_BIT))
4452 + curr_automata_list_el->automaton->automaton_order_num);
4453 return hash_value;
4456 /* Return nonzero value if the automata_lists are the same. */
4457 static int
4458 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4460 automata_list_el_t automata_list_el_1;
4461 automata_list_el_t automata_list_el_2;
4463 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4464 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4465 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4466 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4467 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4468 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4469 return 0;
4470 return automata_list_el_1 == automata_list_el_2;
4473 /* Initialization of the abstract data. */
4474 static void
4475 initiate_automata_lists (void)
4477 first_free_automata_list_el = NULL;
4478 automata_list_table = htab_create (1500, automata_list_hash,
4479 automata_list_eq_p, (htab_del) 0);
4482 /* The following function starts new automata list and makes it the
4483 current one. */
4484 static void
4485 automata_list_start (void)
4487 current_automata_list = NULL;
4490 /* The following function adds AUTOMATON to the current list. */
4491 static void
4492 automata_list_add (automaton_t automaton)
4494 automata_list_el_t el;
4496 el = get_free_automata_list_el ();
4497 el->automaton = automaton;
4498 el->next_automata_list_el = current_automata_list;
4499 current_automata_list = el;
4502 /* The following function finishes forming the current list, inserts
4503 it into the table and returns it. */
4504 static automata_list_el_t
4505 automata_list_finish (void)
4507 void **entry_ptr;
4509 if (current_automata_list == NULL)
4510 return NULL;
4511 entry_ptr = htab_find_slot (automata_list_table,
4512 (void *) current_automata_list, 1);
4513 if (*entry_ptr == NULL)
4514 *entry_ptr = (void *) current_automata_list;
4515 else
4516 free_automata_list (current_automata_list);
4517 current_automata_list = NULL;
4518 return (automata_list_el_t) *entry_ptr;
4521 /* Finishing work with the abstract data. */
4522 static void
4523 finish_automata_lists (void)
4525 htab_delete (automata_list_table);
4530 /* The page contains abstract data for work with exclusion sets (see
4531 exclusion_set in file rtl.def). */
4533 /* The following variable refers to an exclusion set returned by
4534 get_excl_set. This is bit string of length equal to cpu units
4535 number. If exclusion set for given unit contains 1 for a unit,
4536 then simultaneous reservation of the units is prohibited. */
4537 static reserv_sets_t excl_set;
4539 /* The array contains exclusion sets for each unit. */
4540 static reserv_sets_t *unit_excl_set_table;
4542 /* The following function forms the array containing exclusion sets
4543 for each unit. */
4544 static void
4545 initiate_excl_sets (void)
4547 decl_t decl;
4548 reserv_sets_t unit_excl_set;
4549 unit_set_el_t el;
4550 int i;
4552 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4553 excl_set = (reserv_sets_t) obstack_base (&irp);
4554 obstack_finish (&irp);
4555 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4556 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4557 obstack_finish (&irp);
4558 /* Evaluate unit exclusion sets. */
4559 for (i = 0; i < description->decls_num; i++)
4561 decl = description->decls [i];
4562 if (decl->mode == dm_unit)
4564 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4565 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4566 obstack_finish (&irp);
4567 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4568 for (el = DECL_UNIT (decl)->excl_list;
4569 el != NULL;
4570 el = el->next_unit_set_el)
4572 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4573 el->unit_decl->in_set_p = TRUE;
4575 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4580 /* The function sets up and return EXCL_SET which is union of
4581 exclusion sets for each unit in IN_SET. */
4582 static reserv_sets_t
4583 get_excl_set (reserv_sets_t in_set)
4585 int excl_char_num;
4586 int chars_num;
4587 int i;
4588 int start_unit_num;
4589 int unit_num;
4591 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4592 memset (excl_set, 0, chars_num);
4593 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4594 if (((unsigned char *) in_set) [excl_char_num])
4595 for (i = CHAR_BIT - 1; i >= 0; i--)
4596 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4598 start_unit_num = excl_char_num * CHAR_BIT + i;
4599 if (start_unit_num >= description->units_num)
4600 return excl_set;
4601 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4603 excl_set [unit_num]
4604 |= unit_excl_set_table [start_unit_num] [unit_num];
4607 return excl_set;
4612 /* The page contains abstract data for work with presence/absence
4613 pattern sets (see presence_set/absence_set in file rtl.def). */
4615 /* The following arrays contain correspondingly presence, final
4616 presence, absence, and final absence patterns for each unit. */
4617 static pattern_reserv_t *unit_presence_set_table;
4618 static pattern_reserv_t *unit_final_presence_set_table;
4619 static pattern_reserv_t *unit_absence_set_table;
4620 static pattern_reserv_t *unit_final_absence_set_table;
4622 /* The following function forms list of reservation sets for given
4623 PATTERN_LIST. */
4624 static pattern_reserv_t
4625 form_reserv_sets_list (pattern_set_el_t pattern_list)
4627 pattern_set_el_t el;
4628 pattern_reserv_t first, curr, prev;
4629 int i;
4631 prev = first = NULL;
4632 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4634 curr = create_node (sizeof (struct pattern_reserv));
4635 curr->reserv = alloc_empty_reserv_sets ();
4636 curr->next_pattern_reserv = NULL;
4637 for (i = 0; i < el->units_num; i++)
4639 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4640 el->unit_decls [i]->in_set_p = TRUE;
4642 if (prev != NULL)
4643 prev->next_pattern_reserv = curr;
4644 else
4645 first = curr;
4646 prev = curr;
4648 return first;
4651 /* The following function forms the array containing presence and
4652 absence pattern sets for each unit. */
4653 static void
4654 initiate_presence_absence_pattern_sets (void)
4656 decl_t decl;
4657 int i;
4659 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4660 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4661 obstack_finish (&irp);
4662 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4663 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4664 obstack_finish (&irp);
4665 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4666 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4667 obstack_finish (&irp);
4668 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4669 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4670 obstack_finish (&irp);
4671 /* Evaluate unit presence/absence sets. */
4672 for (i = 0; i < description->decls_num; i++)
4674 decl = description->decls [i];
4675 if (decl->mode == dm_unit)
4677 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4678 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4679 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4680 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4681 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4682 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4683 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4684 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4689 /* The function checks that CHECKED_SET satisfies all presence pattern
4690 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4691 is ok. */
4692 static int
4693 check_presence_pattern_sets (reserv_sets_t checked_set,
4694 reserv_sets_t origional_set,
4695 int final_p)
4697 int char_num;
4698 int chars_num;
4699 int i;
4700 int start_unit_num;
4701 int unit_num;
4702 int presence_p;
4703 pattern_reserv_t pat_reserv;
4705 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4706 for (char_num = 0; char_num < chars_num; char_num++)
4707 if (((unsigned char *) origional_set) [char_num])
4708 for (i = CHAR_BIT - 1; i >= 0; i--)
4709 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4711 start_unit_num = char_num * CHAR_BIT + i;
4712 if (start_unit_num >= description->units_num)
4713 break;
4714 if ((final_p
4715 && unit_final_presence_set_table [start_unit_num] == NULL)
4716 || (!final_p
4717 && unit_presence_set_table [start_unit_num] == NULL))
4718 continue;
4719 presence_p = FALSE;
4720 for (pat_reserv = (final_p
4721 ? unit_final_presence_set_table [start_unit_num]
4722 : unit_presence_set_table [start_unit_num]);
4723 pat_reserv != NULL;
4724 pat_reserv = pat_reserv->next_pattern_reserv)
4726 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4727 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4728 != pat_reserv->reserv [unit_num])
4729 break;
4730 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4732 if (!presence_p)
4733 return FALSE;
4735 return TRUE;
4738 /* The function checks that CHECKED_SET satisfies all absence pattern
4739 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4740 is ok. */
4741 static int
4742 check_absence_pattern_sets (reserv_sets_t checked_set,
4743 reserv_sets_t origional_set,
4744 int final_p)
4746 int char_num;
4747 int chars_num;
4748 int i;
4749 int start_unit_num;
4750 int unit_num;
4751 pattern_reserv_t pat_reserv;
4753 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4754 for (char_num = 0; char_num < chars_num; char_num++)
4755 if (((unsigned char *) origional_set) [char_num])
4756 for (i = CHAR_BIT - 1; i >= 0; i--)
4757 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4759 start_unit_num = char_num * CHAR_BIT + i;
4760 if (start_unit_num >= description->units_num)
4761 break;
4762 for (pat_reserv = (final_p
4763 ? unit_final_absence_set_table [start_unit_num]
4764 : unit_absence_set_table [start_unit_num]);
4765 pat_reserv != NULL;
4766 pat_reserv = pat_reserv->next_pattern_reserv)
4768 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4769 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4770 != pat_reserv->reserv [unit_num]
4771 && pat_reserv->reserv [unit_num])
4772 break;
4773 if (unit_num >= els_in_cycle_reserv)
4774 return FALSE;
4777 return TRUE;
4782 /* This page contains code for transformation of original reservations
4783 described in .md file. The main goal of transformations is
4784 simplifying reservation and lifting up all `|' on the top of IR
4785 reservation representation. */
4788 /* The following function makes copy of IR representation of
4789 reservation. The function also substitutes all reservations
4790 defined by define_reservation by corresponding value during making
4791 the copy. */
4792 static regexp_t
4793 copy_insn_regexp (regexp_t regexp)
4795 regexp_t result;
4796 int i;
4798 if (regexp->mode == rm_reserv)
4799 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4800 else if (regexp->mode == rm_unit)
4801 result = copy_node (regexp, sizeof (struct regexp));
4802 else if (regexp->mode == rm_repeat)
4804 result = copy_node (regexp, sizeof (struct regexp));
4805 REGEXP_REPEAT (result)->regexp
4806 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4808 else if (regexp->mode == rm_sequence)
4810 result = copy_node (regexp,
4811 sizeof (struct regexp) + sizeof (regexp_t)
4812 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4813 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4814 REGEXP_SEQUENCE (result)->regexps [i]
4815 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4817 else if (regexp->mode == rm_allof)
4819 result = copy_node (regexp,
4820 sizeof (struct regexp) + sizeof (regexp_t)
4821 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4822 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4823 REGEXP_ALLOF (result)->regexps [i]
4824 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4826 else if (regexp->mode == rm_oneof)
4828 result = copy_node (regexp,
4829 sizeof (struct regexp) + sizeof (regexp_t)
4830 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4831 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4832 REGEXP_ONEOF (result)->regexps [i]
4833 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4835 else
4837 if (regexp->mode != rm_nothing)
4838 abort ();
4839 result = copy_node (regexp, sizeof (struct regexp));
4841 return result;
4844 /* The following variable is set up 1 if a transformation has been
4845 applied. */
4846 static int regexp_transformed_p;
4848 /* The function makes transformation
4849 A*N -> A, A, ... */
4850 static regexp_t
4851 transform_1 (regexp_t regexp)
4853 int i;
4854 int repeat_num;
4855 regexp_t operand;
4856 pos_t pos;
4858 if (regexp->mode == rm_repeat)
4860 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4861 if (repeat_num <= 1)
4862 abort ();
4863 operand = REGEXP_REPEAT (regexp)->regexp;
4864 pos = regexp->mode;
4865 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4866 * (repeat_num - 1));
4867 regexp->mode = rm_sequence;
4868 regexp->pos = pos;
4869 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4870 for (i = 0; i < repeat_num; i++)
4871 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4872 regexp_transformed_p = 1;
4874 return regexp;
4877 /* The function makes transformations
4878 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4879 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4880 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4881 static regexp_t
4882 transform_2 (regexp_t regexp)
4884 if (regexp->mode == rm_sequence)
4886 regexp_t sequence = NULL;
4887 regexp_t result;
4888 int sequence_index = 0;
4889 int i, j;
4891 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4892 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4894 sequence_index = i;
4895 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4896 break;
4898 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4900 if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
4901 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4902 abort ();
4903 result = create_node (sizeof (struct regexp)
4904 + sizeof (regexp_t)
4905 * (REGEXP_SEQUENCE (regexp)->regexps_num
4906 + REGEXP_SEQUENCE (sequence)->regexps_num
4907 - 2));
4908 result->mode = rm_sequence;
4909 result->pos = regexp->pos;
4910 REGEXP_SEQUENCE (result)->regexps_num
4911 = (REGEXP_SEQUENCE (regexp)->regexps_num
4912 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4913 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4914 if (i < sequence_index)
4915 REGEXP_SEQUENCE (result)->regexps [i]
4916 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4917 else if (i > sequence_index)
4918 REGEXP_SEQUENCE (result)->regexps
4919 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4920 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4921 else
4922 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4923 REGEXP_SEQUENCE (result)->regexps [i + j]
4924 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4925 regexp_transformed_p = 1;
4926 regexp = result;
4929 else if (regexp->mode == rm_allof)
4931 regexp_t allof = NULL;
4932 regexp_t result;
4933 int allof_index = 0;
4934 int i, j;
4936 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4937 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4939 allof_index = i;
4940 allof = REGEXP_ALLOF (regexp)->regexps [i];
4941 break;
4943 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4945 if (REGEXP_ALLOF (allof)->regexps_num <= 1
4946 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4947 abort ();
4948 result = create_node (sizeof (struct regexp)
4949 + sizeof (regexp_t)
4950 * (REGEXP_ALLOF (regexp)->regexps_num
4951 + REGEXP_ALLOF (allof)->regexps_num - 2));
4952 result->mode = rm_allof;
4953 result->pos = regexp->pos;
4954 REGEXP_ALLOF (result)->regexps_num
4955 = (REGEXP_ALLOF (regexp)->regexps_num
4956 + REGEXP_ALLOF (allof)->regexps_num - 1);
4957 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4958 if (i < allof_index)
4959 REGEXP_ALLOF (result)->regexps [i]
4960 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4961 else if (i > allof_index)
4962 REGEXP_ALLOF (result)->regexps
4963 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4964 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4965 else
4966 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4967 REGEXP_ALLOF (result)->regexps [i + j]
4968 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4969 regexp_transformed_p = 1;
4970 regexp = result;
4973 else if (regexp->mode == rm_oneof)
4975 regexp_t oneof = NULL;
4976 regexp_t result;
4977 int oneof_index = 0;
4978 int i, j;
4980 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4981 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4983 oneof_index = i;
4984 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4985 break;
4987 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4989 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4990 || REGEXP_ONEOF (regexp)->regexps_num <= 1)
4991 abort ();
4992 result = create_node (sizeof (struct regexp)
4993 + sizeof (regexp_t)
4994 * (REGEXP_ONEOF (regexp)->regexps_num
4995 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4996 result->mode = rm_oneof;
4997 result->pos = regexp->pos;
4998 REGEXP_ONEOF (result)->regexps_num
4999 = (REGEXP_ONEOF (regexp)->regexps_num
5000 + REGEXP_ONEOF (oneof)->regexps_num - 1);
5001 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5002 if (i < oneof_index)
5003 REGEXP_ONEOF (result)->regexps [i]
5004 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
5005 else if (i > oneof_index)
5006 REGEXP_ONEOF (result)->regexps
5007 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
5008 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
5009 else
5010 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
5011 REGEXP_ONEOF (result)->regexps [i + j]
5012 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
5013 regexp_transformed_p = 1;
5014 regexp = result;
5017 return regexp;
5020 /* The function makes transformations
5021 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
5022 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
5023 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
5024 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
5025 static regexp_t
5026 transform_3 (regexp_t regexp)
5028 if (regexp->mode == rm_sequence)
5030 regexp_t oneof = NULL;
5031 int oneof_index = 0;
5032 regexp_t result;
5033 regexp_t sequence;
5034 int i, j;
5036 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5037 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
5039 oneof_index = i;
5040 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
5041 break;
5043 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
5045 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5046 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
5047 abort ();
5048 result = create_node (sizeof (struct regexp)
5049 + sizeof (regexp_t)
5050 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5051 result->mode = rm_oneof;
5052 result->pos = regexp->pos;
5053 REGEXP_ONEOF (result)->regexps_num
5054 = REGEXP_ONEOF (oneof)->regexps_num;
5055 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5057 sequence
5058 = create_node (sizeof (struct regexp)
5059 + sizeof (regexp_t)
5060 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
5061 sequence->mode = rm_sequence;
5062 sequence->pos = regexp->pos;
5063 REGEXP_SEQUENCE (sequence)->regexps_num
5064 = REGEXP_SEQUENCE (regexp)->regexps_num;
5065 REGEXP_ONEOF (result)->regexps [i] = sequence;
5066 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
5067 if (j != oneof_index)
5068 REGEXP_SEQUENCE (sequence)->regexps [j]
5069 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
5070 else
5071 REGEXP_SEQUENCE (sequence)->regexps [j]
5072 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5074 regexp_transformed_p = 1;
5075 regexp = result;
5078 else if (regexp->mode == rm_allof)
5080 regexp_t oneof = NULL;
5081 regexp_t seq;
5082 int oneof_index = 0;
5083 int max_seq_length, allof_length;
5084 regexp_t result;
5085 regexp_t allof = NULL;
5086 regexp_t allof_op = NULL;
5087 int i, j;
5089 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5090 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
5092 oneof_index = i;
5093 oneof = REGEXP_ALLOF (regexp)->regexps [i];
5094 break;
5096 if (i < REGEXP_ALLOF (regexp)->regexps_num)
5098 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5099 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5100 abort ();
5101 result = create_node (sizeof (struct regexp)
5102 + sizeof (regexp_t)
5103 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5104 result->mode = rm_oneof;
5105 result->pos = regexp->pos;
5106 REGEXP_ONEOF (result)->regexps_num
5107 = REGEXP_ONEOF (oneof)->regexps_num;
5108 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5110 allof
5111 = create_node (sizeof (struct regexp)
5112 + sizeof (regexp_t)
5113 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
5114 allof->mode = rm_allof;
5115 allof->pos = regexp->pos;
5116 REGEXP_ALLOF (allof)->regexps_num
5117 = REGEXP_ALLOF (regexp)->regexps_num;
5118 REGEXP_ONEOF (result)->regexps [i] = allof;
5119 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
5120 if (j != oneof_index)
5121 REGEXP_ALLOF (allof)->regexps [j]
5122 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
5123 else
5124 REGEXP_ALLOF (allof)->regexps [j]
5125 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5127 regexp_transformed_p = 1;
5128 regexp = result;
5130 max_seq_length = 0;
5131 if (regexp->mode == rm_allof)
5132 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5134 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
5136 seq = REGEXP_ALLOF (regexp)->regexps [i];
5137 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
5138 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
5140 else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit
5141 && REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_nothing)
5143 max_seq_length = 0;
5144 break;
5147 if (max_seq_length != 0)
5149 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5150 abort ();
5151 result = create_node (sizeof (struct regexp)
5152 + sizeof (regexp_t) * (max_seq_length - 1));
5153 result->mode = rm_sequence;
5154 result->pos = regexp->pos;
5155 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5156 for (i = 0; i < max_seq_length; i++)
5158 allof_length = 0;
5159 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5160 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5161 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5162 ->regexps [j])->regexps_num)))
5164 allof_op
5165 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5166 ->regexps [i]);
5167 allof_length++;
5169 else if (i == 0
5170 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5171 == rm_unit
5172 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5173 == rm_nothing)))
5175 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5176 allof_length++;
5178 if (allof_length == 1)
5179 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5180 else
5182 allof = create_node (sizeof (struct regexp)
5183 + sizeof (regexp_t)
5184 * (allof_length - 1));
5185 allof->mode = rm_allof;
5186 allof->pos = regexp->pos;
5187 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5188 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5189 allof_length = 0;
5190 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5191 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5192 && (i <
5193 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5194 ->regexps [j])->regexps_num)))
5196 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5197 ->regexps [j])
5198 ->regexps [i]);
5199 REGEXP_ALLOF (allof)->regexps [allof_length]
5200 = allof_op;
5201 allof_length++;
5203 else if (i == 0
5204 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5205 == rm_unit
5206 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5207 == rm_nothing)))
5209 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5210 REGEXP_ALLOF (allof)->regexps [allof_length]
5211 = allof_op;
5212 allof_length++;
5216 regexp_transformed_p = 1;
5217 regexp = result;
5220 return regexp;
5223 /* The function traverses IR of reservation and applies transformations
5224 implemented by FUNC. */
5225 static regexp_t
5226 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
5228 int i;
5230 if (regexp->mode == rm_sequence)
5231 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5232 REGEXP_SEQUENCE (regexp)->regexps [i]
5233 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5234 else if (regexp->mode == rm_allof)
5235 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5236 REGEXP_ALLOF (regexp)->regexps [i]
5237 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5238 else if (regexp->mode == rm_oneof)
5239 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5240 REGEXP_ONEOF (regexp)->regexps [i]
5241 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5242 else if (regexp->mode == rm_repeat)
5243 REGEXP_REPEAT (regexp)->regexp
5244 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5245 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5246 abort ();
5247 return (*func) (regexp);
5250 /* The function applies all transformations for IR representation of
5251 reservation REGEXP. */
5252 static regexp_t
5253 transform_regexp (regexp_t regexp)
5255 regexp = regexp_transform_func (regexp, transform_1);
5258 regexp_transformed_p = 0;
5259 regexp = regexp_transform_func (regexp, transform_2);
5260 regexp = regexp_transform_func (regexp, transform_3);
5262 while (regexp_transformed_p);
5263 return regexp;
5266 /* The function applies all transformations for reservations of all
5267 insn declarations. */
5268 static void
5269 transform_insn_regexps (void)
5271 decl_t decl;
5272 int i;
5274 transform_time = create_ticker ();
5275 add_advance_cycle_insn_decl ();
5276 if (progress_flag)
5277 fprintf (stderr, "Reservation transformation...");
5278 for (i = 0; i < description->decls_num; i++)
5280 decl = description->decls [i];
5281 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5282 DECL_INSN_RESERV (decl)->transformed_regexp
5283 = transform_regexp (copy_insn_regexp
5284 (DECL_INSN_RESERV (decl)->regexp));
5286 if (progress_flag)
5287 fprintf (stderr, "done\n");
5288 ticker_off (&transform_time);
5293 /* The following variable value is TRUE if the first annotated message
5294 about units to automata distribution has been output. */
5295 static int annotation_message_reported_p;
5297 /* The following structure describes usage of a unit in a reservation. */
5298 struct unit_usage
5300 unit_decl_t unit_decl;
5301 /* The following forms a list of units used on the same cycle in the
5302 same alternative. */
5303 struct unit_usage *next;
5306 /* Obstack for unit_usage structures. */
5307 static struct obstack unit_usages;
5309 /* VLA for representation of array of pointers to unit usage
5310 structures. There is an element for each combination of
5311 (alternative number, cycle). Unit usages on given cycle in
5312 alternative with given number are referred through element with
5313 index equals to the cycle * number of all alternatives in the regexp
5314 + the alternative number. */
5315 static vla_ptr_t cycle_alt_unit_usages;
5317 /* The following function creates the structure unit_usage for UNIT on
5318 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5319 accessed through cycle_alt_unit_usages. */
5320 static void
5321 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
5322 int alt_num)
5324 size_t i, length, old_length;
5325 unit_decl_t unit_decl;
5326 struct unit_usage *unit_usage_ptr;
5327 int index;
5329 if (regexp == NULL || regexp->mode != rm_oneof
5330 || alt_num >= REGEXP_ONEOF (regexp)->regexps_num)
5331 abort ();
5332 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5333 old_length = VLA_PTR_LENGTH (cycle_alt_unit_usages);
5334 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
5335 if (old_length < length)
5337 VLA_PTR_EXPAND (cycle_alt_unit_usages, length - old_length);
5338 for (i = old_length; i < length; i++)
5339 VLA_PTR (cycle_alt_unit_usages, i) = NULL;
5341 obstack_blank (&unit_usages, sizeof (struct unit_usage));
5342 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5343 obstack_finish (&unit_usages);
5344 unit_usage_ptr->unit_decl = unit_decl;
5345 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5346 unit_usage_ptr->next = VLA_PTR (cycle_alt_unit_usages, index);
5347 VLA_PTR (cycle_alt_unit_usages, index) = unit_usage_ptr;
5348 unit_decl->last_distribution_check_cycle = -1; /* undefined */
5351 /* The function processes given REGEXP to find units with the wrong
5352 distribution. */
5353 static void
5354 check_regexp_units_distribution (const char *insn_reserv_name,
5355 regexp_t regexp)
5357 int i, j, k, cycle;
5358 regexp_t seq, allof, unit;
5359 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
5361 if (regexp == NULL || regexp->mode != rm_oneof)
5362 return;
5363 /* Store all unit usages in the regexp: */
5364 obstack_init (&unit_usages);
5365 VLA_PTR_CREATE (cycle_alt_unit_usages, 100, "unit usages on cycles");
5366 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5368 seq = REGEXP_ONEOF (regexp)->regexps [i];
5369 if (seq->mode == rm_sequence)
5370 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5372 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5373 if (allof->mode == rm_allof)
5374 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5376 unit = REGEXP_ALLOF (allof)->regexps [k];
5377 if (unit->mode == rm_unit)
5378 store_alt_unit_usage (regexp, unit, j, i);
5379 else if (unit->mode != rm_nothing)
5380 abort ();
5382 else if (allof->mode == rm_unit)
5383 store_alt_unit_usage (regexp, allof, j, i);
5384 else if (allof->mode != rm_nothing)
5385 abort ();
5387 else if (seq->mode == rm_allof)
5388 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5390 unit = REGEXP_ALLOF (seq)->regexps [k];
5391 if (unit->mode == rm_unit)
5392 store_alt_unit_usage (regexp, unit, 0, i);
5393 else if (unit->mode != rm_nothing)
5394 abort ();
5396 else if (seq->mode == rm_unit)
5397 store_alt_unit_usage (regexp, seq, 0, i);
5398 else if (seq->mode != rm_nothing)
5399 abort ();
5401 /* Check distribution: */
5402 for (i = 0; i < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages); i++)
5404 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5405 for (unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages, i);
5406 unit_usage_ptr != NULL;
5407 unit_usage_ptr = unit_usage_ptr->next)
5408 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5410 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5411 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5412 k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages)
5413 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5414 k++)
5416 for (other_unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages, k);
5417 other_unit_usage_ptr != NULL;
5418 other_unit_usage_ptr = other_unit_usage_ptr->next)
5419 if (unit_usage_ptr->unit_decl->automaton_decl
5420 == other_unit_usage_ptr->unit_decl->automaton_decl)
5421 break;
5422 if (other_unit_usage_ptr == NULL
5423 && VLA_PTR (cycle_alt_unit_usages, k) != NULL)
5424 break;
5426 if (k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages)
5427 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5429 if (!annotation_message_reported_p)
5431 fprintf (stderr, "\n");
5432 error ("The following units do not satisfy units-automata distribution rule");
5433 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5434 annotation_message_reported_p = TRUE;
5436 error ("Unit %s, reserv. %s, cycle %d",
5437 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5438 cycle);
5442 VLA_PTR_DELETE (cycle_alt_unit_usages);
5443 obstack_free (&unit_usages, NULL);
5446 /* The function finds units which violates units to automata
5447 distribution rule. If the units exist, report about them. */
5448 static void
5449 check_unit_distributions_to_automata (void)
5451 decl_t decl;
5452 int i;
5454 if (progress_flag)
5455 fprintf (stderr, "Check unit distributions to automata...");
5456 annotation_message_reported_p = FALSE;
5457 for (i = 0; i < description->decls_num; i++)
5459 decl = description->decls [i];
5460 if (decl->mode == dm_insn_reserv)
5461 check_regexp_units_distribution
5462 (DECL_INSN_RESERV (decl)->name,
5463 DECL_INSN_RESERV (decl)->transformed_regexp);
5465 if (progress_flag)
5466 fprintf (stderr, "done\n");
5471 /* The page contains code for building alt_states (see comments for
5472 IR) describing all possible insns reservations of an automaton. */
5474 /* Current state being formed for which the current alt_state
5475 refers. */
5476 static state_t state_being_formed;
5478 /* Current alt_state being formed. */
5479 static alt_state_t alt_state_being_formed;
5481 /* This recursive function processes `,' and units in reservation
5482 REGEXP for forming alt_states of AUTOMATON. It is believed that
5483 CURR_CYCLE is start cycle of all reservation REGEXP. */
5484 static int
5485 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5486 int curr_cycle)
5488 int i;
5490 if (regexp == NULL)
5491 return curr_cycle;
5492 else if (regexp->mode == rm_unit)
5494 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5495 == automaton->automaton_order_num)
5496 set_state_reserv (state_being_formed, curr_cycle,
5497 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5498 return curr_cycle;
5500 else if (regexp->mode == rm_sequence)
5502 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5503 curr_cycle
5504 = process_seq_for_forming_states
5505 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5506 return curr_cycle;
5508 else if (regexp->mode == rm_allof)
5510 int finish_cycle = 0;
5511 int cycle;
5513 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5515 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5516 ->regexps [i],
5517 automaton, curr_cycle);
5518 if (finish_cycle < cycle)
5519 finish_cycle = cycle;
5521 return finish_cycle;
5523 else
5525 if (regexp->mode != rm_nothing)
5526 abort ();
5527 return curr_cycle;
5531 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5532 inserts alt_state into the table. */
5533 static void
5534 finish_forming_alt_state (alt_state_t alt_state,
5535 automaton_t automaton ATTRIBUTE_UNUSED)
5537 state_t state_in_table;
5538 state_t corresponding_state;
5540 corresponding_state = alt_state->state;
5541 state_in_table = insert_state (corresponding_state);
5542 if (state_in_table != corresponding_state)
5544 free_state (corresponding_state);
5545 alt_state->state = state_in_table;
5549 /* The following variable value is current automaton insn for whose
5550 reservation the alt states are created. */
5551 static ainsn_t curr_ainsn;
5553 /* This recursive function processes `|' in reservation REGEXP for
5554 forming alt_states of AUTOMATON. List of the alt states should
5555 have the same order as in the description. */
5556 static void
5557 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5558 int inside_oneof_p)
5560 int i;
5562 if (regexp->mode != rm_oneof)
5564 alt_state_being_formed = get_free_alt_state ();
5565 state_being_formed = get_free_state (1, automaton);
5566 alt_state_being_formed->state = state_being_formed;
5567 /* We inserts in reverse order but we process alternatives also
5568 in reverse order. So we have the same order of alternative
5569 as in the description. */
5570 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5571 curr_ainsn->alt_states = alt_state_being_formed;
5572 (void) process_seq_for_forming_states (regexp, automaton, 0);
5573 finish_forming_alt_state (alt_state_being_formed, automaton);
5575 else
5577 if (inside_oneof_p)
5578 abort ();
5579 /* We processes it in reverse order to get list with the same
5580 order as in the description. See also the previous
5581 commentary. */
5582 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5583 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5584 automaton, 1);
5588 /* Create nodes alt_state for all AUTOMATON insns. */
5589 static void
5590 create_alt_states (automaton_t automaton)
5592 struct insn_reserv_decl *reserv_decl;
5594 for (curr_ainsn = automaton->ainsn_list;
5595 curr_ainsn != NULL;
5596 curr_ainsn = curr_ainsn->next_ainsn)
5598 reserv_decl = curr_ainsn->insn_reserv_decl;
5599 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5601 curr_ainsn->alt_states = NULL;
5602 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5603 automaton, 0);
5604 curr_ainsn->sorted_alt_states
5605 = uniq_sort_alt_states (curr_ainsn->alt_states);
5612 /* The page contains major code for building DFA(s) for fast pipeline
5613 hazards recognition. */
5615 /* The function forms list of ainsns of AUTOMATON with the same
5616 reservation. */
5617 static void
5618 form_ainsn_with_same_reservs (automaton_t automaton)
5620 ainsn_t curr_ainsn;
5621 size_t i;
5622 vla_ptr_t first_insns;
5623 vla_ptr_t last_insns;
5625 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5626 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5627 for (curr_ainsn = automaton->ainsn_list;
5628 curr_ainsn != NULL;
5629 curr_ainsn = curr_ainsn->next_ainsn)
5630 if (curr_ainsn->insn_reserv_decl
5631 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5633 curr_ainsn->next_same_reservs_insn = NULL;
5634 curr_ainsn->first_insn_with_same_reservs = 1;
5636 else
5638 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5639 if (alt_states_eq
5640 (curr_ainsn->sorted_alt_states,
5641 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5642 break;
5643 curr_ainsn->next_same_reservs_insn = NULL;
5644 if (i < VLA_PTR_LENGTH (first_insns))
5646 curr_ainsn->first_insn_with_same_reservs = 0;
5647 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5648 = curr_ainsn;
5649 VLA_PTR (last_insns, i) = curr_ainsn;
5651 else
5653 VLA_PTR_ADD (first_insns, curr_ainsn);
5654 VLA_PTR_ADD (last_insns, curr_ainsn);
5655 curr_ainsn->first_insn_with_same_reservs = 1;
5658 VLA_PTR_DELETE (first_insns);
5659 VLA_PTR_DELETE (last_insns);
5662 /* Forming unit reservations which can affect creating the automaton
5663 states achieved from a given state. It permits to build smaller
5664 automata in many cases. We would have the same automata after
5665 the minimization without such optimization, but the automaton
5666 right after the building could be huge. So in other words, usage
5667 of reservs_matter means some minimization during building the
5668 automaton. */
5669 static reserv_sets_t
5670 form_reservs_matter (automaton_t automaton)
5672 int cycle, unit;
5673 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5675 for (cycle = 0; cycle < max_cycles_num; cycle++)
5676 for (unit = 0; unit < description->units_num; unit++)
5677 if (units_array [unit]->automaton_decl
5678 == automaton->corresponding_automaton_decl
5679 && (cycle >= units_array [unit]->min_occ_cycle_num
5680 /* We can not remove queried unit from reservations. */
5681 || units_array [unit]->query_p
5682 /* We can not remove units which are used
5683 `exclusion_set', `presence_set',
5684 `final_presence_set', `absence_set', and
5685 `final_absence_set'. */
5686 || units_array [unit]->in_set_p))
5687 set_unit_reserv (reservs_matter, cycle, unit);
5688 return reservs_matter;
5691 /* The following function creates all states of nondeterministic (if
5692 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5693 static void
5694 make_automaton (automaton_t automaton)
5696 ainsn_t ainsn;
5697 struct insn_reserv_decl *insn_reserv_decl;
5698 alt_state_t alt_state;
5699 state_t state;
5700 state_t start_state;
5701 state_t state2;
5702 ainsn_t advance_cycle_ainsn;
5703 arc_t added_arc;
5704 vla_ptr_t state_stack;
5705 int states_n;
5706 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5708 VLA_PTR_CREATE (state_stack, 150, "state stack");
5709 /* Create the start state (empty state). */
5710 start_state = insert_state (get_free_state (1, automaton));
5711 automaton->start_state = start_state;
5712 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5713 VLA_PTR_ADD (state_stack, start_state);
5714 states_n = 1;
5715 while (VLA_PTR_LENGTH (state_stack) != 0)
5717 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5718 VLA_PTR_SHORTEN (state_stack, 1);
5719 advance_cycle_ainsn = NULL;
5720 for (ainsn = automaton->ainsn_list;
5721 ainsn != NULL;
5722 ainsn = ainsn->next_ainsn)
5723 if (ainsn->first_insn_with_same_reservs)
5725 insn_reserv_decl = ainsn->insn_reserv_decl;
5726 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5728 /* We process alt_states in the same order as they are
5729 present in the description. */
5730 added_arc = NULL;
5731 for (alt_state = ainsn->alt_states;
5732 alt_state != NULL;
5733 alt_state = alt_state->next_alt_state)
5735 state2 = alt_state->state;
5736 if (!intersected_state_reservs_p (state, state2))
5738 state2 = states_union (state, state2, reservs_matter);
5739 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5741 state2->it_was_placed_in_stack_for_NDFA_forming
5742 = 1;
5743 VLA_PTR_ADD (state_stack, state2);
5744 states_n++;
5745 if (progress_flag && states_n % 100 == 0)
5746 fprintf (stderr, ".");
5748 added_arc = add_arc (state, state2, ainsn, 1);
5749 if (!ndfa_flag)
5750 break;
5753 if (!ndfa_flag && added_arc != NULL)
5755 added_arc->state_alts = 0;
5756 for (alt_state = ainsn->alt_states;
5757 alt_state != NULL;
5758 alt_state = alt_state->next_alt_state)
5760 state2 = alt_state->state;
5761 if (!intersected_state_reservs_p (state, state2))
5762 added_arc->state_alts++;
5766 else
5767 advance_cycle_ainsn = ainsn;
5769 /* Add transition to advance cycle. */
5770 state2 = state_shift (state, reservs_matter);
5771 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5773 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5774 VLA_PTR_ADD (state_stack, state2);
5775 states_n++;
5776 if (progress_flag && states_n % 100 == 0)
5777 fprintf (stderr, ".");
5779 if (advance_cycle_ainsn == NULL)
5780 abort ();
5781 add_arc (state, state2, advance_cycle_ainsn, 1);
5783 VLA_PTR_DELETE (state_stack);
5786 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5787 static void
5788 form_arcs_marked_by_insn (state_t state)
5790 decl_t decl;
5791 arc_t arc;
5792 int i;
5794 for (i = 0; i < description->decls_num; i++)
5796 decl = description->decls [i];
5797 if (decl->mode == dm_insn_reserv)
5798 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5800 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5802 if (arc->insn == NULL)
5803 abort ();
5804 arc->next_arc_marked_by_insn
5805 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5806 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5810 /* The function creates composed state (see comments for IR) from
5811 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5812 same insn. If the composed state is not in STATE_STACK yet, it is
5813 pushed into STATE_STACK. */
5814 static int
5815 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5816 vla_ptr_t *state_stack)
5818 state_t state;
5819 alt_state_t alt_state, curr_alt_state;
5820 alt_state_t new_alt_state;
5821 arc_t curr_arc;
5822 arc_t next_arc;
5823 state_t state_in_table;
5824 state_t temp_state;
5825 alt_state_t canonical_alt_states_list;
5826 int alts_number;
5827 int new_state_p = 0;
5829 if (arcs_marked_by_insn == NULL)
5830 return new_state_p;
5831 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5832 state = arcs_marked_by_insn->to_state;
5833 else
5835 if (!ndfa_flag)
5836 abort ();
5837 /* Create composed state. */
5838 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5839 curr_alt_state = NULL;
5840 for (curr_arc = arcs_marked_by_insn;
5841 curr_arc != NULL;
5842 curr_arc = curr_arc->next_arc_marked_by_insn)
5843 if (curr_arc->to_state->component_states == NULL)
5845 new_alt_state = get_free_alt_state ();
5846 new_alt_state->next_alt_state = curr_alt_state;
5847 new_alt_state->state = curr_arc->to_state;
5848 curr_alt_state = new_alt_state;
5850 else
5851 for (alt_state = curr_arc->to_state->component_states;
5852 alt_state != NULL;
5853 alt_state = alt_state->next_sorted_alt_state)
5855 new_alt_state = get_free_alt_state ();
5856 new_alt_state->next_alt_state = curr_alt_state;
5857 new_alt_state->state = alt_state->state;
5858 if (alt_state->state->component_states != NULL)
5859 abort ();
5860 curr_alt_state = new_alt_state;
5862 /* There are not identical sets in the alt state list. */
5863 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5864 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5866 temp_state = state;
5867 state = canonical_alt_states_list->state;
5868 free_state (temp_state);
5870 else
5872 state->component_states = canonical_alt_states_list;
5873 state_in_table = insert_state (state);
5874 if (state_in_table != state)
5876 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5877 abort ();
5878 free_state (state);
5879 state = state_in_table;
5881 else
5883 if (state->it_was_placed_in_stack_for_DFA_forming)
5884 abort ();
5885 new_state_p = 1;
5886 for (curr_alt_state = state->component_states;
5887 curr_alt_state != NULL;
5888 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5889 for (curr_arc = first_out_arc (curr_alt_state->state);
5890 curr_arc != NULL;
5891 curr_arc = next_out_arc (curr_arc))
5892 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5894 arcs_marked_by_insn->to_state = state;
5895 for (alts_number = 0,
5896 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5897 curr_arc != NULL;
5898 curr_arc = next_arc)
5900 next_arc = curr_arc->next_arc_marked_by_insn;
5901 remove_arc (original_state, curr_arc);
5902 alts_number++;
5904 arcs_marked_by_insn->state_alts = alts_number;
5907 if (!state->it_was_placed_in_stack_for_DFA_forming)
5909 state->it_was_placed_in_stack_for_DFA_forming = 1;
5910 VLA_PTR_ADD (*state_stack, state);
5912 return new_state_p;
5915 /* The function transforms nondeterministic AUTOMATON into
5916 deterministic. */
5917 static void
5918 NDFA_to_DFA (automaton_t automaton)
5920 state_t start_state;
5921 state_t state;
5922 decl_t decl;
5923 vla_ptr_t state_stack;
5924 int i;
5925 int states_n;
5927 VLA_PTR_CREATE (state_stack, 150, "state stack");
5928 /* Create the start state (empty state). */
5929 start_state = automaton->start_state;
5930 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5931 VLA_PTR_ADD (state_stack, start_state);
5932 states_n = 1;
5933 while (VLA_PTR_LENGTH (state_stack) != 0)
5935 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5936 VLA_PTR_SHORTEN (state_stack, 1);
5937 form_arcs_marked_by_insn (state);
5938 for (i = 0; i < description->decls_num; i++)
5940 decl = description->decls [i];
5941 if (decl->mode == dm_insn_reserv
5942 && create_composed_state
5943 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5944 &state_stack))
5946 states_n++;
5947 if (progress_flag && states_n % 100 == 0)
5948 fprintf (stderr, ".");
5952 VLA_PTR_DELETE (state_stack);
5955 /* The following variable value is current number (1, 2, ...) of passing
5956 graph of states. */
5957 static int curr_state_graph_pass_num;
5959 /* This recursive function passes all states achieved from START_STATE
5960 and applies APPLIED_FUNC to them. */
5961 static void
5962 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5964 arc_t arc;
5966 if (start_state->pass_num == curr_state_graph_pass_num)
5967 return;
5968 start_state->pass_num = curr_state_graph_pass_num;
5969 (*applied_func) (start_state);
5970 for (arc = first_out_arc (start_state);
5971 arc != NULL;
5972 arc = next_out_arc (arc))
5973 pass_state_graph (arc->to_state, applied_func);
5976 /* This recursive function passes all states of AUTOMATON and applies
5977 APPLIED_FUNC to them. */
5978 static void
5979 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5981 curr_state_graph_pass_num++;
5982 pass_state_graph (automaton->start_state, applied_func);
5985 /* The function initializes code for passing of all states. */
5986 static void
5987 initiate_pass_states (void)
5989 curr_state_graph_pass_num = 0;
5992 /* The following vla is used for storing pointers to all achieved
5993 states. */
5994 static vla_ptr_t all_achieved_states;
5996 /* This function is called by function pass_states to add an achieved
5997 STATE. */
5998 static void
5999 add_achieved_state (state_t state)
6001 VLA_PTR_ADD (all_achieved_states, state);
6004 /* The function sets up equivalence numbers of insns which mark all
6005 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
6006 nonzero value) or by equiv_class_num_2 of the destination state.
6007 The function returns number of out arcs of STATE. */
6008 static int
6009 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
6011 int state_out_arcs_num;
6012 arc_t arc;
6014 state_out_arcs_num = 0;
6015 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6017 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
6018 || arc->insn->insn_reserv_decl->state_alts != 0)
6019 abort ();
6020 state_out_arcs_num++;
6021 arc->insn->insn_reserv_decl->equiv_class_num
6022 = (odd_iteration_flag
6023 ? arc->to_state->equiv_class_num_1
6024 : arc->to_state->equiv_class_num_2);
6025 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
6026 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
6027 || arc->insn->insn_reserv_decl->state_alts <= 0)
6028 abort ();
6030 return state_out_arcs_num;
6033 /* The function clears equivalence numbers and alt_states in all insns
6034 which mark all out arcs of STATE. */
6035 static void
6036 clear_arc_insns_equiv_num (state_t state)
6038 arc_t arc;
6040 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6042 arc->insn->insn_reserv_decl->equiv_class_num = 0;
6043 arc->insn->insn_reserv_decl->state_alts = 0;
6047 /* The function copies pointers to equivalent states from vla FROM
6048 into vla TO. */
6049 static void
6050 copy_equiv_class (vla_ptr_t *to, const vla_ptr_t *from)
6052 state_t *class_ptr;
6054 VLA_PTR_NULLIFY (*to);
6055 for (class_ptr = VLA_PTR_BEGIN (*from);
6056 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
6057 class_ptr++)
6058 VLA_PTR_ADD (*to, *class_ptr);
6061 /* The following function returns TRUE if STATE reserves the unit with
6062 UNIT_NUM on the first cycle. */
6063 static int
6064 first_cycle_unit_presence (state_t state, int unit_num)
6066 int presence_p;
6068 if (state->component_states == NULL)
6069 presence_p = test_unit_reserv (state->reservs, 0, unit_num);
6070 else
6071 presence_p
6072 = test_unit_reserv (state->component_states->state->reservs,
6073 0, unit_num);
6074 return presence_p;
6077 /* The function returns nonzero value if STATE is not equivalent to
6078 ANOTHER_STATE from the same current partition on equivalence
6079 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
6080 output arcs. Iteration of making equivalence partition is defined
6081 by ODD_ITERATION_FLAG. */
6082 static int
6083 state_is_differed (state_t state, state_t another_state,
6084 int another_state_out_arcs_num, int odd_iteration_flag)
6086 arc_t arc;
6087 int state_out_arcs_num;
6088 int i, presence1_p, presence2_p;
6090 state_out_arcs_num = 0;
6091 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6093 state_out_arcs_num++;
6094 if ((odd_iteration_flag
6095 ? arc->to_state->equiv_class_num_1
6096 : arc->to_state->equiv_class_num_2)
6097 != arc->insn->insn_reserv_decl->equiv_class_num
6098 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
6099 return 1;
6101 if (state_out_arcs_num != another_state_out_arcs_num)
6102 return 1;
6103 /* Now we are looking at the states with the point of view of query
6104 units. */
6105 for (i = 0; i < description->units_num; i++)
6106 if (units_array [i]->query_p)
6108 presence1_p = first_cycle_unit_presence (state, i);
6109 presence2_p = first_cycle_unit_presence (another_state, i);
6110 if ((presence1_p && !presence2_p) || (!presence1_p && presence2_p))
6111 return 1;
6113 return 0;
6116 /* The function makes initial partition of STATES on equivalent
6117 classes. */
6118 static state_t
6119 init_equiv_class (state_t *states, int states_num)
6121 state_t *state_ptr;
6122 state_t result_equiv_class;
6124 result_equiv_class = NULL;
6125 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
6127 (*state_ptr)->equiv_class_num_1 = 1;
6128 (*state_ptr)->next_equiv_class_state = result_equiv_class;
6129 result_equiv_class = *state_ptr;
6131 return result_equiv_class;
6134 /* The function processes equivalence class given by its pointer
6135 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
6136 are not equivalent states, the function partitions the class
6137 removing nonequivalent states and placing them in
6138 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6139 assigns it to the state equivalence number. If the class has been
6140 partitioned, the function returns nonzero value. */
6141 static int
6142 partition_equiv_class (state_t *equiv_class_ptr, int odd_iteration_flag,
6143 vla_ptr_t *next_iteration_classes,
6144 int *new_equiv_class_num_ptr)
6146 state_t new_equiv_class;
6147 int partition_p;
6148 state_t first_state;
6149 state_t curr_state;
6150 state_t prev_state;
6151 state_t next_state;
6152 int out_arcs_num;
6154 partition_p = 0;
6155 if (*equiv_class_ptr == NULL)
6156 abort ();
6157 for (first_state = *equiv_class_ptr;
6158 first_state != NULL;
6159 first_state = new_equiv_class)
6161 new_equiv_class = NULL;
6162 if (first_state->next_equiv_class_state != NULL)
6164 /* There are more one states in the class equivalence. */
6165 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
6166 odd_iteration_flag);
6167 for (prev_state = first_state,
6168 curr_state = first_state->next_equiv_class_state;
6169 curr_state != NULL;
6170 curr_state = next_state)
6172 next_state = curr_state->next_equiv_class_state;
6173 if (state_is_differed (curr_state, first_state, out_arcs_num,
6174 odd_iteration_flag))
6176 /* Remove curr state from the class equivalence. */
6177 prev_state->next_equiv_class_state = next_state;
6178 /* Add curr state to the new class equivalence. */
6179 curr_state->next_equiv_class_state = new_equiv_class;
6180 if (new_equiv_class == NULL)
6181 (*new_equiv_class_num_ptr)++;
6182 if (odd_iteration_flag)
6183 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6184 else
6185 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6186 new_equiv_class = curr_state;
6187 partition_p = 1;
6189 else
6190 prev_state = curr_state;
6192 clear_arc_insns_equiv_num (first_state);
6194 if (new_equiv_class != NULL)
6195 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
6197 return partition_p;
6200 /* The function finds equivalent states of AUTOMATON. */
6201 static void
6202 evaluate_equiv_classes (automaton_t automaton, vla_ptr_t *equiv_classes)
6204 state_t new_equiv_class;
6205 int new_equiv_class_num;
6206 int odd_iteration_flag;
6207 int finish_flag;
6208 vla_ptr_t next_iteration_classes;
6209 state_t *equiv_class_ptr;
6210 state_t *state_ptr;
6212 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6213 pass_states (automaton, add_achieved_state);
6214 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6215 VLA_PTR_LENGTH (all_achieved_states));
6216 odd_iteration_flag = 0;
6217 new_equiv_class_num = 1;
6218 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6219 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6222 odd_iteration_flag = !odd_iteration_flag;
6223 finish_flag = 1;
6224 copy_equiv_class (equiv_classes, &next_iteration_classes);
6225 /* Transfer equiv numbers for the next iteration. */
6226 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6227 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6228 state_ptr++)
6229 if (odd_iteration_flag)
6230 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6231 else
6232 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6233 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6234 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6235 equiv_class_ptr++)
6236 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6237 &next_iteration_classes,
6238 &new_equiv_class_num))
6239 finish_flag = 0;
6241 while (!finish_flag);
6242 VLA_PTR_DELETE (next_iteration_classes);
6243 VLA_PTR_DELETE (all_achieved_states);
6246 /* The function merges equivalent states of AUTOMATON. */
6247 static void
6248 merge_states (automaton_t automaton, vla_ptr_t *equiv_classes)
6250 state_t *equiv_class_ptr;
6251 state_t curr_state;
6252 state_t new_state;
6253 state_t first_class_state;
6254 alt_state_t alt_states;
6255 alt_state_t alt_state, new_alt_state;
6256 arc_t curr_arc;
6257 arc_t next_arc;
6259 /* Create states corresponding to equivalence classes containing two
6260 or more states. */
6261 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6262 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6263 equiv_class_ptr++)
6264 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6266 /* There are more one states in the class equivalence. */
6267 /* Create new compound state. */
6268 new_state = get_free_state (0, automaton);
6269 alt_states = NULL;
6270 first_class_state = *equiv_class_ptr;
6271 for (curr_state = first_class_state;
6272 curr_state != NULL;
6273 curr_state = curr_state->next_equiv_class_state)
6275 curr_state->equiv_class_state = new_state;
6276 if (curr_state->component_states == NULL)
6278 new_alt_state = get_free_alt_state ();
6279 new_alt_state->state = curr_state;
6280 new_alt_state->next_alt_state = alt_states;
6281 alt_states = new_alt_state;
6283 else
6284 for (alt_state = curr_state->component_states;
6285 alt_state != NULL;
6286 alt_state = alt_state->next_sorted_alt_state)
6288 new_alt_state = get_free_alt_state ();
6289 new_alt_state->state = alt_state->state;
6290 new_alt_state->next_alt_state = alt_states;
6291 alt_states = new_alt_state;
6294 /* Its is important that alt states were sorted before and
6295 after merging to have the same querying results. */
6296 new_state->component_states = uniq_sort_alt_states (alt_states);
6298 else
6299 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6300 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6301 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6302 equiv_class_ptr++)
6303 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6305 first_class_state = *equiv_class_ptr;
6306 /* Create new arcs output from the state corresponding to
6307 equiv class. */
6308 for (curr_arc = first_out_arc (first_class_state);
6309 curr_arc != NULL;
6310 curr_arc = next_out_arc (curr_arc))
6311 add_arc (first_class_state->equiv_class_state,
6312 curr_arc->to_state->equiv_class_state,
6313 curr_arc->insn, curr_arc->state_alts);
6314 /* Delete output arcs from states of given class equivalence. */
6315 for (curr_state = first_class_state;
6316 curr_state != NULL;
6317 curr_state = curr_state->next_equiv_class_state)
6319 if (automaton->start_state == curr_state)
6320 automaton->start_state = curr_state->equiv_class_state;
6321 /* Delete the state and its output arcs. */
6322 for (curr_arc = first_out_arc (curr_state);
6323 curr_arc != NULL;
6324 curr_arc = next_arc)
6326 next_arc = next_out_arc (curr_arc);
6327 free_arc (curr_arc);
6331 else
6333 /* Change `to_state' of arcs output from the state of given
6334 equivalence class. */
6335 for (curr_arc = first_out_arc (*equiv_class_ptr);
6336 curr_arc != NULL;
6337 curr_arc = next_out_arc (curr_arc))
6338 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6342 /* The function sets up new_cycle_p for states if there is arc to the
6343 state marked by advance_cycle_insn_decl. */
6344 static void
6345 set_new_cycle_flags (state_t state)
6347 arc_t arc;
6349 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6350 if (arc->insn->insn_reserv_decl
6351 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6352 arc->to_state->new_cycle_p = 1;
6355 /* The top level function for minimization of deterministic
6356 AUTOMATON. */
6357 static void
6358 minimize_DFA (automaton_t automaton)
6360 vla_ptr_t equiv_classes;
6362 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6363 evaluate_equiv_classes (automaton, &equiv_classes);
6364 merge_states (automaton, &equiv_classes);
6365 pass_states (automaton, set_new_cycle_flags);
6366 VLA_PTR_DELETE (equiv_classes);
6369 /* Values of two variables are counted number of states and arcs in an
6370 automaton. */
6371 static int curr_counted_states_num;
6372 static int curr_counted_arcs_num;
6374 /* The function is called by function `pass_states' to count states
6375 and arcs of an automaton. */
6376 static void
6377 incr_states_and_arcs_nums (state_t state)
6379 arc_t arc;
6381 curr_counted_states_num++;
6382 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6383 curr_counted_arcs_num++;
6386 /* The function counts states and arcs of AUTOMATON. */
6387 static void
6388 count_states_and_arcs (automaton_t automaton, int *states_num,
6389 int *arcs_num)
6391 curr_counted_states_num = 0;
6392 curr_counted_arcs_num = 0;
6393 pass_states (automaton, incr_states_and_arcs_nums);
6394 *states_num = curr_counted_states_num;
6395 *arcs_num = curr_counted_arcs_num;
6398 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6399 recognition after checking and simplifying IR of the
6400 description. */
6401 static void
6402 build_automaton (automaton_t automaton)
6404 int states_num;
6405 int arcs_num;
6407 ticker_on (&NDFA_time);
6408 if (progress_flag)
6410 if (automaton->corresponding_automaton_decl == NULL)
6411 fprintf (stderr, "Create anonymous automaton");
6412 else
6413 fprintf (stderr, "Create automaton `%s'",
6414 automaton->corresponding_automaton_decl->name);
6415 fprintf (stderr, " (1 dot is 100 new states):");
6417 make_automaton (automaton);
6418 if (progress_flag)
6419 fprintf (stderr, " done\n");
6420 ticker_off (&NDFA_time);
6421 count_states_and_arcs (automaton, &states_num, &arcs_num);
6422 automaton->NDFA_states_num = states_num;
6423 automaton->NDFA_arcs_num = arcs_num;
6424 ticker_on (&NDFA_to_DFA_time);
6425 if (progress_flag)
6427 if (automaton->corresponding_automaton_decl == NULL)
6428 fprintf (stderr, "Make anonymous DFA");
6429 else
6430 fprintf (stderr, "Make DFA `%s'",
6431 automaton->corresponding_automaton_decl->name);
6432 fprintf (stderr, " (1 dot is 100 new states):");
6434 NDFA_to_DFA (automaton);
6435 if (progress_flag)
6436 fprintf (stderr, " done\n");
6437 ticker_off (&NDFA_to_DFA_time);
6438 count_states_and_arcs (automaton, &states_num, &arcs_num);
6439 automaton->DFA_states_num = states_num;
6440 automaton->DFA_arcs_num = arcs_num;
6441 if (!no_minimization_flag)
6443 ticker_on (&minimize_time);
6444 if (progress_flag)
6446 if (automaton->corresponding_automaton_decl == NULL)
6447 fprintf (stderr, "Minimize anonymous DFA...");
6448 else
6449 fprintf (stderr, "Minimize DFA `%s'...",
6450 automaton->corresponding_automaton_decl->name);
6452 minimize_DFA (automaton);
6453 if (progress_flag)
6454 fprintf (stderr, "done\n");
6455 ticker_off (&minimize_time);
6456 count_states_and_arcs (automaton, &states_num, &arcs_num);
6457 automaton->minimal_DFA_states_num = states_num;
6458 automaton->minimal_DFA_arcs_num = arcs_num;
6464 /* The page contains code for enumeration of all states of an automaton. */
6466 /* Variable used for enumeration of all states of an automaton. Its
6467 value is current number of automaton states. */
6468 static int curr_state_order_num;
6470 /* The function is called by function `pass_states' for enumerating
6471 states. */
6472 static void
6473 set_order_state_num (state_t state)
6475 state->order_state_num = curr_state_order_num;
6476 curr_state_order_num++;
6479 /* The function enumerates all states of AUTOMATON. */
6480 static void
6481 enumerate_states (automaton_t automaton)
6483 curr_state_order_num = 0;
6484 pass_states (automaton, set_order_state_num);
6485 automaton->achieved_states_num = curr_state_order_num;
6490 /* The page contains code for finding equivalent automaton insns
6491 (ainsns). */
6493 /* The function inserts AINSN into cyclic list
6494 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6495 static ainsn_t
6496 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6497 ainsn_t cyclic_equiv_class_insn_list)
6499 if (cyclic_equiv_class_insn_list == NULL)
6500 ainsn->next_equiv_class_insn = ainsn;
6501 else
6503 ainsn->next_equiv_class_insn
6504 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6505 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6507 return ainsn;
6510 /* The function deletes equiv_class_insn into cyclic list of
6511 equivalent ainsns. */
6512 static void
6513 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6515 ainsn_t curr_equiv_class_insn;
6516 ainsn_t prev_equiv_class_insn;
6518 prev_equiv_class_insn = equiv_class_insn;
6519 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6520 curr_equiv_class_insn != equiv_class_insn;
6521 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6522 prev_equiv_class_insn = curr_equiv_class_insn;
6523 if (prev_equiv_class_insn != equiv_class_insn)
6524 prev_equiv_class_insn->next_equiv_class_insn
6525 = equiv_class_insn->next_equiv_class_insn;
6528 /* The function processes AINSN of a state in order to find equivalent
6529 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6530 state. */
6531 static void
6532 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6534 ainsn_t next_insn;
6535 ainsn_t curr_insn;
6536 ainsn_t cyclic_insn_list;
6537 arc_t arc;
6539 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6540 abort ();
6541 curr_insn = ainsn;
6542 /* New class of ainsns which are not equivalent to given ainsn. */
6543 cyclic_insn_list = NULL;
6546 next_insn = curr_insn->next_equiv_class_insn;
6547 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6548 if (arc == NULL
6549 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6550 != arc->to_state))
6552 delete_ainsn_from_equiv_class (curr_insn);
6553 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6554 cyclic_insn_list);
6556 curr_insn = next_insn;
6558 while (curr_insn != ainsn);
6561 /* The function processes STATE in order to find equivalent ainsns. */
6562 static void
6563 process_state_for_insn_equiv_partition (state_t state)
6565 arc_t arc;
6566 arc_t *insn_arcs_array;
6567 int i;
6568 vla_ptr_t insn_arcs_vect;
6570 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6571 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6572 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6573 /* Process insns of the arcs. */
6574 for (i = 0; i < description->insns_num; i++)
6575 insn_arcs_array [i] = NULL;
6576 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6577 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6578 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6579 process_insn_equiv_class (arc->insn, insn_arcs_array);
6580 VLA_PTR_DELETE (insn_arcs_vect);
6583 /* The function searches for equivalent ainsns of AUTOMATON. */
6584 static void
6585 set_insn_equiv_classes (automaton_t automaton)
6587 ainsn_t ainsn;
6588 ainsn_t first_insn;
6589 ainsn_t curr_insn;
6590 ainsn_t cyclic_insn_list;
6591 ainsn_t insn_with_same_reservs;
6592 int equiv_classes_num;
6594 /* All insns are included in one equivalence class. */
6595 cyclic_insn_list = NULL;
6596 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6597 if (ainsn->first_insn_with_same_reservs)
6598 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6599 cyclic_insn_list);
6600 /* Process insns in order to make equivalence partition. */
6601 pass_states (automaton, process_state_for_insn_equiv_partition);
6602 /* Enumerate equiv classes. */
6603 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6604 /* Set undefined value. */
6605 ainsn->insn_equiv_class_num = -1;
6606 equiv_classes_num = 0;
6607 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6608 if (ainsn->insn_equiv_class_num < 0)
6610 first_insn = ainsn;
6611 if (!first_insn->first_insn_with_same_reservs)
6612 abort ();
6613 first_insn->first_ainsn_with_given_equialence_num = 1;
6614 curr_insn = first_insn;
6617 for (insn_with_same_reservs = curr_insn;
6618 insn_with_same_reservs != NULL;
6619 insn_with_same_reservs
6620 = insn_with_same_reservs->next_same_reservs_insn)
6621 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6622 curr_insn = curr_insn->next_equiv_class_insn;
6624 while (curr_insn != first_insn);
6625 equiv_classes_num++;
6627 automaton->insn_equiv_classes_num = equiv_classes_num;
6632 /* This page contains code for creating DFA(s) and calls functions
6633 building them. */
6636 /* The following value is used to prevent floating point overflow for
6637 estimating an automaton bound. The value should be less DBL_MAX on
6638 the host machine. We use here approximate minimum of maximal
6639 double floating point value required by ANSI C standard. It
6640 will work for non ANSI sun compiler too. */
6642 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6644 /* The function estimate size of the single DFA used by PHR (pipeline
6645 hazards recognizer). */
6646 static double
6647 estimate_one_automaton_bound (void)
6649 decl_t decl;
6650 double one_automaton_estimation_bound;
6651 double root_value;
6652 int i;
6654 one_automaton_estimation_bound = 1.0;
6655 for (i = 0; i < description->decls_num; i++)
6657 decl = description->decls [i];
6658 if (decl->mode == dm_unit)
6660 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6661 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6662 / automata_num);
6663 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6664 > one_automaton_estimation_bound)
6665 one_automaton_estimation_bound *= root_value;
6668 return one_automaton_estimation_bound;
6671 /* The function compares unit declarations according to their maximal
6672 cycle in reservations. */
6673 static int
6674 compare_max_occ_cycle_nums (const void *unit_decl_1,
6675 const void *unit_decl_2)
6677 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6678 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6679 return 1;
6680 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6681 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6682 return 0;
6683 else
6684 return -1;
6687 /* The function makes heuristic assigning automata to units. Actually
6688 efficacy of the algorithm has been checked yet??? */
6689 static void
6690 units_to_automata_heuristic_distr (void)
6692 double estimation_bound;
6693 decl_t decl;
6694 decl_t *unit_decl_ptr;
6695 int automaton_num;
6696 int rest_units_num;
6697 double bound_value;
6698 vla_ptr_t unit_decls;
6699 int i;
6701 if (description->units_num == 0)
6702 return;
6703 estimation_bound = estimate_one_automaton_bound ();
6704 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6705 for (i = 0; i < description->decls_num; i++)
6707 decl = description->decls [i];
6708 if (decl->mode == dm_unit)
6709 VLA_PTR_ADD (unit_decls, decl);
6711 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6712 sizeof (decl_t), compare_max_occ_cycle_nums);
6713 automaton_num = 0;
6714 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6715 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6716 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6717 for (unit_decl_ptr++;
6718 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6719 unit_decl_ptr++)
6721 rest_units_num
6722 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6723 if (automata_num - automaton_num - 1 > rest_units_num)
6724 abort ();
6725 if (automaton_num < automata_num - 1
6726 && ((automata_num - automaton_num - 1 == rest_units_num)
6727 || (bound_value
6728 > (estimation_bound
6729 / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6731 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6732 automaton_num++;
6734 else
6735 bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6736 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6738 if (automaton_num != automata_num - 1)
6739 abort ();
6740 VLA_PTR_DELETE (unit_decls);
6743 /* The functions creates automaton insns for each automata. Automaton
6744 insn is simply insn for given automaton which makes reservation
6745 only of units of the automaton. */
6746 static ainsn_t
6747 create_ainsns (void)
6749 decl_t decl;
6750 ainsn_t first_ainsn;
6751 ainsn_t curr_ainsn;
6752 ainsn_t prev_ainsn;
6753 int i;
6755 first_ainsn = NULL;
6756 prev_ainsn = NULL;
6757 for (i = 0; i < description->decls_num; i++)
6759 decl = description->decls [i];
6760 if (decl->mode == dm_insn_reserv)
6762 curr_ainsn = create_node (sizeof (struct ainsn));
6763 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6764 curr_ainsn->important_p = FALSE;
6765 curr_ainsn->next_ainsn = NULL;
6766 if (prev_ainsn == NULL)
6767 first_ainsn = curr_ainsn;
6768 else
6769 prev_ainsn->next_ainsn = curr_ainsn;
6770 prev_ainsn = curr_ainsn;
6773 return first_ainsn;
6776 /* The function assigns automata to units according to constructions
6777 `define_automaton' in the description. */
6778 static void
6779 units_to_automata_distr (void)
6781 decl_t decl;
6782 int i;
6784 for (i = 0; i < description->decls_num; i++)
6786 decl = description->decls [i];
6787 if (decl->mode == dm_unit)
6789 if (DECL_UNIT (decl)->automaton_decl == NULL
6790 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6791 == NULL))
6792 /* Distribute to the first automaton. */
6793 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6794 else
6795 DECL_UNIT (decl)->corresponding_automaton_num
6796 = (DECL_UNIT (decl)->automaton_decl
6797 ->corresponding_automaton->automaton_order_num);
6802 /* The function creates DFA(s) for fast pipeline hazards recognition
6803 after checking and simplifying IR of the description. */
6804 static void
6805 create_automata (void)
6807 automaton_t curr_automaton;
6808 automaton_t prev_automaton;
6809 decl_t decl;
6810 int curr_automaton_num;
6811 int i;
6813 if (automata_num != 0)
6815 units_to_automata_heuristic_distr ();
6816 for (prev_automaton = NULL, curr_automaton_num = 0;
6817 curr_automaton_num < automata_num;
6818 curr_automaton_num++, prev_automaton = curr_automaton)
6820 curr_automaton = create_node (sizeof (struct automaton));
6821 curr_automaton->ainsn_list = create_ainsns ();
6822 curr_automaton->corresponding_automaton_decl = NULL;
6823 curr_automaton->next_automaton = NULL;
6824 curr_automaton->automaton_order_num = curr_automaton_num;
6825 if (prev_automaton == NULL)
6826 description->first_automaton = curr_automaton;
6827 else
6828 prev_automaton->next_automaton = curr_automaton;
6831 else
6833 curr_automaton_num = 0;
6834 prev_automaton = NULL;
6835 for (i = 0; i < description->decls_num; i++)
6837 decl = description->decls [i];
6838 if (decl->mode == dm_automaton
6839 && DECL_AUTOMATON (decl)->automaton_is_used)
6841 curr_automaton = create_node (sizeof (struct automaton));
6842 curr_automaton->ainsn_list = create_ainsns ();
6843 curr_automaton->corresponding_automaton_decl
6844 = DECL_AUTOMATON (decl);
6845 curr_automaton->next_automaton = NULL;
6846 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6847 curr_automaton->automaton_order_num = curr_automaton_num;
6848 if (prev_automaton == NULL)
6849 description->first_automaton = curr_automaton;
6850 else
6851 prev_automaton->next_automaton = curr_automaton;
6852 curr_automaton_num++;
6853 prev_automaton = curr_automaton;
6856 if (curr_automaton_num == 0)
6858 curr_automaton = create_node (sizeof (struct automaton));
6859 curr_automaton->ainsn_list = create_ainsns ();
6860 curr_automaton->corresponding_automaton_decl = NULL;
6861 curr_automaton->next_automaton = NULL;
6862 description->first_automaton = curr_automaton;
6864 units_to_automata_distr ();
6866 NDFA_time = create_ticker ();
6867 ticker_off (&NDFA_time);
6868 NDFA_to_DFA_time = create_ticker ();
6869 ticker_off (&NDFA_to_DFA_time);
6870 minimize_time = create_ticker ();
6871 ticker_off (&minimize_time);
6872 equiv_time = create_ticker ();
6873 ticker_off (&equiv_time);
6874 for (curr_automaton = description->first_automaton;
6875 curr_automaton != NULL;
6876 curr_automaton = curr_automaton->next_automaton)
6878 if (progress_flag)
6880 if (curr_automaton->corresponding_automaton_decl == NULL)
6881 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6882 else
6883 fprintf (stderr, "Prepare automaton `%s' creation...",
6884 curr_automaton->corresponding_automaton_decl->name);
6886 create_alt_states (curr_automaton);
6887 form_ainsn_with_same_reservs (curr_automaton);
6888 if (progress_flag)
6889 fprintf (stderr, "done\n");
6890 build_automaton (curr_automaton);
6891 enumerate_states (curr_automaton);
6892 ticker_on (&equiv_time);
6893 set_insn_equiv_classes (curr_automaton);
6894 ticker_off (&equiv_time);
6900 /* This page contains code for forming string representation of
6901 regexp. The representation is formed on IR obstack. So you should
6902 not work with IR obstack between regexp_representation and
6903 finish_regexp_representation calls. */
6905 /* This recursive function forms string representation of regexp
6906 (without tailing '\0'). */
6907 static void
6908 form_regexp (regexp_t regexp)
6910 int i;
6912 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6914 const char *name = (regexp->mode == rm_unit
6915 ? REGEXP_UNIT (regexp)->name
6916 : REGEXP_RESERV (regexp)->name);
6918 obstack_grow (&irp, name, strlen (name));
6920 else if (regexp->mode == rm_sequence)
6921 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6923 if (i != 0)
6924 obstack_1grow (&irp, ',');
6925 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6927 else if (regexp->mode == rm_allof)
6929 obstack_1grow (&irp, '(');
6930 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6932 if (i != 0)
6933 obstack_1grow (&irp, '+');
6934 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6935 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6936 obstack_1grow (&irp, '(');
6937 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6938 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6939 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6940 obstack_1grow (&irp, ')');
6942 obstack_1grow (&irp, ')');
6944 else if (regexp->mode == rm_oneof)
6945 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6947 if (i != 0)
6948 obstack_1grow (&irp, '|');
6949 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6950 obstack_1grow (&irp, '(');
6951 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6952 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6953 obstack_1grow (&irp, ')');
6955 else if (regexp->mode == rm_repeat)
6957 char digits [30];
6959 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6960 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6961 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6962 obstack_1grow (&irp, '(');
6963 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6964 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6965 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6966 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6967 obstack_1grow (&irp, ')');
6968 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6969 obstack_grow (&irp, digits, strlen (digits));
6971 else if (regexp->mode == rm_nothing)
6972 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6973 else
6974 abort ();
6977 /* The function returns string representation of REGEXP on IR
6978 obstack. */
6979 static const char *
6980 regexp_representation (regexp_t regexp)
6982 form_regexp (regexp);
6983 obstack_1grow (&irp, '\0');
6984 return obstack_base (&irp);
6987 /* The function frees memory allocated for last formed string
6988 representation of regexp. */
6989 static void
6990 finish_regexp_representation (void)
6992 int length = obstack_object_size (&irp);
6994 obstack_blank_fast (&irp, -length);
6999 /* This page contains code for output PHR (pipeline hazards recognizer). */
7001 /* The function outputs minimal C type which is sufficient for
7002 representation numbers in range min_range_value and
7003 max_range_value. Because host machine and build machine may be
7004 different, we use here minimal values required by ANSI C standard
7005 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
7006 approximation. */
7008 static void
7009 output_range_type (FILE *f, long int min_range_value,
7010 long int max_range_value)
7012 if (min_range_value >= 0 && max_range_value <= 255)
7013 fprintf (f, "unsigned char");
7014 else if (min_range_value >= -127 && max_range_value <= 127)
7015 fprintf (f, "signed char");
7016 else if (min_range_value >= 0 && max_range_value <= 65535)
7017 fprintf (f, "unsigned short");
7018 else if (min_range_value >= -32767 && max_range_value <= 32767)
7019 fprintf (f, "short");
7020 else
7021 fprintf (f, "int");
7024 /* The following macro value is used as value of member
7025 `longest_path_length' of state when we are processing path and the
7026 state on the path. */
7028 #define ON_THE_PATH -2
7030 /* The following recursive function searches for the length of the
7031 longest path starting from STATE which does not contain cycles and
7032 `cycle advance' arcs. */
7034 static int
7035 longest_path_length (state_t state)
7037 arc_t arc;
7038 int length, result;
7040 if (state->longest_path_length == ON_THE_PATH)
7041 /* We don't expect the path cycle here. Our graph may contain
7042 only cycles with one state on the path not containing `cycle
7043 advance' arcs -- see comment below. */
7044 abort ();
7045 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
7046 /* We already visited the state. */
7047 return state->longest_path_length;
7049 result = 0;
7050 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7051 /* Ignore cycles containing one state and `cycle advance' arcs. */
7052 if (arc->to_state != state
7053 && (arc->insn->insn_reserv_decl
7054 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
7056 length = longest_path_length (arc->to_state);
7057 if (length > result)
7058 result = length;
7060 state->longest_path_length = result + 1;
7061 return result;
7064 /* The following variable value is value of the corresponding global
7065 variable in the automaton based pipeline interface. */
7067 static int max_dfa_issue_rate;
7069 /* The following function processes the longest path length staring
7070 from STATE to find MAX_DFA_ISSUE_RATE. */
7072 static void
7073 process_state_longest_path_length (state_t state)
7075 int value;
7077 value = longest_path_length (state);
7078 if (value > max_dfa_issue_rate)
7079 max_dfa_issue_rate = value;
7082 /* The following macro value is name of the corresponding global
7083 variable in the automaton based pipeline interface. */
7085 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
7087 /* The following function calculates value of the corresponding
7088 global variable and outputs its declaration. */
7090 static void
7091 output_dfa_max_issue_rate (void)
7093 automaton_t automaton;
7095 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
7096 abort ();
7097 max_dfa_issue_rate = 0;
7098 for (automaton = description->first_automaton;
7099 automaton != NULL;
7100 automaton = automaton->next_automaton)
7101 pass_states (automaton, process_state_longest_path_length);
7102 fprintf (output_file, "\nint %s = %d;\n",
7103 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
7106 /* The function outputs all initialization values of VECT with length
7107 vect_length. */
7108 static void
7109 output_vect (vect_el_t *vect, int vect_length)
7111 int els_on_line;
7113 els_on_line = 1;
7114 if (vect_length == 0)
7115 fprintf (output_file,
7116 "0 /* This is dummy el because the vect is empty */");
7117 else
7121 fprintf (output_file, "%5ld", (long) *vect);
7122 vect_length--;
7123 if (els_on_line == 10)
7125 els_on_line = 0;
7126 fprintf (output_file, ",\n");
7128 else if (vect_length != 0)
7129 fprintf (output_file, ", ");
7130 els_on_line++;
7131 vect++;
7133 while (vect_length != 0);
7137 /* The following is name of the structure which represents DFA(s) for
7138 PHR. */
7139 #define CHIP_NAME "DFA_chip"
7141 /* The following is name of member which represents state of a DFA for
7142 PHR. */
7143 static void
7144 output_chip_member_name (FILE *f, automaton_t automaton)
7146 if (automaton->corresponding_automaton_decl == NULL)
7147 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
7148 else
7149 fprintf (f, "%s_automaton_state",
7150 automaton->corresponding_automaton_decl->name);
7153 /* The following is name of temporary variable which stores state of a
7154 DFA for PHR. */
7155 static void
7156 output_temp_chip_member_name (FILE *f, automaton_t automaton)
7158 fprintf (f, "_");
7159 output_chip_member_name (f, automaton);
7162 /* This is name of macro value which is code of pseudo_insn
7163 representing advancing cpu cycle. Its value is used as internal
7164 code unknown insn. */
7165 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7167 /* Output name of translate vector for given automaton. */
7168 static void
7169 output_translate_vect_name (FILE *f, automaton_t automaton)
7171 if (automaton->corresponding_automaton_decl == NULL)
7172 fprintf (f, "translate_%d", automaton->automaton_order_num);
7173 else
7174 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
7177 /* Output name for simple transition table representation. */
7178 static void
7179 output_trans_full_vect_name (FILE *f, automaton_t automaton)
7181 if (automaton->corresponding_automaton_decl == NULL)
7182 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7183 else
7184 fprintf (f, "%s_transitions",
7185 automaton->corresponding_automaton_decl->name);
7188 /* Output name of comb vector of the transition table for given
7189 automaton. */
7190 static void
7191 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
7193 if (automaton->corresponding_automaton_decl == NULL)
7194 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7195 else
7196 fprintf (f, "%s_transitions",
7197 automaton->corresponding_automaton_decl->name);
7200 /* Output name of check vector of the transition table for given
7201 automaton. */
7202 static void
7203 output_trans_check_vect_name (FILE *f, automaton_t automaton)
7205 if (automaton->corresponding_automaton_decl == NULL)
7206 fprintf (f, "check_%d", automaton->automaton_order_num);
7207 else
7208 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7211 /* Output name of base vector of the transition table for given
7212 automaton. */
7213 static void
7214 output_trans_base_vect_name (FILE *f, automaton_t automaton)
7216 if (automaton->corresponding_automaton_decl == NULL)
7217 fprintf (f, "base_%d", automaton->automaton_order_num);
7218 else
7219 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7222 /* Output name for simple alternatives number representation. */
7223 static void
7224 output_state_alts_full_vect_name (FILE *f, automaton_t automaton)
7226 if (automaton->corresponding_automaton_decl == NULL)
7227 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7228 else
7229 fprintf (f, "%s_state_alts",
7230 automaton->corresponding_automaton_decl->name);
7233 /* Output name of comb vector of the alternatives number table for given
7234 automaton. */
7235 static void
7236 output_state_alts_comb_vect_name (FILE *f, automaton_t automaton)
7238 if (automaton->corresponding_automaton_decl == NULL)
7239 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7240 else
7241 fprintf (f, "%s_state_alts",
7242 automaton->corresponding_automaton_decl->name);
7245 /* Output name of check vector of the alternatives number table for given
7246 automaton. */
7247 static void
7248 output_state_alts_check_vect_name (FILE *f, automaton_t automaton)
7250 if (automaton->corresponding_automaton_decl == NULL)
7251 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7252 else
7253 fprintf (f, "%s_check_state_alts",
7254 automaton->corresponding_automaton_decl->name);
7257 /* Output name of base vector of the alternatives number table for given
7258 automaton. */
7259 static void
7260 output_state_alts_base_vect_name (FILE *f, automaton_t automaton)
7262 if (automaton->corresponding_automaton_decl == NULL)
7263 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7264 else
7265 fprintf (f, "%s_base_state_alts",
7266 automaton->corresponding_automaton_decl->name);
7269 /* Output name of simple min issue delay table representation. */
7270 static void
7271 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
7273 if (automaton->corresponding_automaton_decl == NULL)
7274 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7275 else
7276 fprintf (f, "%s_min_issue_delay",
7277 automaton->corresponding_automaton_decl->name);
7280 /* Output name of deadlock vector for given automaton. */
7281 static void
7282 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
7284 if (automaton->corresponding_automaton_decl == NULL)
7285 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7286 else
7287 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7290 /* Output name of reserved units table for AUTOMATON into file F. */
7291 static void
7292 output_reserved_units_table_name (FILE *f, automaton_t automaton)
7294 if (automaton->corresponding_automaton_decl == NULL)
7295 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7296 else
7297 fprintf (f, "%s_reserved_units",
7298 automaton->corresponding_automaton_decl->name);
7301 /* Name of the PHR interface macro. */
7302 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7304 /* Name of the PHR interface macro. */
7305 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7307 /* Names of an internal functions: */
7308 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7310 /* This is external type of DFA(s) state. */
7311 #define STATE_TYPE_NAME "state_t"
7313 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7315 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7317 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7319 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7321 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7323 /* Name of cache of insn dfa codes. */
7324 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7326 /* Name of length of cache of insn dfa codes. */
7327 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7329 /* Names of the PHR interface functions: */
7330 #define SIZE_FUNC_NAME "state_size"
7332 #define TRANSITION_FUNC_NAME "state_transition"
7334 #define STATE_ALTS_FUNC_NAME "state_alts"
7336 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7338 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7340 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7342 #define RESET_FUNC_NAME "state_reset"
7344 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7346 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7348 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7350 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7352 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7354 #define DFA_START_FUNC_NAME "dfa_start"
7356 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7358 /* Names of parameters of the PHR interface functions. */
7359 #define STATE_NAME "state"
7361 #define INSN_PARAMETER_NAME "insn"
7363 #define INSN2_PARAMETER_NAME "insn2"
7365 #define CHIP_PARAMETER_NAME "chip"
7367 #define FILE_PARAMETER_NAME "f"
7369 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7371 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7373 /* Names of the variables whose values are internal insn code of rtx
7374 insn. */
7375 #define INTERNAL_INSN_CODE_NAME "insn_code"
7377 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7379 /* Names of temporary variables in some functions. */
7380 #define TEMPORARY_VARIABLE_NAME "temp"
7382 #define I_VARIABLE_NAME "i"
7384 /* Name of result variable in some functions. */
7385 #define RESULT_VARIABLE_NAME "res"
7387 /* Name of function (attribute) to translate insn into internal insn
7388 code. */
7389 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7391 /* Name of function (attribute) to translate insn into internal insn
7392 code with caching. */
7393 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7395 /* Name of function (attribute) to translate insn into internal insn
7396 code. */
7397 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7399 /* Name of function (attribute) to translate insn into internal insn
7400 code. */
7401 #define BYPASS_P_FUNC_NAME "bypass_p"
7403 /* Output C type which is used for representation of codes of states
7404 of AUTOMATON. */
7405 static void
7406 output_state_member_type (FILE *f, automaton_t automaton)
7408 output_range_type (f, 0, automaton->achieved_states_num);
7411 /* Output definition of the structure representing current DFA(s)
7412 state(s). */
7413 static void
7414 output_chip_definitions (void)
7416 automaton_t automaton;
7418 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7419 for (automaton = description->first_automaton;
7420 automaton != NULL;
7421 automaton = automaton->next_automaton)
7423 fprintf (output_file, " ");
7424 output_state_member_type (output_file, automaton);
7425 fprintf (output_file, " ");
7426 output_chip_member_name (output_file, automaton);
7427 fprintf (output_file, ";\n");
7429 fprintf (output_file, "};\n\n");
7430 #if 0
7431 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7432 #endif
7436 /* The function outputs translate vector of internal insn code into
7437 insn equivalence class number. The equivalence class number is
7438 used to access to table and vectors representing DFA(s). */
7439 static void
7440 output_translate_vect (automaton_t automaton)
7442 ainsn_t ainsn;
7443 int insn_value;
7444 vla_hwint_t translate_vect;
7446 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7447 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7448 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7449 /* Undefined value */
7450 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7451 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7452 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7453 = ainsn->insn_equiv_class_num;
7454 fprintf (output_file,
7455 "/* Vector translating external insn codes to internal ones.*/\n");
7456 fprintf (output_file, "static const ");
7457 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7458 fprintf (output_file, " ");
7459 output_translate_vect_name (output_file, automaton);
7460 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7461 output_vect (VLA_HWINT_BEGIN (translate_vect),
7462 VLA_HWINT_LENGTH (translate_vect));
7463 fprintf (output_file, "};\n\n");
7464 VLA_HWINT_DELETE (translate_vect);
7467 /* The value in a table state x ainsn -> something which represents
7468 undefined value. */
7469 static int undefined_vect_el_value;
7471 /* The following function returns nonzero value if the best
7472 representation of the table is comb vector. */
7473 static int
7474 comb_vect_p (state_ainsn_table_t tab)
7476 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7477 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7480 /* The following function creates new table for AUTOMATON. */
7481 static state_ainsn_table_t
7482 create_state_ainsn_table (automaton_t automaton)
7484 state_ainsn_table_t tab;
7485 int full_vect_length;
7486 int i;
7488 tab = create_node (sizeof (struct state_ainsn_table));
7489 tab->automaton = automaton;
7490 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7491 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7492 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7493 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7494 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7495 full_vect_length = (automaton->insn_equiv_classes_num
7496 * automaton->achieved_states_num);
7497 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7498 for (i = 0; i < full_vect_length; i++)
7499 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7500 tab->min_base_vect_el_value = 0;
7501 tab->max_base_vect_el_value = 0;
7502 tab->min_comb_vect_el_value = 0;
7503 tab->max_comb_vect_el_value = 0;
7504 return tab;
7507 /* The following function outputs the best C representation of the
7508 table TAB of given TABLE_NAME. */
7509 static void
7510 output_state_ainsn_table (state_ainsn_table_t tab, char *table_name,
7511 void (*output_full_vect_name_func) (FILE *, automaton_t),
7512 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7513 void (*output_check_vect_name_func) (FILE *, automaton_t),
7514 void (*output_base_vect_name_func) (FILE *, automaton_t))
7516 if (!comb_vect_p (tab))
7518 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7519 fprintf (output_file, "static const ");
7520 output_range_type (output_file, tab->min_comb_vect_el_value,
7521 tab->max_comb_vect_el_value);
7522 fprintf (output_file, " ");
7523 (*output_full_vect_name_func) (output_file, tab->automaton);
7524 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7525 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7526 VLA_HWINT_LENGTH (tab->full_vect));
7527 fprintf (output_file, "};\n\n");
7529 else
7531 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7532 fprintf (output_file, "static const ");
7533 output_range_type (output_file, tab->min_comb_vect_el_value,
7534 tab->max_comb_vect_el_value);
7535 fprintf (output_file, " ");
7536 (*output_comb_vect_name_func) (output_file, tab->automaton);
7537 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7538 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7539 VLA_HWINT_LENGTH (tab->comb_vect));
7540 fprintf (output_file, "};\n\n");
7541 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7542 fprintf (output_file, "static const ");
7543 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7544 fprintf (output_file, " ");
7545 (*output_check_vect_name_func) (output_file, tab->automaton);
7546 fprintf (output_file, "[] = {\n");
7547 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7548 VLA_HWINT_LENGTH (tab->check_vect));
7549 fprintf (output_file, "};\n\n");
7550 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7551 fprintf (output_file, "static const ");
7552 output_range_type (output_file, tab->min_base_vect_el_value,
7553 tab->max_base_vect_el_value);
7554 fprintf (output_file, " ");
7555 (*output_base_vect_name_func) (output_file, tab->automaton);
7556 fprintf (output_file, "[] = {\n");
7557 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7558 VLA_HWINT_LENGTH (tab->base_vect));
7559 fprintf (output_file, "};\n\n");
7563 /* The following function adds vector with length VECT_LENGTH and
7564 elements pointed by VECT to table TAB as its line with number
7565 VECT_NUM. */
7566 static void
7567 add_vect (state_ainsn_table_t tab, int vect_num, vect_el_t *vect,
7568 int vect_length)
7570 int real_vect_length;
7571 vect_el_t *comb_vect_start;
7572 vect_el_t *check_vect_start;
7573 int comb_vect_index;
7574 int comb_vect_els_num;
7575 int vect_index;
7576 int first_unempty_vect_index;
7577 int additional_els_num;
7578 int no_state_value;
7579 vect_el_t vect_el;
7580 int i;
7582 if (vect_length == 0)
7583 abort ();
7584 real_vect_length = tab->automaton->insn_equiv_classes_num;
7585 if (vect [vect_length - 1] == undefined_vect_el_value)
7586 abort ();
7587 /* Form full vector in the table: */
7588 for (i = 0; i < vect_length; i++)
7589 VLA_HWINT (tab->full_vect,
7590 i + tab->automaton->insn_equiv_classes_num * vect_num)
7591 = vect [i];
7592 /* Form comb vector in the table: */
7593 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7594 abort ();
7595 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7596 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7597 for (first_unempty_vect_index = 0;
7598 first_unempty_vect_index < vect_length;
7599 first_unempty_vect_index++)
7600 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7601 break;
7602 /* Search for the place in comb vect for the inserted vect. */
7603 for (comb_vect_index = 0;
7604 comb_vect_index < comb_vect_els_num;
7605 comb_vect_index++)
7607 for (vect_index = first_unempty_vect_index;
7608 vect_index < vect_length
7609 && vect_index + comb_vect_index < comb_vect_els_num;
7610 vect_index++)
7611 if (vect [vect_index] != undefined_vect_el_value
7612 && (comb_vect_start [vect_index + comb_vect_index]
7613 != undefined_vect_el_value))
7614 break;
7615 if (vect_index >= vect_length
7616 || vect_index + comb_vect_index >= comb_vect_els_num)
7617 break;
7619 /* Slot was found. */
7620 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7621 if (additional_els_num < 0)
7622 additional_els_num = 0;
7623 /* Expand comb and check vectors. */
7624 vect_el = undefined_vect_el_value;
7625 no_state_value = tab->automaton->achieved_states_num;
7626 while (additional_els_num > 0)
7628 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7629 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7630 additional_els_num--;
7632 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7633 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7634 if (VLA_HWINT_LENGTH (tab->comb_vect)
7635 < (size_t) (comb_vect_index + real_vect_length))
7636 abort ();
7637 /* Fill comb and check vectors. */
7638 for (vect_index = 0; vect_index < vect_length; vect_index++)
7639 if (vect [vect_index] != undefined_vect_el_value)
7641 if (comb_vect_start [comb_vect_index + vect_index]
7642 != undefined_vect_el_value)
7643 abort ();
7644 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7645 if (vect [vect_index] < 0)
7646 abort ();
7647 if (tab->max_comb_vect_el_value < vect [vect_index])
7648 tab->max_comb_vect_el_value = vect [vect_index];
7649 if (tab->min_comb_vect_el_value > vect [vect_index])
7650 tab->min_comb_vect_el_value = vect [vect_index];
7651 check_vect_start [comb_vect_index + vect_index] = vect_num;
7653 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7654 tab->max_comb_vect_el_value = undefined_vect_el_value;
7655 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7656 tab->min_comb_vect_el_value = undefined_vect_el_value;
7657 if (tab->max_base_vect_el_value < comb_vect_index)
7658 tab->max_base_vect_el_value = comb_vect_index;
7659 if (tab->min_base_vect_el_value > comb_vect_index)
7660 tab->min_base_vect_el_value = comb_vect_index;
7661 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7664 /* Return number of out arcs of STATE. */
7665 static int
7666 out_state_arcs_num (state_t state)
7668 int result;
7669 arc_t arc;
7671 result = 0;
7672 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7674 if (arc->insn == NULL)
7675 abort ();
7676 if (arc->insn->first_ainsn_with_given_equialence_num)
7677 result++;
7679 return result;
7682 /* Compare number of possible transitions from the states. */
7683 static int
7684 compare_transition_els_num (const void *state_ptr_1,
7685 const void *state_ptr_2)
7687 int transition_els_num_1;
7688 int transition_els_num_2;
7690 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7691 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7692 if (transition_els_num_1 < transition_els_num_2)
7693 return 1;
7694 else if (transition_els_num_1 == transition_els_num_2)
7695 return 0;
7696 else
7697 return -1;
7700 /* The function adds element EL_VALUE to vector VECT for a table state
7701 x AINSN. */
7702 static void
7703 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7705 int equiv_class_num;
7706 int vect_index;
7708 if (ainsn == NULL)
7709 abort ();
7710 equiv_class_num = ainsn->insn_equiv_class_num;
7711 for (vect_index = VLA_HWINT_LENGTH (*vect);
7712 vect_index <= equiv_class_num;
7713 vect_index++)
7714 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7715 VLA_HWINT (*vect, equiv_class_num) = el_value;
7718 /* This is for forming vector of states of an automaton. */
7719 static vla_ptr_t output_states_vect;
7721 /* The function is called by function pass_states. The function adds
7722 STATE to `output_states_vect'. */
7723 static void
7724 add_states_vect_el (state_t state)
7726 VLA_PTR_ADD (output_states_vect, state);
7729 /* Form and output vectors (comb, check, base or full vector)
7730 representing transition table of AUTOMATON. */
7731 static void
7732 output_trans_table (automaton_t automaton)
7734 state_t *state_ptr;
7735 arc_t arc;
7736 vla_hwint_t transition_vect;
7738 undefined_vect_el_value = automaton->achieved_states_num;
7739 automaton->trans_table = create_state_ainsn_table (automaton);
7740 /* Create vect of pointers to states ordered by num of transitions
7741 from the state (state with the maximum num is the first). */
7742 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7743 pass_states (automaton, add_states_vect_el);
7744 qsort (VLA_PTR_BEGIN (output_states_vect),
7745 VLA_PTR_LENGTH (output_states_vect),
7746 sizeof (state_t), compare_transition_els_num);
7747 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7748 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7749 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7750 state_ptr++)
7752 VLA_HWINT_NULLIFY (transition_vect);
7753 for (arc = first_out_arc (*state_ptr);
7754 arc != NULL;
7755 arc = next_out_arc (arc))
7757 if (arc->insn == NULL)
7758 abort ();
7759 if (arc->insn->first_ainsn_with_given_equialence_num)
7760 add_vect_el (&transition_vect, arc->insn,
7761 arc->to_state->order_state_num);
7763 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7764 VLA_HWINT_BEGIN (transition_vect),
7765 VLA_HWINT_LENGTH (transition_vect));
7767 output_state_ainsn_table
7768 (automaton->trans_table, (char *) "state transitions",
7769 output_trans_full_vect_name, output_trans_comb_vect_name,
7770 output_trans_check_vect_name, output_trans_base_vect_name);
7771 VLA_PTR_DELETE (output_states_vect);
7772 VLA_HWINT_DELETE (transition_vect);
7775 /* Form and output vectors (comb, check, base or simple vect)
7776 representing alts number table of AUTOMATON. The table is state x
7777 ainsn -> number of possible alternative reservations by the
7778 ainsn. */
7779 static void
7780 output_state_alts_table (automaton_t automaton)
7782 state_t *state_ptr;
7783 arc_t arc;
7784 vla_hwint_t state_alts_vect;
7786 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7787 automaton->state_alts_table = create_state_ainsn_table (automaton);
7788 /* Create vect of pointers to states ordered by num of transitions
7789 from the state (state with the maximum num is the first). */
7790 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7791 pass_states (automaton, add_states_vect_el);
7792 qsort (VLA_PTR_BEGIN (output_states_vect),
7793 VLA_PTR_LENGTH (output_states_vect),
7794 sizeof (state_t), compare_transition_els_num);
7795 /* Create base, comb, and check vectors. */
7796 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7797 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7798 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7799 state_ptr++)
7801 VLA_HWINT_NULLIFY (state_alts_vect);
7802 for (arc = first_out_arc (*state_ptr);
7803 arc != NULL;
7804 arc = next_out_arc (arc))
7806 if (arc->insn == NULL)
7807 abort ();
7808 if (arc->insn->first_ainsn_with_given_equialence_num)
7809 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7811 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7812 VLA_HWINT_BEGIN (state_alts_vect),
7813 VLA_HWINT_LENGTH (state_alts_vect));
7815 output_state_ainsn_table
7816 (automaton->state_alts_table, (char *) "state insn alternatives",
7817 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7818 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7819 VLA_PTR_DELETE (output_states_vect);
7820 VLA_HWINT_DELETE (state_alts_vect);
7823 /* The current number of passing states to find minimal issue delay
7824 value for an ainsn and state. */
7825 static int curr_state_pass_num;
7827 /* This recursive function passes states to find minimal issue delay
7828 value for AINSN. The state being visited is STATE. The function
7829 returns minimal issue delay value for AINSN in STATE or -1 if we
7830 enter into a loop. */
7831 static int
7832 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7834 arc_t arc;
7835 int min_insn_issue_delay, insn_issue_delay;
7837 if (state->state_pass_num == curr_state_pass_num
7838 || state->min_insn_issue_delay != -1)
7839 /* We've entered into a loop or already have the correct value for
7840 given state and ainsn. */
7841 return state->min_insn_issue_delay;
7842 state->state_pass_num = curr_state_pass_num;
7843 min_insn_issue_delay = -1;
7844 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7845 if (arc->insn == ainsn)
7847 min_insn_issue_delay = 0;
7848 break;
7850 else
7852 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7853 if (insn_issue_delay != -1)
7855 if (arc->insn->insn_reserv_decl
7856 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7857 insn_issue_delay++;
7858 if (min_insn_issue_delay == -1
7859 || min_insn_issue_delay > insn_issue_delay)
7861 min_insn_issue_delay = insn_issue_delay;
7862 if (insn_issue_delay == 0)
7863 break;
7867 return min_insn_issue_delay;
7870 /* The function searches minimal issue delay value for AINSN in STATE.
7871 The function can return negative value if we can not issue AINSN. We
7872 will report about it later. */
7873 static int
7874 min_issue_delay (state_t state, ainsn_t ainsn)
7876 curr_state_pass_num++;
7877 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7878 return state->min_insn_issue_delay;
7881 /* The function initiates code for finding minimal issue delay values.
7882 It should be called only once. */
7883 static void
7884 initiate_min_issue_delay_pass_states (void)
7886 curr_state_pass_num = 0;
7889 /* Form and output vectors representing minimal issue delay table of
7890 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7891 the ainsn. */
7892 static void
7893 output_min_issue_delay_table (automaton_t automaton)
7895 vla_hwint_t min_issue_delay_vect;
7896 vla_hwint_t compressed_min_issue_delay_vect;
7897 vect_el_t min_delay;
7898 ainsn_t ainsn;
7899 state_t *state_ptr;
7900 int i;
7902 /* Create vect of pointers to states ordered by num of transitions
7903 from the state (state with the maximum num is the first). */
7904 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7905 pass_states (automaton, add_states_vect_el);
7906 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7907 VLA_HWINT_EXPAND (min_issue_delay_vect,
7908 VLA_HWINT_LENGTH (output_states_vect)
7909 * automaton->insn_equiv_classes_num);
7910 for (i = 0;
7911 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7912 * automaton->insn_equiv_classes_num);
7913 i++)
7914 VLA_HWINT (min_issue_delay_vect, i) = 0;
7915 automaton->max_min_delay = 0;
7916 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7917 if (ainsn->first_ainsn_with_given_equialence_num)
7919 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7920 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7921 state_ptr++)
7922 (*state_ptr)->min_insn_issue_delay = -1;
7923 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7924 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7925 state_ptr++)
7927 min_delay = min_issue_delay (*state_ptr, ainsn);
7928 if (automaton->max_min_delay < min_delay)
7929 automaton->max_min_delay = min_delay;
7930 VLA_HWINT (min_issue_delay_vect,
7931 (*state_ptr)->order_state_num
7932 * automaton->insn_equiv_classes_num
7933 + ainsn->insn_equiv_class_num) = min_delay;
7936 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7937 fprintf (output_file, "static const ");
7938 output_range_type (output_file, 0, automaton->max_min_delay);
7939 fprintf (output_file, " ");
7940 output_min_issue_delay_vect_name (output_file, automaton);
7941 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7942 /* Compress the vector. */
7943 if (automaton->max_min_delay < 2)
7944 automaton->min_issue_delay_table_compression_factor = 8;
7945 else if (automaton->max_min_delay < 4)
7946 automaton->min_issue_delay_table_compression_factor = 4;
7947 else if (automaton->max_min_delay < 16)
7948 automaton->min_issue_delay_table_compression_factor = 2;
7949 else
7950 automaton->min_issue_delay_table_compression_factor = 1;
7951 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7952 "compressed min issue delay vector");
7953 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7954 (VLA_HWINT_LENGTH (min_issue_delay_vect)
7955 + automaton->min_issue_delay_table_compression_factor
7956 - 1)
7957 / automaton->min_issue_delay_table_compression_factor);
7958 for (i = 0;
7959 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7960 i++)
7961 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7962 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7963 VLA_HWINT (compressed_min_issue_delay_vect,
7964 i / automaton->min_issue_delay_table_compression_factor)
7965 |= (VLA_HWINT (min_issue_delay_vect, i)
7966 << (8 - (i % automaton->min_issue_delay_table_compression_factor
7967 + 1)
7968 * (8 / automaton->min_issue_delay_table_compression_factor)));
7969 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7970 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7971 fprintf (output_file, "};\n\n");
7972 VLA_PTR_DELETE (output_states_vect);
7973 VLA_HWINT_DELETE (min_issue_delay_vect);
7974 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7977 #ifndef NDEBUG
7978 /* Number of states which contains transition only by advancing cpu
7979 cycle. */
7980 static int locked_states_num;
7981 #endif
7983 /* Form and output vector representing the locked states of
7984 AUTOMATON. */
7985 static void
7986 output_dead_lock_vect (automaton_t automaton)
7988 state_t *state_ptr;
7989 arc_t arc;
7990 vla_hwint_t dead_lock_vect;
7992 /* Create vect of pointers to states ordered by num of
7993 transitions from the state (state with the maximum num is the
7994 first). */
7995 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7996 pass_states (automaton, add_states_vect_el);
7997 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7998 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7999 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
8000 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8001 state_ptr++)
8003 arc = first_out_arc (*state_ptr);
8004 if (arc == NULL)
8005 abort ();
8006 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
8007 = (next_out_arc (arc) == NULL
8008 && (arc->insn->insn_reserv_decl
8009 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
8010 #ifndef NDEBUG
8011 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
8012 locked_states_num++;
8013 #endif
8015 fprintf (output_file, "/* Vector for locked state flags. */\n");
8016 fprintf (output_file, "static const ");
8017 output_range_type (output_file, 0, 1);
8018 fprintf (output_file, " ");
8019 output_dead_lock_vect_name (output_file, automaton);
8020 fprintf (output_file, "[] = {\n");
8021 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
8022 VLA_HWINT_LENGTH (dead_lock_vect));
8023 fprintf (output_file, "};\n\n");
8024 VLA_HWINT_DELETE (dead_lock_vect);
8025 VLA_PTR_DELETE (output_states_vect);
8028 /* Form and output vector representing reserved units of the states of
8029 AUTOMATON. */
8030 static void
8031 output_reserved_units_table (automaton_t automaton)
8033 state_t *curr_state_ptr;
8034 vla_hwint_t reserved_units_table;
8035 size_t state_byte_size;
8036 int i;
8038 /* Create vect of pointers to states. */
8039 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8040 pass_states (automaton, add_states_vect_el);
8041 /* Create vector. */
8042 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
8043 state_byte_size = (description->query_units_num + 7) / 8;
8044 VLA_HWINT_EXPAND (reserved_units_table,
8045 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8046 for (i = 0;
8047 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8048 i++)
8049 VLA_HWINT (reserved_units_table, i) = 0;
8050 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
8051 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8052 curr_state_ptr++)
8054 for (i = 0; i < description->units_num; i++)
8055 if (units_array [i]->query_p
8056 && first_cycle_unit_presence (*curr_state_ptr, i))
8057 VLA_HWINT (reserved_units_table,
8058 (*curr_state_ptr)->order_state_num * state_byte_size
8059 + units_array [i]->query_num / 8)
8060 += (1 << (units_array [i]->query_num % 8));
8062 fprintf (output_file, "/* Vector for reserved units of states. */\n");
8063 fprintf (output_file, "static const ");
8064 output_range_type (output_file, 0, 255);
8065 fprintf (output_file, " ");
8066 output_reserved_units_table_name (output_file, automaton);
8067 fprintf (output_file, "[] = {\n");
8068 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
8069 VLA_HWINT_LENGTH (reserved_units_table));
8070 fprintf (output_file, "};\n\n");
8071 VLA_HWINT_DELETE (reserved_units_table);
8072 VLA_PTR_DELETE (output_states_vect);
8075 /* The function outputs all tables representing DFA(s) used for fast
8076 pipeline hazards recognition. */
8077 static void
8078 output_tables (void)
8080 automaton_t automaton;
8082 #ifndef NDEBUG
8083 locked_states_num = 0;
8084 #endif
8085 initiate_min_issue_delay_pass_states ();
8086 for (automaton = description->first_automaton;
8087 automaton != NULL;
8088 automaton = automaton->next_automaton)
8090 output_translate_vect (automaton);
8091 output_trans_table (automaton);
8092 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
8093 output_state_alts_table (automaton);
8094 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8095 AUTOMATON_STATE_ALTS_MACRO_NAME);
8096 output_min_issue_delay_table (automaton);
8097 output_dead_lock_vect (automaton);
8098 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
8099 output_reserved_units_table (automaton);
8100 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8101 CPU_UNITS_QUERY_MACRO_NAME);
8103 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
8104 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8107 /* The function outputs definition and value of PHR interface variable
8108 `max_insn_queue_index'. Its value is not less than maximal queue
8109 length needed for the insn scheduler. */
8110 static void
8111 output_max_insn_queue_index_def (void)
8113 int i, max, latency;
8114 decl_t decl;
8116 max = description->max_insn_reserv_cycles;
8117 for (i = 0; i < description->decls_num; i++)
8119 decl = description->decls [i];
8120 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8122 latency = DECL_INSN_RESERV (decl)->default_latency;
8123 if (latency > max)
8124 max = latency;
8126 else if (decl->mode == dm_bypass)
8128 latency = DECL_BYPASS (decl)->latency;
8129 if (latency > max)
8130 max = latency;
8133 for (i = 0; (1 << i) <= max; i++)
8135 if (i < 0)
8136 abort ();
8137 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
8141 /* The function outputs switch cases for insn reservations using
8142 function *output_automata_list_code. */
8143 static void
8144 output_insn_code_cases (void (*output_automata_list_code)
8145 (automata_list_el_t))
8147 decl_t decl, decl2;
8148 int i, j;
8150 for (i = 0; i < description->decls_num; i++)
8152 decl = description->decls [i];
8153 if (decl->mode == dm_insn_reserv)
8154 DECL_INSN_RESERV (decl)->processed_p = FALSE;
8156 for (i = 0; i < description->decls_num; i++)
8158 decl = description->decls [i];
8159 if (decl->mode == dm_insn_reserv
8160 && !DECL_INSN_RESERV (decl)->processed_p)
8162 for (j = i; j < description->decls_num; j++)
8164 decl2 = description->decls [j];
8165 if (decl2->mode == dm_insn_reserv
8166 && (DECL_INSN_RESERV (decl2)->important_automata_list
8167 == DECL_INSN_RESERV (decl)->important_automata_list))
8169 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8170 fprintf (output_file, " case %d: /* %s */\n",
8171 DECL_INSN_RESERV (decl2)->insn_num,
8172 DECL_INSN_RESERV (decl2)->name);
8175 (*output_automata_list_code)
8176 (DECL_INSN_RESERV (decl)->important_automata_list);
8182 /* The function outputs a code for evaluation of a minimal delay of
8183 issue of insns which have reservations in given AUTOMATA_LIST. */
8184 static void
8185 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
8187 automata_list_el_t el;
8188 automaton_t automaton;
8190 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8192 automaton = el->automaton;
8193 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8194 output_min_issue_delay_vect_name (output_file, automaton);
8195 fprintf (output_file,
8196 (automaton->min_issue_delay_table_compression_factor != 1
8197 ? " [(" : " ["));
8198 output_translate_vect_name (output_file, automaton);
8199 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8200 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8201 output_chip_member_name (output_file, automaton);
8202 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8203 if (automaton->min_issue_delay_table_compression_factor == 1)
8204 fprintf (output_file, "];\n");
8205 else
8207 fprintf (output_file, ") / %d];\n",
8208 automaton->min_issue_delay_table_compression_factor);
8209 fprintf (output_file, " %s = (%s >> (8 - (",
8210 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8211 output_translate_vect_name (output_file, automaton);
8212 fprintf
8213 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8214 INTERNAL_INSN_CODE_NAME,
8215 automaton->min_issue_delay_table_compression_factor,
8216 8 / automaton->min_issue_delay_table_compression_factor,
8217 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8218 - 1);
8220 if (el == automata_list)
8221 fprintf (output_file, " %s = %s;\n",
8222 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8223 else
8225 fprintf (output_file, " if (%s > %s)\n",
8226 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8227 fprintf (output_file, " %s = %s;\n",
8228 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8231 fprintf (output_file, " break;\n\n");
8234 /* Output function `internal_min_issue_delay'. */
8235 static void
8236 output_internal_min_issue_delay_func (void)
8238 fprintf (output_file,
8239 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8240 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8241 CHIP_NAME, CHIP_PARAMETER_NAME);
8242 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8243 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8244 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8245 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8246 fprintf (output_file,
8247 "\n default:\n %s = -1;\n break;\n }\n",
8248 RESULT_VARIABLE_NAME);
8249 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8250 fprintf (output_file, "}\n\n");
8253 /* The function outputs a code changing state after issue of insns
8254 which have reservations in given AUTOMATA_LIST. */
8255 static void
8256 output_automata_list_transition_code (automata_list_el_t automata_list)
8258 automata_list_el_t el, next_el;
8260 fprintf (output_file, " {\n");
8261 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8262 for (el = automata_list;; el = next_el)
8264 next_el = el->next_automata_list_el;
8265 if (next_el == NULL)
8266 break;
8267 fprintf (output_file, " ");
8268 output_state_member_type (output_file, el->automaton);
8269 fprintf (output_file, " ");
8270 output_temp_chip_member_name (output_file, el->automaton);
8271 fprintf (output_file, ";\n");
8273 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8274 if (comb_vect_p (el->automaton->trans_table))
8276 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8277 output_trans_base_vect_name (output_file, el->automaton);
8278 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8279 output_chip_member_name (output_file, el->automaton);
8280 fprintf (output_file, "] + ");
8281 output_translate_vect_name (output_file, el->automaton);
8282 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8283 fprintf (output_file, " if (");
8284 output_trans_check_vect_name (output_file, el->automaton);
8285 fprintf (output_file, " [%s] != %s->",
8286 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8287 output_chip_member_name (output_file, el->automaton);
8288 fprintf (output_file, ")\n");
8289 fprintf (output_file, " return %s (%s, %s);\n",
8290 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8291 CHIP_PARAMETER_NAME);
8292 fprintf (output_file, " else\n");
8293 fprintf (output_file, " ");
8294 if (el->next_automata_list_el != NULL)
8295 output_temp_chip_member_name (output_file, el->automaton);
8296 else
8298 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8299 output_chip_member_name (output_file, el->automaton);
8301 fprintf (output_file, " = ");
8302 output_trans_comb_vect_name (output_file, el->automaton);
8303 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8305 else
8307 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8308 output_trans_full_vect_name (output_file, el->automaton);
8309 fprintf (output_file, " [");
8310 output_translate_vect_name (output_file, el->automaton);
8311 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8312 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8313 output_chip_member_name (output_file, el->automaton);
8314 fprintf (output_file, " * %d];\n",
8315 el->automaton->insn_equiv_classes_num);
8316 fprintf (output_file, " if (%s >= %d)\n",
8317 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8318 fprintf (output_file, " return %s (%s, %s);\n",
8319 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8320 CHIP_PARAMETER_NAME);
8321 fprintf (output_file, " else\n ");
8322 if (el->next_automata_list_el != NULL)
8323 output_temp_chip_member_name (output_file, el->automaton);
8324 else
8326 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8327 output_chip_member_name (output_file, el->automaton);
8329 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8331 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8332 for (el = automata_list;; el = next_el)
8334 next_el = el->next_automata_list_el;
8335 if (next_el == NULL)
8336 break;
8337 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8338 output_chip_member_name (output_file, el->automaton);
8339 fprintf (output_file, " = ");
8340 output_temp_chip_member_name (output_file, el->automaton);
8341 fprintf (output_file, ";\n");
8343 fprintf (output_file, " return -1;\n");
8344 fprintf (output_file, " }\n");
8347 /* Output function `internal_state_transition'. */
8348 static void
8349 output_internal_trans_func (void)
8351 fprintf (output_file,
8352 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8353 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8354 CHIP_NAME, CHIP_PARAMETER_NAME);
8355 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8356 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8357 output_insn_code_cases (output_automata_list_transition_code);
8358 fprintf (output_file, "\n default:\n return -1;\n }\n");
8359 fprintf (output_file, "}\n\n");
8362 /* Output code
8364 if (insn != 0)
8366 insn_code = dfa_insn_code (insn);
8367 if (insn_code > DFA__ADVANCE_CYCLE)
8368 return code;
8370 else
8371 insn_code = DFA__ADVANCE_CYCLE;
8373 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8374 code denotes CODE. */
8375 static void
8376 output_internal_insn_code_evaluation (const char *insn_name,
8377 const char *insn_code_name,
8378 int code)
8380 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8381 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8382 DFA_INSN_CODE_FUNC_NAME, insn_name);
8383 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8384 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8385 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8386 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8390 /* This function outputs `dfa_insn_code' and its helper function
8391 `dfa_insn_code_enlarge'. */
8392 static void
8393 output_dfa_insn_code_func (void)
8395 /* Emacs c-mode gets really confused if there's a { or } in column 0
8396 inside a string, so don't do that. */
8397 fprintf (output_file, "\
8398 static void\n\
8399 dfa_insn_code_enlarge (int uid)\n\
8400 {\n\
8401 int i = %s;\n\
8402 %s = 2 * uid;\n\
8403 %s = xrealloc (%s,\n\
8404 %s * sizeof(int));\n\
8405 for (; i < %s; i++)\n\
8406 %s[i] = -1;\n}\n\n",
8407 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8408 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8409 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8410 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8411 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8412 DFA_INSN_CODES_VARIABLE_NAME);
8413 fprintf (output_file, "\
8414 static inline int\n%s (rtx %s)\n\
8415 {\n\
8416 int uid = INSN_UID (%s);\n\
8417 int %s;\n\n",
8418 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8419 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8421 fprintf (output_file,
8422 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8423 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8424 fprintf (output_file, " %s = %s[uid];\n",
8425 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8426 fprintf (output_file, "\
8427 if (%s < 0)\n\
8428 {\n\
8429 %s = %s (%s);\n\
8430 %s[uid] = %s;\n\
8431 }\n",
8432 INTERNAL_INSN_CODE_NAME,
8433 INTERNAL_INSN_CODE_NAME,
8434 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8435 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8436 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8439 /* The function outputs PHR interface function `state_transition'. */
8440 static void
8441 output_trans_func (void)
8443 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8444 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8445 INSN_PARAMETER_NAME);
8446 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8447 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8448 INTERNAL_INSN_CODE_NAME, -1);
8449 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8450 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8453 /* The function outputs a code for evaluation of alternative states
8454 number for insns which have reservations in given AUTOMATA_LIST. */
8455 static void
8456 output_automata_list_state_alts_code (automata_list_el_t automata_list)
8458 automata_list_el_t el;
8459 automaton_t automaton;
8461 fprintf (output_file, " {\n");
8462 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8463 if (comb_vect_p (el->automaton->state_alts_table))
8465 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8466 break;
8468 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8470 automaton = el->automaton;
8471 if (comb_vect_p (automaton->state_alts_table))
8473 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8474 output_state_alts_base_vect_name (output_file, automaton);
8475 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8476 output_chip_member_name (output_file, automaton);
8477 fprintf (output_file, "] + ");
8478 output_translate_vect_name (output_file, automaton);
8479 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8480 fprintf (output_file, " if (");
8481 output_state_alts_check_vect_name (output_file, automaton);
8482 fprintf (output_file, " [%s] != %s->",
8483 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8484 output_chip_member_name (output_file, automaton);
8485 fprintf (output_file, ")\n");
8486 fprintf (output_file, " return 0;\n");
8487 fprintf (output_file, " else\n");
8488 fprintf (output_file,
8489 (el == automata_list
8490 ? " %s = " : " %s += "),
8491 RESULT_VARIABLE_NAME);
8492 output_state_alts_comb_vect_name (output_file, automaton);
8493 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8495 else
8497 fprintf (output_file,
8498 (el == automata_list
8499 ? "\n %s = " : " %s += "),
8500 RESULT_VARIABLE_NAME);
8501 output_state_alts_full_vect_name (output_file, automaton);
8502 fprintf (output_file, " [");
8503 output_translate_vect_name (output_file, automaton);
8504 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8505 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8506 output_chip_member_name (output_file, automaton);
8507 fprintf (output_file, " * %d];\n",
8508 automaton->insn_equiv_classes_num);
8511 fprintf (output_file, " break;\n }\n\n");
8514 /* Output function `internal_state_alts'. */
8515 static void
8516 output_internal_state_alts_func (void)
8518 fprintf (output_file,
8519 "static int\n%s (int %s, struct %s *%s)\n",
8520 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8521 CHIP_NAME, CHIP_PARAMETER_NAME);
8522 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8523 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8524 output_insn_code_cases (output_automata_list_state_alts_code);
8525 fprintf (output_file,
8526 "\n default:\n %s = 0;\n break;\n }\n",
8527 RESULT_VARIABLE_NAME);
8528 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8529 fprintf (output_file, "}\n\n");
8532 /* The function outputs PHR interface function `state_alts'. */
8533 static void
8534 output_state_alts_func (void)
8536 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8537 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8538 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8539 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8540 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8541 INTERNAL_INSN_CODE_NAME, 0);
8542 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8543 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8546 /* Output function `min_issue_delay'. */
8547 static void
8548 output_min_issue_delay_func (void)
8550 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8551 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8552 INSN_PARAMETER_NAME);
8553 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8554 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8555 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8556 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8557 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8558 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8559 fprintf (output_file, " }\n else\n %s = %s;\n",
8560 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8561 fprintf (output_file, "\n return %s (%s, %s);\n",
8562 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8563 STATE_NAME);
8564 fprintf (output_file, "}\n\n");
8567 /* Output function `internal_dead_lock'. */
8568 static void
8569 output_internal_dead_lock_func (void)
8571 automaton_t automaton;
8573 fprintf (output_file, "static int\n%s (struct %s *%s)\n",
8574 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8575 fprintf (output_file, "{\n");
8576 for (automaton = description->first_automaton;
8577 automaton != NULL;
8578 automaton = automaton->next_automaton)
8580 fprintf (output_file, " if (");
8581 output_dead_lock_vect_name (output_file, automaton);
8582 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8583 output_chip_member_name (output_file, automaton);
8584 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8586 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8589 /* The function outputs PHR interface function `state_dead_lock_p'. */
8590 static void
8591 output_dead_lock_func (void)
8593 fprintf (output_file, "int\n%s (%s %s)\n",
8594 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8595 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8596 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8599 /* Output function `internal_reset'. */
8600 static void
8601 output_internal_reset_func (void)
8603 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8604 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8605 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8606 CHIP_PARAMETER_NAME, CHIP_NAME);
8609 /* The function outputs PHR interface function `state_size'. */
8610 static void
8611 output_size_func (void)
8613 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8614 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8617 /* The function outputs PHR interface function `state_reset'. */
8618 static void
8619 output_reset_func (void)
8621 fprintf (output_file, "void\n%s (%s %s)\n",
8622 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8623 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8624 STATE_NAME);
8627 /* Output function `min_insn_conflict_delay'. */
8628 static void
8629 output_min_insn_conflict_delay_func (void)
8631 fprintf (output_file,
8632 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8633 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8634 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8635 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8636 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8637 INTERNAL_INSN2_CODE_NAME);
8638 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8639 INTERNAL_INSN_CODE_NAME, 0);
8640 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8641 INTERNAL_INSN2_CODE_NAME, 0);
8642 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8643 CHIP_NAME, STATE_NAME, CHIP_NAME);
8644 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8645 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8646 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8647 fprintf (output_file, " return %s (%s, &%s);\n",
8648 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8649 CHIP_NAME);
8650 fprintf (output_file, "}\n\n");
8653 /* Output function `internal_insn_latency'. */
8654 static void
8655 output_internal_insn_latency_func (void)
8657 decl_t decl;
8658 struct bypass_decl *bypass;
8659 int i, j, col;
8660 const char *tabletype = "unsigned char";
8662 /* Find the smallest integer type that can hold all the default
8663 latency values. */
8664 for (i = 0; i < description->decls_num; i++)
8665 if (description->decls[i]->mode == dm_insn_reserv)
8667 decl = description->decls[i];
8668 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8669 && tabletype[0] != 'i') /* Don't shrink it. */
8670 tabletype = "unsigned short";
8671 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8672 tabletype = "int";
8675 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8676 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8677 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8678 INSN2_PARAMETER_NAME);
8679 fprintf (output_file, "{\n");
8681 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8683 fputs (" return 0;\n}\n\n", output_file);
8684 return;
8687 fprintf (output_file, " static const %s default_latencies[] =\n {",
8688 tabletype);
8690 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8691 if (description->decls[i]->mode == dm_insn_reserv
8692 && description->decls[i] != advance_cycle_insn_decl)
8694 if ((col = (col+1) % 8) == 0)
8695 fputs ("\n ", output_file);
8696 decl = description->decls[i];
8697 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
8698 abort ();
8699 fprintf (output_file, "% 4d,",
8700 DECL_INSN_RESERV (decl)->default_latency);
8702 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8703 abort ();
8704 fputs ("\n };\n", output_file);
8706 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8707 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8708 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8710 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8711 for (i = 0; i < description->decls_num; i++)
8712 if (description->decls[i]->mode == dm_insn_reserv
8713 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8715 decl = description->decls [i];
8716 fprintf (output_file,
8717 " case %d:\n switch (%s)\n {\n",
8718 DECL_INSN_RESERV (decl)->insn_num,
8719 INTERNAL_INSN2_CODE_NAME);
8720 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8721 bypass != NULL;
8722 bypass = bypass->next)
8724 if (bypass->in_insn_reserv->insn_num
8725 == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8726 abort ();
8727 fprintf (output_file, " case %d:\n",
8728 bypass->in_insn_reserv->insn_num);
8729 if (bypass->bypass_guard_name == NULL)
8730 fprintf (output_file, " return %d;\n",
8731 bypass->latency);
8732 else
8734 fprintf (output_file,
8735 " if (%s (%s, %s))\n",
8736 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8737 INSN2_PARAMETER_NAME);
8738 fprintf (output_file,
8739 " return %d;\n break;\n",
8740 bypass->latency);
8743 fputs (" }\n break;\n", output_file);
8746 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8747 INTERNAL_INSN_CODE_NAME);
8750 /* The function outputs PHR interface function `insn_latency'. */
8751 static void
8752 output_insn_latency_func (void)
8754 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8755 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8756 fprintf (output_file, "{\n int %s, %s;\n",
8757 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8758 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8759 INTERNAL_INSN_CODE_NAME, 0);
8760 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8761 INTERNAL_INSN2_CODE_NAME, 0);
8762 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8763 INTERNAL_INSN_LATENCY_FUNC_NAME,
8764 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8765 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8768 /* The function outputs PHR interface function `print_reservation'. */
8769 static void
8770 output_print_reservation_func (void)
8772 decl_t decl;
8773 int i, j;
8775 fprintf (output_file,
8776 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8777 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8778 INSN_PARAMETER_NAME);
8780 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8782 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8783 NOTHING_NAME, FILE_PARAMETER_NAME);
8784 return;
8788 fputs (" static const char *const reservation_names[] =\n {",
8789 output_file);
8791 for (i = 0, j = 0; i < description->decls_num; i++)
8793 decl = description->decls [i];
8794 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8796 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
8797 abort ();
8798 fprintf (output_file, "\n \"%s\",",
8799 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8800 finish_regexp_representation ();
8803 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8804 abort ();
8806 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8807 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8809 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8810 INSN_PARAMETER_NAME,
8811 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8812 fprintf (output_file, " else\n\
8813 {\n\
8814 %s = %s (%s);\n\
8815 if (%s > %s)\n\
8816 %s = %s;\n\
8817 }\n",
8818 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8819 INSN_PARAMETER_NAME,
8820 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8821 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8823 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8824 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8827 /* The following function is used to sort unit declaration by their
8828 names. */
8829 static int
8830 units_cmp (const void *unit1, const void *unit2)
8832 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8833 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8835 return strcmp (u1->name, u2->name);
8838 /* The following macro value is name of struct containing unit name
8839 and unit code. */
8840 #define NAME_CODE_STRUCT_NAME "name_code"
8842 /* The following macro value is name of table of struct name_code. */
8843 #define NAME_CODE_TABLE_NAME "name_code_table"
8845 /* The following macro values are member names for struct name_code. */
8846 #define NAME_MEMBER_NAME "name"
8847 #define CODE_MEMBER_NAME "code"
8849 /* The following macro values are local variable names for function
8850 `get_cpu_unit_code'. */
8851 #define CMP_VARIABLE_NAME "cmp"
8852 #define LOW_VARIABLE_NAME "l"
8853 #define MIDDLE_VARIABLE_NAME "m"
8854 #define HIGH_VARIABLE_NAME "h"
8856 /* The following function outputs function to obtain internal cpu unit
8857 code by the cpu unit name. */
8858 static void
8859 output_get_cpu_unit_code_func (void)
8861 int i;
8862 unit_decl_t *units;
8864 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8865 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8866 CPU_UNIT_NAME_PARAMETER_NAME);
8867 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8868 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8869 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8870 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8871 fprintf (output_file, " static struct %s %s [] =\n {\n",
8872 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8873 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8874 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8875 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8876 for (i = 0; i < description->units_num; i++)
8877 if (units [i]->query_p)
8878 fprintf (output_file, " {\"%s\", %d},\n",
8879 units[i]->name, units[i]->query_num);
8880 fprintf (output_file, " };\n\n");
8881 fprintf (output_file, " /* The following is binary search: */\n");
8882 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8883 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8884 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8885 fprintf (output_file, " while (%s <= %s)\n {\n",
8886 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8887 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8888 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8889 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8890 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8891 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8892 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8893 fprintf (output_file, " %s = %s - 1;\n",
8894 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8895 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8896 fprintf (output_file, " %s = %s + 1;\n",
8897 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8898 fprintf (output_file, " else\n");
8899 fprintf (output_file, " return %s [%s].%s;\n }\n",
8900 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8901 fprintf (output_file, " return -1;\n}\n\n");
8902 free (units);
8905 /* The following function outputs function to check reservation of cpu
8906 unit (its internal code will be passed as the function argument) in
8907 given cpu state. */
8908 static void
8909 output_cpu_unit_reservation_p (void)
8911 automaton_t automaton;
8913 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8914 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8915 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8916 CPU_CODE_PARAMETER_NAME);
8917 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8918 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8919 description->query_units_num);
8920 for (automaton = description->first_automaton;
8921 automaton != NULL;
8922 automaton = automaton->next_automaton)
8924 fprintf (output_file, " if ((");
8925 output_reserved_units_table_name (output_file, automaton);
8926 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8927 output_chip_member_name (output_file, automaton);
8928 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8929 (description->query_units_num + 7) / 8,
8930 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8931 fprintf (output_file, " return 1;\n");
8933 fprintf (output_file, " return 0;\n}\n\n");
8936 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
8937 static void
8938 output_dfa_clean_insn_cache_func (void)
8940 fprintf (output_file,
8941 "void\n%s (void)\n{\n int %s;\n\n",
8942 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8943 fprintf (output_file,
8944 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8945 I_VARIABLE_NAME, I_VARIABLE_NAME,
8946 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8947 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8950 /* The function outputs PHR interface function `dfa_start'. */
8951 static void
8952 output_dfa_start_func (void)
8954 fprintf (output_file,
8955 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8956 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8957 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8958 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8959 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8962 /* The function outputs PHR interface function `dfa_finish'. */
8963 static void
8964 output_dfa_finish_func (void)
8966 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8967 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8972 /* The page contains code for output description file (readable
8973 representation of original description and generated DFA(s). */
8975 /* The function outputs string representation of IR reservation. */
8976 static void
8977 output_regexp (regexp_t regexp)
8979 fprintf (output_description_file, "%s", regexp_representation (regexp));
8980 finish_regexp_representation ();
8983 /* Output names of units in LIST separated by comma. */
8984 static void
8985 output_unit_set_el_list (unit_set_el_t list)
8987 unit_set_el_t el;
8989 for (el = list; el != NULL; el = el->next_unit_set_el)
8991 if (el != list)
8992 fprintf (output_description_file, ", ");
8993 fprintf (output_description_file, "%s", el->unit_decl->name);
8997 /* Output patterns in LIST separated by comma. */
8998 static void
8999 output_pattern_set_el_list (pattern_set_el_t list)
9001 pattern_set_el_t el;
9002 int i;
9004 for (el = list; el != NULL; el = el->next_pattern_set_el)
9006 if (el != list)
9007 fprintf (output_description_file, ", ");
9008 for (i = 0; i < el->units_num; i++)
9009 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
9010 el->unit_decls [i]->name);
9014 /* The function outputs string representation of IR define_reservation
9015 and define_insn_reservation. */
9016 static void
9017 output_description (void)
9019 decl_t decl;
9020 int i;
9022 for (i = 0; i < description->decls_num; i++)
9024 decl = description->decls [i];
9025 if (decl->mode == dm_unit)
9027 if (DECL_UNIT (decl)->excl_list != NULL)
9029 fprintf (output_description_file, "unit %s exlusion_set: ",
9030 DECL_UNIT (decl)->name);
9031 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
9032 fprintf (output_description_file, "\n");
9034 if (DECL_UNIT (decl)->presence_list != NULL)
9036 fprintf (output_description_file, "unit %s presence_set: ",
9037 DECL_UNIT (decl)->name);
9038 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
9039 fprintf (output_description_file, "\n");
9041 if (DECL_UNIT (decl)->final_presence_list != NULL)
9043 fprintf (output_description_file, "unit %s final_presence_set: ",
9044 DECL_UNIT (decl)->name);
9045 output_pattern_set_el_list
9046 (DECL_UNIT (decl)->final_presence_list);
9047 fprintf (output_description_file, "\n");
9049 if (DECL_UNIT (decl)->absence_list != NULL)
9051 fprintf (output_description_file, "unit %s absence_set: ",
9052 DECL_UNIT (decl)->name);
9053 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
9054 fprintf (output_description_file, "\n");
9056 if (DECL_UNIT (decl)->final_absence_list != NULL)
9058 fprintf (output_description_file, "unit %s final_absence_set: ",
9059 DECL_UNIT (decl)->name);
9060 output_pattern_set_el_list
9061 (DECL_UNIT (decl)->final_absence_list);
9062 fprintf (output_description_file, "\n");
9066 fprintf (output_description_file, "\n");
9067 for (i = 0; i < description->decls_num; i++)
9069 decl = description->decls [i];
9070 if (decl->mode == dm_reserv)
9072 fprintf (output_description_file, "reservation %s: ",
9073 DECL_RESERV (decl)->name);
9074 output_regexp (DECL_RESERV (decl)->regexp);
9075 fprintf (output_description_file, "\n");
9077 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9079 fprintf (output_description_file, "insn reservation %s ",
9080 DECL_INSN_RESERV (decl)->name);
9081 print_rtl (output_description_file,
9082 DECL_INSN_RESERV (decl)->condexp);
9083 fprintf (output_description_file, ": ");
9084 output_regexp (DECL_INSN_RESERV (decl)->regexp);
9085 fprintf (output_description_file, "\n");
9087 else if (decl->mode == dm_bypass)
9088 fprintf (output_description_file, "bypass %d %s %s\n",
9089 DECL_BYPASS (decl)->latency,
9090 DECL_BYPASS (decl)->out_insn_name,
9091 DECL_BYPASS (decl)->in_insn_name);
9093 fprintf (output_description_file, "\n\f\n");
9096 /* The function outputs name of AUTOMATON. */
9097 static void
9098 output_automaton_name (FILE *f, automaton_t automaton)
9100 if (automaton->corresponding_automaton_decl == NULL)
9101 fprintf (f, "#%d", automaton->automaton_order_num);
9102 else
9103 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
9106 /* Maximal length of line for pretty printing into description
9107 file. */
9108 #define MAX_LINE_LENGTH 70
9110 /* The function outputs units name belonging to AUTOMATON. */
9111 static void
9112 output_automaton_units (automaton_t automaton)
9114 decl_t decl;
9115 char *name;
9116 int curr_line_length;
9117 int there_is_an_automaton_unit;
9118 int i;
9120 fprintf (output_description_file, "\n Coresponding units:\n");
9121 fprintf (output_description_file, " ");
9122 curr_line_length = 4;
9123 there_is_an_automaton_unit = 0;
9124 for (i = 0; i < description->decls_num; i++)
9126 decl = description->decls [i];
9127 if (decl->mode == dm_unit
9128 && (DECL_UNIT (decl)->corresponding_automaton_num
9129 == automaton->automaton_order_num))
9131 there_is_an_automaton_unit = 1;
9132 name = DECL_UNIT (decl)->name;
9133 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
9135 curr_line_length = strlen (name) + 4;
9136 fprintf (output_description_file, "\n ");
9138 else
9140 curr_line_length += strlen (name) + 1;
9141 fprintf (output_description_file, " ");
9143 fprintf (output_description_file, "%s", name);
9146 if (!there_is_an_automaton_unit)
9147 fprintf (output_description_file, "<None>");
9148 fprintf (output_description_file, "\n\n");
9151 /* The following variable is used for forming array of all possible cpu unit
9152 reservations described by the current DFA state. */
9153 static vla_ptr_t state_reservs;
9155 /* The function forms `state_reservs' for STATE. */
9156 static void
9157 add_state_reservs (state_t state)
9159 alt_state_t curr_alt_state;
9160 reserv_sets_t reservs;
9162 if (state->component_states != NULL)
9163 for (curr_alt_state = state->component_states;
9164 curr_alt_state != NULL;
9165 curr_alt_state = curr_alt_state->next_sorted_alt_state)
9166 add_state_reservs (curr_alt_state->state);
9167 else
9169 reservs = state->reservs;
9170 VLA_PTR_ADD (state_reservs, reservs);
9174 /* The function outputs readable representation of all out arcs of
9175 STATE. */
9176 static void
9177 output_state_arcs (state_t state)
9179 arc_t arc;
9180 ainsn_t ainsn;
9181 char *insn_name;
9182 int curr_line_length;
9184 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
9186 ainsn = arc->insn;
9187 if (!ainsn->first_insn_with_same_reservs)
9188 abort ();
9189 fprintf (output_description_file, " ");
9190 curr_line_length = 7;
9191 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
9194 insn_name = ainsn->insn_reserv_decl->name;
9195 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
9197 if (ainsn != arc->insn)
9199 fprintf (output_description_file, ",\n ");
9200 curr_line_length = strlen (insn_name) + 6;
9202 else
9203 curr_line_length += strlen (insn_name);
9205 else
9207 curr_line_length += strlen (insn_name);
9208 if (ainsn != arc->insn)
9210 curr_line_length += 2;
9211 fprintf (output_description_file, ", ");
9214 fprintf (output_description_file, "%s", insn_name);
9215 ainsn = ainsn->next_same_reservs_insn;
9217 while (ainsn != NULL);
9218 fprintf (output_description_file, " %d (%d)\n",
9219 arc->to_state->order_state_num, arc->state_alts);
9221 fprintf (output_description_file, "\n");
9224 /* The following function is used for sorting possible cpu unit
9225 reservation of a DFA state. */
9226 static int
9227 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
9229 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9230 *(reserv_sets_t *) reservs_ptr_2);
9233 /* The following function is used for sorting possible cpu unit
9234 reservation of a DFA state. */
9235 static void
9236 remove_state_duplicate_reservs (void)
9238 reserv_sets_t *reservs_ptr;
9239 reserv_sets_t *last_formed_reservs_ptr;
9241 last_formed_reservs_ptr = NULL;
9242 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9243 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9244 reservs_ptr++)
9245 if (last_formed_reservs_ptr == NULL)
9246 last_formed_reservs_ptr = reservs_ptr;
9247 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9249 ++last_formed_reservs_ptr;
9250 *last_formed_reservs_ptr = *reservs_ptr;
9252 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9255 /* The following function output readable representation of DFA(s)
9256 state used for fast recognition of pipeline hazards. State is
9257 described by possible (current and scheduled) cpu unit
9258 reservations. */
9259 static void
9260 output_state (state_t state)
9262 reserv_sets_t *reservs_ptr;
9264 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9265 fprintf (output_description_file, " State #%d", state->order_state_num);
9266 fprintf (output_description_file,
9267 state->new_cycle_p ? " (new cycle)\n" : "\n");
9268 add_state_reservs (state);
9269 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9270 sizeof (reserv_sets_t), state_reservs_cmp);
9271 remove_state_duplicate_reservs ();
9272 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9273 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9274 reservs_ptr++)
9276 fprintf (output_description_file, " ");
9277 output_reserv_sets (output_description_file, *reservs_ptr);
9278 fprintf (output_description_file, "\n");
9280 fprintf (output_description_file, "\n");
9281 output_state_arcs (state);
9282 VLA_PTR_DELETE (state_reservs);
9285 /* The following function output readable representation of
9286 DFAs used for fast recognition of pipeline hazards. */
9287 static void
9288 output_automaton_descriptions (void)
9290 automaton_t automaton;
9292 for (automaton = description->first_automaton;
9293 automaton != NULL;
9294 automaton = automaton->next_automaton)
9296 fprintf (output_description_file, "\nAutomaton ");
9297 output_automaton_name (output_description_file, automaton);
9298 fprintf (output_description_file, "\n");
9299 output_automaton_units (automaton);
9300 pass_states (automaton, output_state);
9306 /* The page contains top level function for generation DFA(s) used for
9307 PHR. */
9309 /* The function outputs statistics about work of different phases of
9310 DFA generator. */
9311 static void
9312 output_statistics (FILE *f)
9314 automaton_t automaton;
9315 int states_num;
9316 #ifndef NDEBUG
9317 int transition_comb_vect_els = 0;
9318 int transition_full_vect_els = 0;
9319 int state_alts_comb_vect_els = 0;
9320 int state_alts_full_vect_els = 0;
9321 int min_issue_delay_vect_els = 0;
9322 #endif
9324 for (automaton = description->first_automaton;
9325 automaton != NULL;
9326 automaton = automaton->next_automaton)
9328 fprintf (f, "\nAutomaton ");
9329 output_automaton_name (f, automaton);
9330 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9331 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9332 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9333 automaton->DFA_states_num, automaton->DFA_arcs_num);
9334 states_num = automaton->DFA_states_num;
9335 if (!no_minimization_flag)
9337 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9338 automaton->minimal_DFA_states_num,
9339 automaton->minimal_DFA_arcs_num);
9340 states_num = automaton->minimal_DFA_states_num;
9342 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9343 description->insns_num, automaton->insn_equiv_classes_num);
9344 #ifndef NDEBUG
9345 fprintf
9346 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9347 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9348 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9349 (comb_vect_p (automaton->trans_table)
9350 ? "use comb vect" : "use simple vect"));
9351 fprintf
9352 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9353 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9354 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9355 (comb_vect_p (automaton->state_alts_table)
9356 ? "use comb vect" : "use simple vect"));
9357 fprintf
9358 (f, "%5ld min delay table els, compression factor %d\n",
9359 (long) states_num * automaton->insn_equiv_classes_num,
9360 automaton->min_issue_delay_table_compression_factor);
9361 transition_comb_vect_els
9362 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9363 transition_full_vect_els
9364 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9365 state_alts_comb_vect_els
9366 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9367 state_alts_full_vect_els
9368 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9369 min_issue_delay_vect_els
9370 += states_num * automaton->insn_equiv_classes_num;
9371 #endif
9373 #ifndef NDEBUG
9374 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9375 allocated_states_num, allocated_arcs_num);
9376 fprintf (f, "%5d all allocated alternative states\n",
9377 allocated_alt_states_num);
9378 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9379 transition_comb_vect_els, transition_full_vect_els);
9380 fprintf
9381 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9382 state_alts_comb_vect_els, state_alts_full_vect_els);
9383 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9384 fprintf (f, "%5d locked states num\n", locked_states_num);
9385 #endif
9388 /* The function output times of work of different phases of DFA
9389 generator. */
9390 static void
9391 output_time_statistics (FILE *f)
9393 fprintf (f, "\n transformation: ");
9394 print_active_time (f, transform_time);
9395 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9396 print_active_time (f, NDFA_time);
9397 if (ndfa_flag)
9399 fprintf (f, ", NDFA -> DFA: ");
9400 print_active_time (f, NDFA_to_DFA_time);
9402 fprintf (f, "\n DFA minimization: ");
9403 print_active_time (f, minimize_time);
9404 fprintf (f, ", making insn equivalence: ");
9405 print_active_time (f, equiv_time);
9406 fprintf (f, "\n all automaton generation: ");
9407 print_active_time (f, automaton_generation_time);
9408 fprintf (f, ", output: ");
9409 print_active_time (f, output_time);
9410 fprintf (f, "\n");
9413 /* The function generates DFA (deterministic finite state automaton)
9414 for fast recognition of pipeline hazards. No errors during
9415 checking must be fixed before this function call. */
9416 static void
9417 generate (void)
9419 automata_num = split_argument;
9420 if (description->units_num < automata_num)
9421 automata_num = description->units_num;
9422 initiate_states ();
9423 initiate_arcs ();
9424 initiate_automata_lists ();
9425 initiate_pass_states ();
9426 initiate_excl_sets ();
9427 initiate_presence_absence_pattern_sets ();
9428 automaton_generation_time = create_ticker ();
9429 create_automata ();
9430 ticker_off (&automaton_generation_time);
9435 /* The following function creates insn attribute whose values are
9436 number alternatives in insn reservations. */
9437 static void
9438 make_insn_alts_attr (void)
9440 int i, insn_num;
9441 decl_t decl;
9442 rtx condexp;
9444 condexp = rtx_alloc (COND);
9445 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9446 XEXP (condexp, 1) = make_numeric_value (0);
9447 for (i = insn_num = 0; i < description->decls_num; i++)
9449 decl = description->decls [i];
9450 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9452 XVECEXP (condexp, 0, 2 * insn_num)
9453 = DECL_INSN_RESERV (decl)->condexp;
9454 XVECEXP (condexp, 0, 2 * insn_num + 1)
9455 = make_numeric_value
9456 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9457 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9458 ->transformed_regexp)->regexps_num);
9459 insn_num++;
9462 if (description->insns_num != insn_num + 1)
9463 abort ();
9464 make_internal_attr (attr_printf (sizeof ("*")
9465 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9466 "*%s", INSN_ALTS_FUNC_NAME),
9467 condexp, ATTR_NONE);
9472 /* The following function creates attribute which is order number of
9473 insn in pipeline hazard description translator. */
9474 static void
9475 make_internal_dfa_insn_code_attr (void)
9477 int i, insn_num;
9478 decl_t decl;
9479 rtx condexp;
9481 condexp = rtx_alloc (COND);
9482 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9483 XEXP (condexp, 1)
9484 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9485 ->insn_num + 1);
9486 for (i = insn_num = 0; i < description->decls_num; i++)
9488 decl = description->decls [i];
9489 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9491 XVECEXP (condexp, 0, 2 * insn_num)
9492 = DECL_INSN_RESERV (decl)->condexp;
9493 XVECEXP (condexp, 0, 2 * insn_num + 1)
9494 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9495 insn_num++;
9498 if (description->insns_num != insn_num + 1)
9499 abort ();
9500 make_internal_attr
9501 (attr_printf (sizeof ("*")
9502 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9503 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9504 condexp, ATTR_STATIC);
9509 /* The following function creates attribute which order number of insn
9510 in pipeline hazard description translator. */
9511 static void
9512 make_default_insn_latency_attr (void)
9514 int i, insn_num;
9515 decl_t decl;
9516 rtx condexp;
9518 condexp = rtx_alloc (COND);
9519 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9520 XEXP (condexp, 1) = make_numeric_value (0);
9521 for (i = insn_num = 0; i < description->decls_num; i++)
9523 decl = description->decls [i];
9524 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9526 XVECEXP (condexp, 0, 2 * insn_num)
9527 = DECL_INSN_RESERV (decl)->condexp;
9528 XVECEXP (condexp, 0, 2 * insn_num + 1)
9529 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9530 insn_num++;
9533 if (description->insns_num != insn_num + 1)
9534 abort ();
9535 make_internal_attr (attr_printf (sizeof ("*")
9536 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9537 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9538 condexp, ATTR_NONE);
9543 /* The following function creates attribute which returns 1 if given
9544 output insn has bypassing and 0 otherwise. */
9545 static void
9546 make_bypass_attr (void)
9548 int i, bypass_insn;
9549 int bypass_insns_num = 0;
9550 decl_t decl;
9551 rtx result_rtx;
9553 for (i = 0; i < description->decls_num; i++)
9555 decl = description->decls [i];
9556 if (decl->mode == dm_insn_reserv
9557 && DECL_INSN_RESERV (decl)->condexp != NULL
9558 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9559 bypass_insns_num++;
9561 if (bypass_insns_num == 0)
9562 result_rtx = make_numeric_value (0);
9563 else
9565 result_rtx = rtx_alloc (COND);
9566 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9567 XEXP (result_rtx, 1) = make_numeric_value (0);
9569 for (i = bypass_insn = 0; i < description->decls_num; i++)
9571 decl = description->decls [i];
9572 if (decl->mode == dm_insn_reserv
9573 && DECL_INSN_RESERV (decl)->condexp != NULL
9574 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9576 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9577 = DECL_INSN_RESERV (decl)->condexp;
9578 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9579 = make_numeric_value (1);
9580 bypass_insn++;
9584 make_internal_attr (attr_printf (sizeof ("*")
9585 + strlen (BYPASS_P_FUNC_NAME) + 1,
9586 "*%s", BYPASS_P_FUNC_NAME),
9587 result_rtx, ATTR_NONE);
9592 /* This page mainly contains top level functions of pipeline hazards
9593 description translator. */
9595 /* The following macro value is suffix of name of description file of
9596 pipeline hazards description translator. */
9597 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9599 /* The function returns suffix of given file name. The returned
9600 string can not be changed. */
9601 static const char *
9602 file_name_suffix (const char *file_name)
9604 const char *last_period;
9606 for (last_period = NULL; *file_name != '\0'; file_name++)
9607 if (*file_name == '.')
9608 last_period = file_name;
9609 return (last_period == NULL ? file_name : last_period);
9612 /* The function returns base name of given file name, i.e. pointer to
9613 first char after last `/' (or `\' for WIN32) in given file name,
9614 given file name itself if the directory name is absent. The
9615 returned string can not be changed. */
9616 static const char *
9617 base_file_name (const char *file_name)
9619 int directory_name_length;
9621 directory_name_length = strlen (file_name);
9622 #ifdef WIN32
9623 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9624 && file_name[directory_name_length] != '\\')
9625 #else
9626 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9627 #endif
9628 directory_name_length--;
9629 return file_name + directory_name_length + 1;
9632 /* The following is top level function to initialize the work of
9633 pipeline hazards description translator. */
9634 void
9635 initiate_automaton_gen (int argc, char **argv)
9637 const char *base_name;
9638 int i;
9640 ndfa_flag = 0;
9641 split_argument = 0; /* default value */
9642 no_minimization_flag = 0;
9643 time_flag = 0;
9644 v_flag = 0;
9645 w_flag = 0;
9646 progress_flag = 0;
9647 for (i = 2; i < argc; i++)
9648 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9649 no_minimization_flag = 1;
9650 else if (strcmp (argv [i], TIME_OPTION) == 0)
9651 time_flag = 1;
9652 else if (strcmp (argv [i], V_OPTION) == 0)
9653 v_flag = 1;
9654 else if (strcmp (argv [i], W_OPTION) == 0)
9655 w_flag = 1;
9656 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9657 ndfa_flag = 1;
9658 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9659 progress_flag = 1;
9660 else if (strcmp (argv [i], "-split") == 0)
9662 if (i + 1 >= argc)
9663 fatal ("-split has no argument.");
9664 fatal ("option `-split' has not been implemented yet\n");
9665 /* split_argument = atoi (argument_vect [i + 1]); */
9667 VLA_PTR_CREATE (decls, 150, "decls");
9668 /* Initialize IR storage. */
9669 obstack_init (&irp);
9670 initiate_automaton_decl_table ();
9671 initiate_insn_decl_table ();
9672 initiate_decl_table ();
9673 output_file = stdout;
9674 output_description_file = NULL;
9675 base_name = base_file_name (argv[1]);
9676 obstack_grow (&irp, base_name,
9677 strlen (base_name) - strlen (file_name_suffix (base_name)));
9678 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9679 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9680 obstack_1grow (&irp, '\0');
9681 output_description_file_name = obstack_base (&irp);
9682 obstack_finish (&irp);
9685 /* The following function checks existence at least one arc marked by
9686 each insn. */
9687 static void
9688 check_automata_insn_issues (void)
9690 automaton_t automaton;
9691 ainsn_t ainsn, reserv_ainsn;
9693 for (automaton = description->first_automaton;
9694 automaton != NULL;
9695 automaton = automaton->next_automaton)
9697 for (ainsn = automaton->ainsn_list;
9698 ainsn != NULL;
9699 ainsn = ainsn->next_ainsn)
9700 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9702 for (reserv_ainsn = ainsn;
9703 reserv_ainsn != NULL;
9704 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9705 if (automaton->corresponding_automaton_decl != NULL)
9707 if (!w_flag)
9708 error ("Automaton `%s': Insn `%s' will never be issued",
9709 automaton->corresponding_automaton_decl->name,
9710 reserv_ainsn->insn_reserv_decl->name);
9711 else
9712 warning
9713 ("Automaton `%s': Insn `%s' will never be issued",
9714 automaton->corresponding_automaton_decl->name,
9715 reserv_ainsn->insn_reserv_decl->name);
9717 else
9719 if (!w_flag)
9720 error ("Insn `%s' will never be issued",
9721 reserv_ainsn->insn_reserv_decl->name);
9722 else
9723 warning ("Insn `%s' will never be issued",
9724 reserv_ainsn->insn_reserv_decl->name);
9730 /* The following vla is used for storing pointers to all achieved
9731 states. */
9732 static vla_ptr_t automaton_states;
9734 /* This function is called by function pass_states to add an achieved
9735 STATE. */
9736 static void
9737 add_automaton_state (state_t state)
9739 VLA_PTR_ADD (automaton_states, state);
9742 /* The following function forms list of important automata (whose
9743 states may be changed after the insn issue) for each insn. */
9744 static void
9745 form_important_insn_automata_lists (void)
9747 automaton_t automaton;
9748 state_t *state_ptr;
9749 decl_t decl;
9750 ainsn_t ainsn;
9751 arc_t arc;
9752 int i;
9754 VLA_PTR_CREATE (automaton_states, 1500,
9755 "automaton states for forming important insn automata sets");
9756 /* Mark important ainsns. */
9757 for (automaton = description->first_automaton;
9758 automaton != NULL;
9759 automaton = automaton->next_automaton)
9761 VLA_PTR_NULLIFY (automaton_states);
9762 pass_states (automaton, add_automaton_state);
9763 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9764 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9765 state_ptr++)
9767 for (arc = first_out_arc (*state_ptr);
9768 arc != NULL;
9769 arc = next_out_arc (arc))
9770 if (arc->to_state != *state_ptr)
9772 if (!arc->insn->first_insn_with_same_reservs)
9773 abort ();
9774 for (ainsn = arc->insn;
9775 ainsn != NULL;
9776 ainsn = ainsn->next_same_reservs_insn)
9777 ainsn->important_p = TRUE;
9781 VLA_PTR_DELETE (automaton_states);
9782 /* Create automata sets for the insns. */
9783 for (i = 0; i < description->decls_num; i++)
9785 decl = description->decls [i];
9786 if (decl->mode == dm_insn_reserv)
9788 automata_list_start ();
9789 for (automaton = description->first_automaton;
9790 automaton != NULL;
9791 automaton = automaton->next_automaton)
9792 for (ainsn = automaton->ainsn_list;
9793 ainsn != NULL;
9794 ainsn = ainsn->next_ainsn)
9795 if (ainsn->important_p
9796 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9798 automata_list_add (automaton);
9799 break;
9801 DECL_INSN_RESERV (decl)->important_automata_list
9802 = automata_list_finish ();
9808 /* The following is top level function to generate automat(a,on) for
9809 fast recognition of pipeline hazards. */
9810 void
9811 expand_automata (void)
9813 int i;
9815 description = create_node (sizeof (struct description)
9816 /* One entry for cycle advancing insn. */
9817 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9818 description->decls_num = VLA_PTR_LENGTH (decls);
9819 description->query_units_num = 0;
9820 for (i = 0; i < description->decls_num; i++)
9822 description->decls [i] = VLA_PTR (decls, i);
9823 if (description->decls [i]->mode == dm_unit
9824 && DECL_UNIT (description->decls [i])->query_p)
9825 DECL_UNIT (description->decls [i])->query_num
9826 = description->query_units_num++;
9828 all_time = create_ticker ();
9829 check_time = create_ticker ();
9830 if (progress_flag)
9831 fprintf (stderr, "Check description...");
9832 check_all_description ();
9833 if (progress_flag)
9834 fprintf (stderr, "done\n");
9835 ticker_off (&check_time);
9836 generation_time = create_ticker ();
9837 if (!have_error)
9839 transform_insn_regexps ();
9840 check_unit_distributions_to_automata ();
9842 if (!have_error)
9844 generate ();
9845 check_automata_insn_issues ();
9847 if (!have_error)
9849 form_important_insn_automata_lists ();
9850 if (progress_flag)
9851 fprintf (stderr, "Generation of attributes...");
9852 make_internal_dfa_insn_code_attr ();
9853 make_insn_alts_attr ();
9854 make_default_insn_latency_attr ();
9855 make_bypass_attr ();
9856 if (progress_flag)
9857 fprintf (stderr, "done\n");
9859 ticker_off (&generation_time);
9860 ticker_off (&all_time);
9861 if (progress_flag)
9862 fprintf (stderr, "All other genattrtab stuff...");
9865 /* The following is top level function to output PHR and to finish
9866 work with pipeline description translator. */
9867 void
9868 write_automata (void)
9870 if (progress_flag)
9871 fprintf (stderr, "done\n");
9872 if (have_error)
9873 fatal ("Errors in DFA description");
9874 ticker_on (&all_time);
9875 output_time = create_ticker ();
9876 if (progress_flag)
9877 fprintf (stderr, "Forming and outputting automata tables...");
9878 output_dfa_max_issue_rate ();
9879 output_tables ();
9880 if (progress_flag)
9882 fprintf (stderr, "done\n");
9883 fprintf (stderr, "Output functions to work with automata...");
9885 output_chip_definitions ();
9886 output_max_insn_queue_index_def ();
9887 output_internal_min_issue_delay_func ();
9888 output_internal_trans_func ();
9889 /* Cache of insn dfa codes: */
9890 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9891 fprintf (output_file, "\nstatic int %s;\n\n",
9892 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9893 output_dfa_insn_code_func ();
9894 output_trans_func ();
9895 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9896 output_internal_state_alts_func ();
9897 output_state_alts_func ();
9898 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9899 AUTOMATON_STATE_ALTS_MACRO_NAME);
9900 output_min_issue_delay_func ();
9901 output_internal_dead_lock_func ();
9902 output_dead_lock_func ();
9903 output_size_func ();
9904 output_internal_reset_func ();
9905 output_reset_func ();
9906 output_min_insn_conflict_delay_func ();
9907 output_internal_insn_latency_func ();
9908 output_insn_latency_func ();
9909 output_print_reservation_func ();
9910 /* Output function get_cpu_unit_code. */
9911 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9912 output_get_cpu_unit_code_func ();
9913 output_cpu_unit_reservation_p ();
9914 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9915 CPU_UNITS_QUERY_MACRO_NAME);
9916 output_dfa_clean_insn_cache_func ();
9917 output_dfa_start_func ();
9918 output_dfa_finish_func ();
9919 if (progress_flag)
9920 fprintf (stderr, "done\n");
9921 if (v_flag)
9923 output_description_file = fopen (output_description_file_name, "w");
9924 if (output_description_file == NULL)
9926 perror (output_description_file_name);
9927 exit (FATAL_EXIT_CODE);
9929 if (progress_flag)
9930 fprintf (stderr, "Output automata description...");
9931 output_description ();
9932 output_automaton_descriptions ();
9933 if (progress_flag)
9934 fprintf (stderr, "done\n");
9935 output_statistics (output_description_file);
9937 output_statistics (stderr);
9938 ticker_off (&output_time);
9939 output_time_statistics (stderr);
9940 finish_states ();
9941 finish_arcs ();
9942 finish_automata_lists ();
9943 if (time_flag)
9945 fprintf (stderr, "Summary:\n");
9946 fprintf (stderr, " check time ");
9947 print_active_time (stderr, check_time);
9948 fprintf (stderr, ", generation time ");
9949 print_active_time (stderr, generation_time);
9950 fprintf (stderr, ", all time ");
9951 print_active_time (stderr, all_time);
9952 fprintf (stderr, "\n");
9954 /* Finish all work. */
9955 if (output_description_file != NULL)
9957 fflush (output_description_file);
9958 if (ferror (stdout) != 0)
9959 fatal ("Error in writing DFA description file %s",
9960 output_description_file_name);
9961 fclose (output_description_file);
9963 finish_automaton_decl_table ();
9964 finish_insn_decl_table ();
9965 finish_decl_table ();
9966 obstack_free (&irp, NULL);
9967 if (have_error && output_description_file != NULL)
9968 remove (output_description_file_name);