2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / gcc / genautomata.c
blobb343d6e65ba5f56db3ab105be327b3697490c26c
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
4 Written by Vladimir Makarov <vmakarov@redhat.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
11 later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
23 /* References:
25 1. Detecting pipeline structural hazards quickly. T. Proebsting,
26 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
27 Principles of Programming Languages, pages 280--286, 1994.
29 This article is a good start point to understand usage of finite
30 state automata for pipeline hazard recognizers. But I'd
31 recommend the 2nd article for more deep understanding.
33 2. Efficient Instruction Scheduling Using Finite State Automata:
34 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
35 article about usage of finite state automata for pipeline hazard
36 recognizers.
38 The current implementation is different from the 2nd article in the
39 following:
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministically and
43 non-deterministically.
45 2. Possibility of usage of nondeterministic automata too.
47 3. Possibility to query functional unit reservations for given
48 automaton state.
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', `final_presence_set',
52 `absence_set', and `final_absence_set').
54 5. No reverse automata are generated. Trace instruction scheduling
55 requires this. It can be easily added in the future if we
56 really need this.
58 6. Union of automaton states are not generated yet. It is planned
59 to be implemented. Such feature is needed to make more accurate
60 interlock insn scheduling to get state describing functional
61 unit reservation in a joint CFG point. */
63 /* This file code processes constructions of machine description file
64 which describes automaton used for recognition of processor pipeline
65 hazards by insn scheduler and can be used for other tasks (such as
66 VLIW insn packing.
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_final_presence_set', `gen_absence_set',
71 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
72 `gen_reserv', `gen_insn_reserv' are called from file
73 `genattrtab.c'. They transform RTL constructions describing
74 automata in .md file into internal representation convenient for
75 further processing.
77 The translator major function `expand_automata' processes the
78 description internal representation into finite state automaton.
79 It can be divided on:
81 o checking correctness of the automaton pipeline description
82 (major function is `check_all_description').
84 o generating automaton (automata) from the description (major
85 function is `make_automaton').
87 o optional transformation of nondeterministic finite state
88 automata into deterministic ones if the alternative operator
89 `|' is treated nondeterministically in the description (major
90 function is NDFA_to_DFA).
92 o optional minimization of the finite state automata by merging
93 equivalent automaton states (major function is `minimize_DFA').
95 o forming tables (some as comb vectors) and attributes
96 representing the automata (functions output_..._table).
98 Function `write_automata' outputs the created finite state
99 automaton as different tables and functions which works with the
100 automata to inquire automaton state and to change its state. These
101 function are used by gcc instruction scheduler and may be some
102 other gcc code. */
104 #include "bconfig.h"
105 #include "system.h"
106 #include "coretypes.h"
107 #include "tm.h"
108 #include "rtl.h"
109 #include "obstack.h"
110 #include "errors.h"
112 #include <math.h>
113 #include "hashtab.h"
114 #include "varray.h"
116 #ifndef CHAR_BIT
117 #define CHAR_BIT 8
118 #endif
120 #include "genattrtab.h"
122 /* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
124 typedef int pos_t;
126 /* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128 typedef unsigned HOST_WIDE_INT set_el_t;
130 /* Reservations of function units are represented by value of the following
131 type. */
132 typedef set_el_t *reserv_sets_t;
134 /* The following structure represents variable length array (vla) of
135 pointers and HOST WIDE INTs. We could be use only varray. But we
136 add new lay because we add elements very frequently and this could
137 stress OS allocator when varray is used only. */
138 typedef struct {
139 size_t length; /* current size of vla. */
140 varray_type varray; /* container for vla. */
141 } vla_ptr_t;
143 typedef vla_ptr_t vla_hwint_t;
145 /* The following structure describes a ticker. */
146 struct ticker
148 /* The following member value is time of the ticker creation with
149 taking into account time when the ticker is off. Active time of
150 the ticker is current time minus the value. */
151 int modified_creation_time;
152 /* The following member value is time (incremented by one) when the
153 ticker was off. Zero value means that now the ticker is on. */
154 int incremented_off_time;
157 /* The ticker is represented by the following type. */
158 typedef struct ticker ticker_t;
160 /* The following type describes elements of output vectors. */
161 typedef HOST_WIDE_INT vect_el_t;
163 /* Forward declaration of structures of internal representation of
164 pipeline description based on NDFA. */
166 struct unit_decl;
167 struct bypass_decl;
168 struct result_decl;
169 struct automaton_decl;
170 struct unit_pattern_rel_decl;
171 struct reserv_decl;
172 struct insn_reserv_decl;
173 struct decl;
174 struct unit_regexp;
175 struct result_regexp;
176 struct reserv_regexp;
177 struct nothing_regexp;
178 struct sequence_regexp;
179 struct repeat_regexp;
180 struct allof_regexp;
181 struct oneof_regexp;
182 struct regexp;
183 struct description;
184 struct unit_set_el;
185 struct pattern_set_el;
186 struct pattern_reserv;
187 struct state;
188 struct alt_state;
189 struct arc;
190 struct ainsn;
191 struct automaton;
192 struct state_ainsn_table;
194 /* The following typedefs are for brevity. */
195 typedef struct unit_decl *unit_decl_t;
196 typedef struct decl *decl_t;
197 typedef struct regexp *regexp_t;
198 typedef struct unit_set_el *unit_set_el_t;
199 typedef struct pattern_set_el *pattern_set_el_t;
200 typedef struct pattern_reserv *pattern_reserv_t;
201 typedef struct alt_state *alt_state_t;
202 typedef struct state *state_t;
203 typedef struct arc *arc_t;
204 typedef struct ainsn *ainsn_t;
205 typedef struct automaton *automaton_t;
206 typedef struct automata_list_el *automata_list_el_t;
207 typedef struct state_ainsn_table *state_ainsn_table_t;
210 /* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
211 gen_bypass, gen_excl_set, gen_presence_set, gen_final_presence_set,
212 gen_absence_set, gen_final_absence_set, gen_automaton,
213 gen_automata_option, gen_reserv, gen_insn_reserv,
214 initiate_automaton_gen, expand_automata, write_automata are
215 described on the file top because the functions are called from
216 function `main'. */
218 static void *create_node (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 /* The following flags are set up by function `initiate_automaton_gen'. */
663 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
664 static int ndfa_flag;
666 /* Do not make minimization of DFA (`-no-minimization'). */
667 static int no_minimization_flag;
669 /* Value of this variable is number of automata being generated. The
670 actual number of automata may be less this value if there is not
671 sufficient number of units. This value is defined by argument of
672 option `-split' or by constructions automaton if the value is zero
673 (it is default value of the argument). */
674 static int split_argument;
676 /* Flag of output time statistics (`-time'). */
677 static int time_flag;
679 /* Flag of creation of description file which contains description of
680 result automaton and statistics information (`-v'). */
681 static int v_flag;
683 /* Flag of generating warning instead of error for non-critical errors
684 (`-w'). */
685 static int w_flag;
688 /* Output file for pipeline hazard recognizer (PHR) being generated.
689 The value is NULL if the file is not defined. */
690 static FILE *output_file;
692 /* Description file of PHR. The value is NULL if the file is not
693 created. */
694 static FILE *output_description_file;
696 /* PHR description file name. */
697 static char *output_description_file_name;
699 /* Value of the following variable is node representing description
700 being processed. This is start point of IR. */
701 static struct description *description;
705 /* This page contains description of IR structure (nodes). */
707 enum decl_mode
709 dm_unit,
710 dm_bypass,
711 dm_automaton,
712 dm_excl,
713 dm_presence,
714 dm_absence,
715 dm_reserv,
716 dm_insn_reserv
719 /* This describes define_cpu_unit and define_query_cpu_unit (see file
720 rtl.def). */
721 struct unit_decl
723 char *name;
724 /* NULL if the automaton name is absent. */
725 char *automaton_name;
726 /* If the following value is not zero, the cpu unit reservation is
727 described in define_query_cpu_unit. */
728 char query_p;
730 /* The following fields are defined by checker. */
732 /* The following field value is nonzero if the unit is used in an
733 regexp. */
734 char unit_is_used;
736 /* The following field value is order number (0, 1, ...) of given
737 unit. */
738 int unit_num;
739 /* The following field value is corresponding declaration of
740 automaton which was given in description. If the field value is
741 NULL then automaton in the unit declaration was absent. */
742 struct automaton_decl *automaton_decl;
743 /* The following field value is maximal cycle number (1, ...) on
744 which given unit occurs in insns. Zero value means that given
745 unit is not used in insns. */
746 int max_occ_cycle_num;
747 /* The following field value is minimal cycle number (0, ...) on
748 which given unit occurs in insns. -1 value means that given
749 unit is not used in insns. */
750 int min_occ_cycle_num;
751 /* The following list contains units which conflict with given
752 unit. */
753 unit_set_el_t excl_list;
754 /* The following list contains patterns which are required to
755 reservation of given unit. */
756 pattern_set_el_t presence_list;
757 pattern_set_el_t final_presence_list;
758 /* The following list contains patterns which should be not present
759 in reservation for given unit. */
760 pattern_set_el_t absence_list;
761 pattern_set_el_t final_absence_list;
762 /* The following is used only when `query_p' has nonzero value.
763 This is query number for the unit. */
764 int query_num;
765 /* The following is the last cycle on which the unit was checked for
766 correct distributions of units to automata in a regexp. */
767 int last_distribution_check_cycle;
769 /* The following fields are defined by automaton generator. */
771 /* The following field value is number of the automaton to which
772 given unit belongs. */
773 int corresponding_automaton_num;
774 /* If the following value is not zero, the cpu unit is present in a
775 `exclusion_set' or in right part of a `presence_set',
776 `final_presence_set', `absence_set', and
777 `final_absence_set'define_query_cpu_unit. */
778 char in_set_p;
781 /* This describes define_bypass (see file rtl.def). */
782 struct bypass_decl
784 int latency;
785 char *out_insn_name;
786 char *in_insn_name;
787 char *bypass_guard_name;
789 /* The following fields are defined by checker. */
791 /* output and input insns of given bypass. */
792 struct insn_reserv_decl *out_insn_reserv;
793 struct insn_reserv_decl *in_insn_reserv;
794 /* The next bypass for given output insn. */
795 struct bypass_decl *next;
798 /* This describes define_automaton (see file rtl.def). */
799 struct automaton_decl
801 char *name;
803 /* The following fields are defined by automaton generator. */
805 /* The following field value is nonzero if the automaton is used in
806 an regexp definition. */
807 char automaton_is_used;
809 /* The following fields are defined by checker. */
811 /* The following field value is the corresponding automaton. This
812 field is not NULL only if the automaton is present in unit
813 declarations and the automatic partition on automata is not
814 used. */
815 automaton_t corresponding_automaton;
818 /* This describes exclusion relations: exclusion_set (see file
819 rtl.def). */
820 struct excl_rel_decl
822 int all_names_num;
823 int first_list_length;
824 char *names [1];
827 /* This describes unit relations: [final_]presence_set or
828 [final_]absence_set (see file rtl.def). */
829 struct unit_pattern_rel_decl
831 int final_p;
832 int names_num;
833 int patterns_num;
834 char **names;
835 char ***patterns;
838 /* This describes define_reservation (see file rtl.def). */
839 struct reserv_decl
841 char *name;
842 regexp_t regexp;
844 /* The following fields are defined by checker. */
846 /* The following field value is nonzero if the unit is used in an
847 regexp. */
848 char reserv_is_used;
849 /* The following field is used to check up cycle in expression
850 definition. */
851 int loop_pass_num;
854 /* This describes define_insn_reservation (see file rtl.def). */
855 struct insn_reserv_decl
857 rtx condexp;
858 int default_latency;
859 regexp_t regexp;
860 char *name;
862 /* The following fields are defined by checker. */
864 /* The following field value is order number (0, 1, ...) of given
865 insn. */
866 int insn_num;
867 /* The following field value is list of bypasses in which given insn
868 is output insn. */
869 struct bypass_decl *bypass_list;
871 /* The following fields are defined by automaton generator. */
873 /* The following field is the insn regexp transformed that
874 the regexp has not optional regexp, repetition regexp, and an
875 reservation name (i.e. reservation identifiers are changed by the
876 corresponding regexp) and all alternations are the topest level
877 of the regexp. The value can be NULL only if it is special
878 insn `cycle advancing'. */
879 regexp_t transformed_regexp;
880 /* The following field value is list of arcs marked given
881 insn. The field is used in transformation NDFA -> DFA. */
882 arc_t arcs_marked_by_insn;
883 /* The two following fields are used during minimization of a finite state
884 automaton. */
885 /* The field value is number of equivalence class of state into
886 which arc marked by given insn enters from a state (fixed during
887 an automaton minimization). */
888 int equiv_class_num;
889 /* The field value is state_alts of arc leaving a state (fixed
890 during an automaton minimization) and marked by given insn
891 enters. */
892 int state_alts;
893 /* The following member value is the list to automata which can be
894 changed by the insn issue. */
895 automata_list_el_t important_automata_list;
896 /* The following member is used to process insn once for output. */
897 int processed_p;
900 /* This contains a declaration mentioned above. */
901 struct decl
903 /* What node in the union? */
904 enum decl_mode mode;
905 pos_t pos;
906 union
908 struct unit_decl unit;
909 struct bypass_decl bypass;
910 struct automaton_decl automaton;
911 struct excl_rel_decl excl;
912 struct unit_pattern_rel_decl presence;
913 struct unit_pattern_rel_decl absence;
914 struct reserv_decl reserv;
915 struct insn_reserv_decl insn_reserv;
916 } decl;
919 /* The following structures represent parsed reservation strings. */
920 enum regexp_mode
922 rm_unit,
923 rm_reserv,
924 rm_nothing,
925 rm_sequence,
926 rm_repeat,
927 rm_allof,
928 rm_oneof
931 /* Cpu unit in reservation. */
932 struct unit_regexp
934 char *name;
935 unit_decl_t unit_decl;
938 /* Define_reservation in a reservation. */
939 struct reserv_regexp
941 char *name;
942 struct reserv_decl *reserv_decl;
945 /* Absence of reservation (represented by string `nothing'). */
946 struct nothing_regexp
948 /* This used to be empty but ISO C doesn't allow that. */
949 char unused;
952 /* Representation of reservations separated by ',' (see file
953 rtl.def). */
954 struct sequence_regexp
956 int regexps_num;
957 regexp_t regexps [1];
960 /* Representation of construction `repeat' (see file rtl.def). */
961 struct repeat_regexp
963 int repeat_num;
964 regexp_t regexp;
967 /* Representation of reservations separated by '+' (see file
968 rtl.def). */
969 struct allof_regexp
971 int regexps_num;
972 regexp_t regexps [1];
975 /* Representation of reservations separated by '|' (see file
976 rtl.def). */
977 struct oneof_regexp
979 int regexps_num;
980 regexp_t regexps [1];
983 /* Representation of a reservation string. */
984 struct regexp
986 /* What node in the union? */
987 enum regexp_mode mode;
988 pos_t pos;
989 union
991 struct unit_regexp unit;
992 struct reserv_regexp reserv;
993 struct nothing_regexp nothing;
994 struct sequence_regexp sequence;
995 struct repeat_regexp repeat;
996 struct allof_regexp allof;
997 struct oneof_regexp oneof;
998 } regexp;
1001 /* Represents description of pipeline hazard description based on
1002 NDFA. */
1003 struct description
1005 int decls_num;
1007 /* The following fields are defined by checker. */
1009 /* The following fields values are correspondingly number of all
1010 units, query units, and insns in the description. */
1011 int units_num;
1012 int query_units_num;
1013 int insns_num;
1014 /* The following field value is max length (in cycles) of
1015 reservations of insns. The field value is defined only for
1016 correct programs. */
1017 int max_insn_reserv_cycles;
1019 /* The following fields are defined by automaton generator. */
1021 /* The following field value is the first automaton. */
1022 automaton_t first_automaton;
1024 /* The following field is created by pipeline hazard parser and
1025 contains all declarations. We allocate additional entry for
1026 special insn "cycle advancing" which is added by the automaton
1027 generator. */
1028 decl_t decls [1];
1032 /* The following nodes are created in automaton checker. */
1034 /* The following nodes represent exclusion set for cpu units. Each
1035 element is accessed through only one excl_list. */
1036 struct unit_set_el
1038 unit_decl_t unit_decl;
1039 unit_set_el_t next_unit_set_el;
1042 /* The following nodes represent presence or absence pattern for cpu
1043 units. Each element is accessed through only one presence_list or
1044 absence_list. */
1045 struct pattern_set_el
1047 /* The number of units in unit_decls. */
1048 int units_num;
1049 /* The units forming the pattern. */
1050 struct unit_decl **unit_decls;
1051 pattern_set_el_t next_pattern_set_el;
1055 /* The following nodes are created in automaton generator. */
1058 /* The following nodes represent presence or absence pattern for cpu
1059 units. Each element is accessed through only one element of
1060 unit_presence_set_table or unit_absence_set_table. */
1061 struct pattern_reserv
1063 reserv_sets_t reserv;
1064 pattern_reserv_t next_pattern_reserv;
1067 /* The following node type describes state automaton. The state may
1068 be deterministic or non-deterministic. Non-deterministic state has
1069 several component states which represent alternative cpu units
1070 reservations. The state also is used for describing a
1071 deterministic reservation of automaton insn. */
1072 struct state
1074 /* The following member value is nonzero if there is a transition by
1075 cycle advancing. */
1076 int new_cycle_p;
1077 /* The following field is list of processor unit reservations on
1078 each cycle. */
1079 reserv_sets_t reservs;
1080 /* The following field is unique number of given state between other
1081 states. */
1082 int unique_num;
1083 /* The following field value is automaton to which given state
1084 belongs. */
1085 automaton_t automaton;
1086 /* The following field value is the first arc output from given
1087 state. */
1088 arc_t first_out_arc;
1089 /* The following field is used to form NDFA. */
1090 char it_was_placed_in_stack_for_NDFA_forming;
1091 /* The following field is used to form DFA. */
1092 char it_was_placed_in_stack_for_DFA_forming;
1093 /* The following field is used to transform NDFA to DFA and DFA
1094 minimization. The field value is not NULL if the state is a
1095 compound state. In this case the value of field `unit_sets_list'
1096 is NULL. All states in the list are in the hash table. The list
1097 is formed through field `next_sorted_alt_state'. We should
1098 support only one level of nesting state. */
1099 alt_state_t component_states;
1100 /* The following field is used for passing graph of states. */
1101 int pass_num;
1102 /* The list of states belonging to one equivalence class is formed
1103 with the aid of the following field. */
1104 state_t next_equiv_class_state;
1105 /* The two following fields are used during minimization of a finite
1106 state automaton. */
1107 int equiv_class_num_1, equiv_class_num_2;
1108 /* The following field is used during minimization of a finite state
1109 automaton. The field value is state corresponding to equivalence
1110 class to which given state belongs. */
1111 state_t equiv_class_state;
1112 /* The following field value is the order number of given state.
1113 The states in final DFA is enumerated with the aid of the
1114 following field. */
1115 int order_state_num;
1116 /* This member is used for passing states for searching minimal
1117 delay time. */
1118 int state_pass_num;
1119 /* The following member is used to evaluate min issue delay of insn
1120 for a state. */
1121 int min_insn_issue_delay;
1122 /* The following member is used to evaluate max issue rate of the
1123 processor. The value of the member is maximal length of the path
1124 from given state no containing arcs marked by special insn `cycle
1125 advancing'. */
1126 int longest_path_length;
1129 /* The following macro is an initial value of member
1130 `longest_path_length' of a state. */
1131 #define UNDEFINED_LONGEST_PATH_LENGTH -1
1133 /* Automaton arc. */
1134 struct arc
1136 /* The following field refers for the state into which given arc
1137 enters. */
1138 state_t to_state;
1139 /* The following field describes that the insn issue (with cycle
1140 advancing for special insn `cycle advancing' and without cycle
1141 advancing for others) makes transition from given state to
1142 another given state. */
1143 ainsn_t insn;
1144 /* The following field value is the next arc output from the same
1145 state. */
1146 arc_t next_out_arc;
1147 /* List of arcs marked given insn is formed with the following
1148 field. The field is used in transformation NDFA -> DFA. */
1149 arc_t next_arc_marked_by_insn;
1150 /* The following field is defined if NDFA_FLAG is zero. The member
1151 value is number of alternative reservations which can be used for
1152 transition for given state by given insn. */
1153 int state_alts;
1156 /* The following node type describes a deterministic alternative in
1157 non-deterministic state which characterizes cpu unit reservations
1158 of automaton insn or which is part of NDFA. */
1159 struct alt_state
1161 /* The following field is a deterministic state which characterizes
1162 unit reservations of the instruction. */
1163 state_t state;
1164 /* The following field refers to the next state which characterizes
1165 unit reservations of the instruction. */
1166 alt_state_t next_alt_state;
1167 /* The following field refers to the next state in sorted list. */
1168 alt_state_t next_sorted_alt_state;
1171 /* The following node type describes insn of automaton. They are
1172 labels of FA arcs. */
1173 struct ainsn
1175 /* The following field value is the corresponding insn declaration
1176 of description. */
1177 struct insn_reserv_decl *insn_reserv_decl;
1178 /* The following field value is the next insn declaration for an
1179 automaton. */
1180 ainsn_t next_ainsn;
1181 /* The following field is states which characterize automaton unit
1182 reservations of the instruction. The value can be NULL only if it
1183 is special insn `cycle advancing'. */
1184 alt_state_t alt_states;
1185 /* The following field is sorted list of states which characterize
1186 automaton unit reservations of the instruction. The value can be
1187 NULL only if it is special insn `cycle advancing'. */
1188 alt_state_t sorted_alt_states;
1189 /* The following field refers the next automaton insn with
1190 the same reservations. */
1191 ainsn_t next_same_reservs_insn;
1192 /* The following field is flag of the first automaton insn with the
1193 same reservations in the declaration list. Only arcs marked such
1194 insn is present in the automaton. This significantly decreases
1195 memory requirements especially when several automata are
1196 formed. */
1197 char first_insn_with_same_reservs;
1198 /* The following member has nonzero value if there is arc from state of
1199 the automaton marked by the ainsn. */
1200 char arc_exists_p;
1201 /* Cyclic list of insns of an equivalence class is formed with the
1202 aid of the following field. */
1203 ainsn_t next_equiv_class_insn;
1204 /* The following field value is nonzero if the insn declaration is
1205 the first insn declaration with given equivalence number. */
1206 char first_ainsn_with_given_equialence_num;
1207 /* The following field is number of class of equivalence of insns.
1208 It is necessary because many insns may be equivalent with the
1209 point of view of pipeline hazards. */
1210 int insn_equiv_class_num;
1211 /* The following member value is TRUE if there is an arc in the
1212 automaton marked by the insn into another state. In other
1213 words, the insn can change the state of the automaton. */
1214 int important_p;
1217 /* The following describes an automaton for PHR. */
1218 struct automaton
1220 /* The following field value is the list of insn declarations for
1221 given automaton. */
1222 ainsn_t ainsn_list;
1223 /* The following field value is the corresponding automaton
1224 declaration. This field is not NULL only if the automatic
1225 partition on automata is not used. */
1226 struct automaton_decl *corresponding_automaton_decl;
1227 /* The following field value is the next automaton. */
1228 automaton_t next_automaton;
1229 /* The following field is start state of FA. There are not unit
1230 reservations in the state. */
1231 state_t start_state;
1232 /* The following field value is number of equivalence classes of
1233 insns (see field `insn_equiv_class_num' in
1234 `insn_reserv_decl'). */
1235 int insn_equiv_classes_num;
1236 /* The following field value is number of states of final DFA. */
1237 int achieved_states_num;
1238 /* The following field value is the order number (0, 1, ...) of
1239 given automaton. */
1240 int automaton_order_num;
1241 /* The following fields contain statistics information about
1242 building automaton. */
1243 int NDFA_states_num, DFA_states_num;
1244 /* The following field value is defined only if minimization of DFA
1245 is used. */
1246 int minimal_DFA_states_num;
1247 int NDFA_arcs_num, DFA_arcs_num;
1248 /* The following field value is defined only if minimization of DFA
1249 is used. */
1250 int minimal_DFA_arcs_num;
1251 /* The following two members refer for two table state x ainsn ->
1252 int. */
1253 state_ainsn_table_t trans_table;
1254 state_ainsn_table_t state_alts_table;
1255 /* The following member value is maximal value of min issue delay
1256 for insns of the automaton. */
1257 int max_min_delay;
1258 /* Usually min issue delay is small and we can place several (2, 4,
1259 8) elements in one vector element. So the compression factor can
1260 be 1 (no compression), 2, 4, 8. */
1261 int min_issue_delay_table_compression_factor;
1264 /* The following is the element of the list of automata. */
1265 struct automata_list_el
1267 /* The automaton itself. */
1268 automaton_t automaton;
1269 /* The next automata set element. */
1270 automata_list_el_t next_automata_list_el;
1273 /* The following structure describes a table state X ainsn -> int(>= 0). */
1274 struct state_ainsn_table
1276 /* Automaton to which given table belongs. */
1277 automaton_t automaton;
1278 /* The following tree vectors for comb vector implementation of the
1279 table. */
1280 vla_hwint_t comb_vect;
1281 vla_hwint_t check_vect;
1282 vla_hwint_t base_vect;
1283 /* This is simple implementation of the table. */
1284 vla_hwint_t full_vect;
1285 /* Minimal and maximal values of the previous vectors. */
1286 int min_comb_vect_el_value, max_comb_vect_el_value;
1287 int min_base_vect_el_value, max_base_vect_el_value;
1290 /* Macros to access members of unions. Use only them for access to
1291 union members of declarations and regexps. */
1293 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1295 #define DECL_UNIT(d) __extension__ \
1296 (({ struct decl *const _decl = (d); \
1297 if (_decl->mode != dm_unit) \
1298 decl_mode_check_failed (_decl->mode, "dm_unit", \
1299 __FILE__, __LINE__, __FUNCTION__); \
1300 &(_decl)->decl.unit; }))
1302 #define DECL_BYPASS(d) __extension__ \
1303 (({ struct decl *const _decl = (d); \
1304 if (_decl->mode != dm_bypass) \
1305 decl_mode_check_failed (_decl->mode, "dm_bypass", \
1306 __FILE__, __LINE__, __FUNCTION__); \
1307 &(_decl)->decl.bypass; }))
1309 #define DECL_AUTOMATON(d) __extension__ \
1310 (({ struct decl *const _decl = (d); \
1311 if (_decl->mode != dm_automaton) \
1312 decl_mode_check_failed (_decl->mode, "dm_automaton", \
1313 __FILE__, __LINE__, __FUNCTION__); \
1314 &(_decl)->decl.automaton; }))
1316 #define DECL_EXCL(d) __extension__ \
1317 (({ struct decl *const _decl = (d); \
1318 if (_decl->mode != dm_excl) \
1319 decl_mode_check_failed (_decl->mode, "dm_excl", \
1320 __FILE__, __LINE__, __FUNCTION__); \
1321 &(_decl)->decl.excl; }))
1323 #define DECL_PRESENCE(d) __extension__ \
1324 (({ struct decl *const _decl = (d); \
1325 if (_decl->mode != dm_presence) \
1326 decl_mode_check_failed (_decl->mode, "dm_presence", \
1327 __FILE__, __LINE__, __FUNCTION__); \
1328 &(_decl)->decl.presence; }))
1330 #define DECL_ABSENCE(d) __extension__ \
1331 (({ struct decl *const _decl = (d); \
1332 if (_decl->mode != dm_absence) \
1333 decl_mode_check_failed (_decl->mode, "dm_absence", \
1334 __FILE__, __LINE__, __FUNCTION__); \
1335 &(_decl)->decl.absence; }))
1337 #define DECL_RESERV(d) __extension__ \
1338 (({ struct decl *const _decl = (d); \
1339 if (_decl->mode != dm_reserv) \
1340 decl_mode_check_failed (_decl->mode, "dm_reserv", \
1341 __FILE__, __LINE__, __FUNCTION__); \
1342 &(_decl)->decl.reserv; }))
1344 #define DECL_INSN_RESERV(d) __extension__ \
1345 (({ struct decl *const _decl = (d); \
1346 if (_decl->mode != dm_insn_reserv) \
1347 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
1348 __FILE__, __LINE__, __FUNCTION__); \
1349 &(_decl)->decl.insn_reserv; }))
1351 static const char *decl_name (enum decl_mode);
1352 static void decl_mode_check_failed (enum decl_mode, const char *,
1353 const char *, int, const char *);
1355 /* Return string representation of declaration mode MODE. */
1356 static const char *
1357 decl_name (enum decl_mode mode)
1359 static char str [100];
1361 if (mode == dm_unit)
1362 return "dm_unit";
1363 else if (mode == dm_bypass)
1364 return "dm_bypass";
1365 else if (mode == dm_automaton)
1366 return "dm_automaton";
1367 else if (mode == dm_excl)
1368 return "dm_excl";
1369 else if (mode == dm_presence)
1370 return "dm_presence";
1371 else if (mode == dm_absence)
1372 return "dm_absence";
1373 else if (mode == dm_reserv)
1374 return "dm_reserv";
1375 else if (mode == dm_insn_reserv)
1376 return "dm_insn_reserv";
1377 else
1378 sprintf (str, "unknown (%d)", (int) mode);
1379 return str;
1382 /* The function prints message about unexpected declaration and finish
1383 the program. */
1384 static void
1385 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
1386 const char *file, int line, const char *func)
1388 fprintf
1389 (stderr,
1390 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1391 file, line, func, expected_mode_str, decl_name (mode));
1392 exit (1);
1396 #define REGEXP_UNIT(r) __extension__ \
1397 (({ struct regexp *const _regexp = (r); \
1398 if (_regexp->mode != rm_unit) \
1399 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1400 __FILE__, __LINE__, __FUNCTION__); \
1401 &(_regexp)->regexp.unit; }))
1403 #define REGEXP_RESERV(r) __extension__ \
1404 (({ struct regexp *const _regexp = (r); \
1405 if (_regexp->mode != rm_reserv) \
1406 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1407 __FILE__, __LINE__, __FUNCTION__); \
1408 &(_regexp)->regexp.reserv; }))
1410 #define REGEXP_SEQUENCE(r) __extension__ \
1411 (({ struct regexp *const _regexp = (r); \
1412 if (_regexp->mode != rm_sequence) \
1413 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1414 __FILE__, __LINE__, __FUNCTION__); \
1415 &(_regexp)->regexp.sequence; }))
1417 #define REGEXP_REPEAT(r) __extension__ \
1418 (({ struct regexp *const _regexp = (r); \
1419 if (_regexp->mode != rm_repeat) \
1420 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1421 __FILE__, __LINE__, __FUNCTION__); \
1422 &(_regexp)->regexp.repeat; }))
1424 #define REGEXP_ALLOF(r) __extension__ \
1425 (({ struct regexp *const _regexp = (r); \
1426 if (_regexp->mode != rm_allof) \
1427 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1428 __FILE__, __LINE__, __FUNCTION__); \
1429 &(_regexp)->regexp.allof; }))
1431 #define REGEXP_ONEOF(r) __extension__ \
1432 (({ struct regexp *const _regexp = (r); \
1433 if (_regexp->mode != rm_oneof) \
1434 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1435 __FILE__, __LINE__, __FUNCTION__); \
1436 &(_regexp)->regexp.oneof; }))
1438 static const char *regexp_name (enum regexp_mode);
1439 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1440 const char *, int,
1441 const char *);
1444 /* Return string representation of regexp mode MODE. */
1445 static const char *
1446 regexp_name (enum regexp_mode mode)
1448 static char str [100];
1450 if (mode == rm_unit)
1451 return "rm_unit";
1452 else if (mode == rm_reserv)
1453 return "rm_reserv";
1454 else if (mode == rm_nothing)
1455 return "rm_nothing";
1456 else if (mode == rm_sequence)
1457 return "rm_sequence";
1458 else if (mode == rm_repeat)
1459 return "rm_repeat";
1460 else if (mode == rm_allof)
1461 return "rm_allof";
1462 else if (mode == rm_oneof)
1463 return "rm_oneof";
1464 else
1465 sprintf (str, "unknown (%d)", (int) mode);
1466 return str;
1469 /* The function prints message about unexpected regexp and finish the
1470 program. */
1471 static void
1472 regexp_mode_check_failed (enum regexp_mode mode,
1473 const char *expected_mode_str,
1474 const char *file, int line, const char *func)
1476 fprintf
1477 (stderr,
1478 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1479 file, line, func, expected_mode_str, regexp_name (mode));
1480 exit (1);
1483 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1485 #define DECL_UNIT(d) (&(d)->decl.unit)
1486 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1487 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1488 #define DECL_EXCL(d) (&(d)->decl.excl)
1489 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1490 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1491 #define DECL_RESERV(d) (&(d)->decl.reserv)
1492 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1494 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1495 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1496 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1497 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1498 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1499 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1501 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1503 /* Create IR structure (node). */
1504 static void *
1505 create_node (size_t size)
1507 void *result;
1509 obstack_blank (&irp, size);
1510 result = obstack_base (&irp);
1511 obstack_finish (&irp);
1512 /* Default values of members are NULL and zero. */
1513 memset (result, 0, size);
1514 return result;
1517 /* Copy IR structure (node). */
1518 static void *
1519 copy_node (const void *from, size_t size)
1521 void *const result = create_node (size);
1522 memcpy (result, from, size);
1523 return result;
1526 /* The function checks that NAME does not contain quotes (`"'). */
1527 static char *
1528 check_name (char * name, pos_t pos ATTRIBUTE_UNUSED)
1530 const char *str;
1532 for (str = name; *str != '\0'; str++)
1533 if (*str == '\"')
1534 error ("Name `%s' contains quotes", name);
1535 return name;
1538 /* Pointers to all declarations during IR generation are stored in the
1539 following. */
1540 static vla_ptr_t decls;
1542 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1543 string containing the next separated element, taking parentheses
1544 into account if PAR_FLAG has nonzero value. Advance the pointer to
1545 after the string scanned, or the end-of-string. Return NULL if at
1546 end of string. */
1547 static char *
1548 next_sep_el (char **pstr, int sep, int par_flag)
1550 char *out_str;
1551 char *p;
1552 int pars_num;
1553 int n_spaces;
1555 /* Remove leading whitespaces. */
1556 while (ISSPACE ((int) **pstr))
1557 (*pstr)++;
1559 if (**pstr == '\0')
1560 return NULL;
1562 n_spaces = 0;
1563 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1565 if (par_flag && *p == '(')
1566 pars_num++;
1567 else if (par_flag && *p == ')')
1568 pars_num--;
1569 else if (pars_num == 0 && *p == sep)
1570 break;
1571 if (pars_num == 0 && ISSPACE ((int) *p))
1572 n_spaces++;
1573 else
1575 for (; n_spaces != 0; n_spaces--)
1576 obstack_1grow (&irp, p [-n_spaces]);
1577 obstack_1grow (&irp, *p);
1580 obstack_1grow (&irp, '\0');
1581 out_str = obstack_base (&irp);
1582 obstack_finish (&irp);
1584 *pstr = p;
1585 if (**pstr == sep)
1586 (*pstr)++;
1588 return out_str;
1591 /* Given a string and a separator, return the number of separated
1592 elements in it, taking parentheses into account if PAR_FLAG has
1593 nonzero value. Return 0 for the null string, -1 if parentheses is
1594 not balanced. */
1595 static int
1596 n_sep_els (char *s, int sep, int par_flag)
1598 int n;
1599 int pars_num;
1601 if (*s == '\0')
1602 return 0;
1604 for (pars_num = 0, n = 1; *s; s++)
1605 if (par_flag && *s == '(')
1606 pars_num++;
1607 else if (par_flag && *s == ')')
1608 pars_num--;
1609 else if (pars_num == 0 && *s == sep)
1610 n++;
1612 return (pars_num != 0 ? -1 : n);
1615 /* Given a string and a separator, return vector of strings which are
1616 elements in the string and number of elements through els_num.
1617 Take parentheses into account if PAREN_P has nonzero value. The
1618 function also inserts the end marker NULL at the end of vector.
1619 Return 0 for the null string, -1 if parentheses are not balanced. */
1620 static char **
1621 get_str_vect (char *str, int *els_num, int sep, int paren_p)
1623 int i;
1624 char **vect;
1625 char **pstr;
1627 *els_num = n_sep_els (str, sep, paren_p);
1628 if (*els_num <= 0)
1629 return NULL;
1630 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1631 vect = (char **) obstack_base (&irp);
1632 obstack_finish (&irp);
1633 pstr = &str;
1634 for (i = 0; i < *els_num; i++)
1635 vect [i] = next_sep_el (pstr, sep, paren_p);
1636 if (next_sep_el (pstr, sep, paren_p) != NULL)
1637 abort ();
1638 vect [i] = NULL;
1639 return vect;
1642 /* Process a DEFINE_CPU_UNIT.
1644 This gives information about a unit contained in CPU. We fill a
1645 struct unit_decl with information used later by `expand_automata'. */
1646 void
1647 gen_cpu_unit (rtx def)
1649 decl_t decl;
1650 char **str_cpu_units;
1651 int vect_length;
1652 int i;
1654 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1655 FALSE);
1656 if (str_cpu_units == NULL)
1657 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1658 for (i = 0; i < vect_length; i++)
1660 decl = create_node (sizeof (struct decl));
1661 decl->mode = dm_unit;
1662 decl->pos = 0;
1663 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1664 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1665 DECL_UNIT (decl)->query_p = 0;
1666 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1667 DECL_UNIT (decl)->in_set_p = 0;
1668 VLA_PTR_ADD (decls, decl);
1669 num_dfa_decls++;
1673 /* Process a DEFINE_QUERY_CPU_UNIT.
1675 This gives information about a unit contained in CPU. We fill a
1676 struct unit_decl with information used later by `expand_automata'. */
1677 void
1678 gen_query_cpu_unit (rtx def)
1680 decl_t decl;
1681 char **str_cpu_units;
1682 int vect_length;
1683 int i;
1685 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1686 FALSE);
1687 if (str_cpu_units == NULL)
1688 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1689 for (i = 0; i < vect_length; i++)
1691 decl = create_node (sizeof (struct decl));
1692 decl->mode = dm_unit;
1693 decl->pos = 0;
1694 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1695 DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1696 DECL_UNIT (decl)->query_p = 1;
1697 VLA_PTR_ADD (decls, decl);
1698 num_dfa_decls++;
1702 /* Process a DEFINE_BYPASS.
1704 This gives information about a unit contained in the CPU. We fill
1705 in a struct bypass_decl with information used later by
1706 `expand_automata'. */
1707 void
1708 gen_bypass (rtx def)
1710 decl_t decl;
1711 char **out_insns;
1712 int out_length;
1713 char **in_insns;
1714 int in_length;
1715 int i, j;
1717 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', FALSE);
1718 if (out_insns == NULL)
1719 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1720 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', FALSE);
1721 if (in_insns == NULL)
1722 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1723 for (i = 0; i < out_length; i++)
1724 for (j = 0; j < in_length; j++)
1726 decl = create_node (sizeof (struct decl));
1727 decl->mode = dm_bypass;
1728 decl->pos = 0;
1729 DECL_BYPASS (decl)->latency = XINT (def, 0);
1730 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1731 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1732 DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
1733 VLA_PTR_ADD (decls, decl);
1734 num_dfa_decls++;
1738 /* Process an EXCLUSION_SET.
1740 This gives information about a cpu unit conflicts. We fill a
1741 struct excl_rel_decl (excl) with information used later by
1742 `expand_automata'. */
1743 void
1744 gen_excl_set (rtx def)
1746 decl_t decl;
1747 char **first_str_cpu_units;
1748 char **second_str_cpu_units;
1749 int first_vect_length;
1750 int length;
1751 int i;
1753 first_str_cpu_units
1754 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', FALSE);
1755 if (first_str_cpu_units == NULL)
1756 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1757 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1758 FALSE);
1759 if (second_str_cpu_units == NULL)
1760 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1761 length += first_vect_length;
1762 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1763 decl->mode = dm_excl;
1764 decl->pos = 0;
1765 DECL_EXCL (decl)->all_names_num = length;
1766 DECL_EXCL (decl)->first_list_length = first_vect_length;
1767 for (i = 0; i < length; i++)
1768 if (i < first_vect_length)
1769 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1770 else
1771 DECL_EXCL (decl)->names [i]
1772 = second_str_cpu_units [i - first_vect_length];
1773 VLA_PTR_ADD (decls, decl);
1774 num_dfa_decls++;
1777 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1778 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1780 This gives information about a cpu unit reservation requirements.
1781 We fill a struct unit_pattern_rel_decl with information used later
1782 by `expand_automata'. */
1783 static void
1784 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1786 decl_t decl;
1787 char **str_cpu_units;
1788 char ***str_patterns;
1789 int cpu_units_length;
1790 int length;
1791 int patterns_length;
1792 int i;
1794 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &cpu_units_length, ',',
1795 FALSE);
1796 if (str_cpu_units == NULL)
1797 fatal ((presence_p
1798 ? (final_p
1799 ? "invalid first string `%s' in final_presence_set"
1800 : "invalid first string `%s' in presence_set")
1801 : (final_p
1802 ? "invalid first string `%s' in final_absence_set"
1803 : "invalid first string `%s' in absence_set")),
1804 XSTR (def, 0));
1805 str_patterns = (char ***) get_str_vect ((char *) XSTR (def, 1),
1806 &patterns_length, ',', FALSE);
1807 if (str_patterns == NULL)
1808 fatal ((presence_p
1809 ? (final_p
1810 ? "invalid second string `%s' in final_presence_set"
1811 : "invalid second string `%s' in presence_set")
1812 : (final_p
1813 ? "invalid second string `%s' in final_absence_set"
1814 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1815 for (i = 0; i < patterns_length; i++)
1817 str_patterns [i] = get_str_vect ((char *) str_patterns [i], &length, ' ',
1818 FALSE);
1819 if (str_patterns [i] == NULL)
1820 abort ();
1822 decl = create_node (sizeof (struct decl));
1823 decl->pos = 0;
1824 if (presence_p)
1826 decl->mode = dm_presence;
1827 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1828 DECL_PRESENCE (decl)->names = str_cpu_units;
1829 DECL_PRESENCE (decl)->patterns = str_patterns;
1830 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1831 DECL_PRESENCE (decl)->final_p = final_p;
1833 else
1835 decl->mode = dm_absence;
1836 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1837 DECL_ABSENCE (decl)->names = str_cpu_units;
1838 DECL_ABSENCE (decl)->patterns = str_patterns;
1839 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1840 DECL_ABSENCE (decl)->final_p = final_p;
1842 VLA_PTR_ADD (decls, decl);
1843 num_dfa_decls++;
1846 /* Process a PRESENCE_SET.
1848 This gives information about a cpu unit reservation requirements.
1849 We fill a struct unit_pattern_rel_decl (presence) with information
1850 used later by `expand_automata'. */
1851 void
1852 gen_presence_set (rtx def)
1854 gen_presence_absence_set (def, TRUE, FALSE);
1857 /* Process a FINAL_PRESENCE_SET.
1859 This gives information about a cpu unit reservation requirements.
1860 We fill a struct unit_pattern_rel_decl (presence) with information
1861 used later by `expand_automata'. */
1862 void
1863 gen_final_presence_set (rtx def)
1865 gen_presence_absence_set (def, TRUE, TRUE);
1868 /* Process an ABSENCE_SET.
1870 This gives information about a cpu unit reservation requirements.
1871 We fill a struct unit_pattern_rel_decl (absence) with information
1872 used later by `expand_automata'. */
1873 void
1874 gen_absence_set (rtx def)
1876 gen_presence_absence_set (def, FALSE, FALSE);
1879 /* Process a FINAL_ABSENCE_SET.
1881 This gives information about a cpu unit reservation requirements.
1882 We fill a struct unit_pattern_rel_decl (absence) with information
1883 used later by `expand_automata'. */
1884 void
1885 gen_final_absence_set (rtx def)
1887 gen_presence_absence_set (def, FALSE, TRUE);
1890 /* Process a DEFINE_AUTOMATON.
1892 This gives information about a finite state automaton used for
1893 recognizing pipeline hazards. We fill a struct automaton_decl
1894 with information used later by `expand_automata'. */
1895 void
1896 gen_automaton (rtx def)
1898 decl_t decl;
1899 char **str_automata;
1900 int vect_length;
1901 int i;
1903 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',',
1904 FALSE);
1905 if (str_automata == NULL)
1906 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1907 for (i = 0; i < vect_length; i++)
1909 decl = create_node (sizeof (struct decl));
1910 decl->mode = dm_automaton;
1911 decl->pos = 0;
1912 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1913 VLA_PTR_ADD (decls, decl);
1914 num_dfa_decls++;
1918 /* Process an AUTOMATA_OPTION.
1920 This gives information how to generate finite state automaton used
1921 for recognizing pipeline hazards. */
1922 void
1923 gen_automata_option (rtx def)
1925 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1926 no_minimization_flag = 1;
1927 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1928 time_flag = 1;
1929 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1930 v_flag = 1;
1931 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1932 w_flag = 1;
1933 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1934 ndfa_flag = 1;
1935 else
1936 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1939 /* Name in reservation to denote absence reservation. */
1940 #define NOTHING_NAME "nothing"
1942 /* The following string contains original reservation string being
1943 parsed. */
1944 static char *reserv_str;
1946 /* Parse an element in STR. */
1947 static regexp_t
1948 gen_regexp_el (char *str)
1950 regexp_t regexp;
1951 int len;
1953 if (*str == '(')
1955 len = strlen (str);
1956 if (str [len - 1] != ')')
1957 fatal ("garbage after ) in reservation `%s'", reserv_str);
1958 str [len - 1] = '\0';
1959 regexp = gen_regexp_sequence (str + 1);
1961 else if (strcmp (str, NOTHING_NAME) == 0)
1963 regexp = create_node (sizeof (struct decl));
1964 regexp->mode = rm_nothing;
1966 else
1968 regexp = create_node (sizeof (struct decl));
1969 regexp->mode = rm_unit;
1970 REGEXP_UNIT (regexp)->name = str;
1972 return regexp;
1975 /* Parse construction `repeat' in STR. */
1976 static regexp_t
1977 gen_regexp_repeat (char *str)
1979 regexp_t regexp;
1980 regexp_t repeat;
1981 char **repeat_vect;
1982 int els_num;
1983 int i;
1985 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1986 if (repeat_vect == NULL)
1987 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1988 if (els_num > 1)
1990 regexp = gen_regexp_el (repeat_vect [0]);
1991 for (i = 1; i < els_num; i++)
1993 repeat = create_node (sizeof (struct regexp));
1994 repeat->mode = rm_repeat;
1995 REGEXP_REPEAT (repeat)->regexp = regexp;
1996 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1997 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1998 fatal ("repetition `%s' <= 1 in reservation `%s'",
1999 str, reserv_str);
2000 regexp = repeat;
2002 return regexp;
2004 else
2005 return gen_regexp_el (str);
2008 /* Parse reservation STR which possibly contains separator '+'. */
2009 static regexp_t
2010 gen_regexp_allof (char *str)
2012 regexp_t allof;
2013 char **allof_vect;
2014 int els_num;
2015 int i;
2017 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
2018 if (allof_vect == NULL)
2019 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2020 if (els_num > 1)
2022 allof = create_node (sizeof (struct regexp)
2023 + sizeof (regexp_t) * (els_num - 1));
2024 allof->mode = rm_allof;
2025 REGEXP_ALLOF (allof)->regexps_num = els_num;
2026 for (i = 0; i < els_num; i++)
2027 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
2028 return allof;
2030 else
2031 return gen_regexp_repeat (str);
2034 /* Parse reservation STR which possibly contains separator '|'. */
2035 static regexp_t
2036 gen_regexp_oneof (char *str)
2038 regexp_t oneof;
2039 char **oneof_vect;
2040 int els_num;
2041 int i;
2043 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
2044 if (oneof_vect == NULL)
2045 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
2046 if (els_num > 1)
2048 oneof = create_node (sizeof (struct regexp)
2049 + sizeof (regexp_t) * (els_num - 1));
2050 oneof->mode = rm_oneof;
2051 REGEXP_ONEOF (oneof)->regexps_num = els_num;
2052 for (i = 0; i < els_num; i++)
2053 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
2054 return oneof;
2056 else
2057 return gen_regexp_allof (str);
2060 /* Parse reservation STR which possibly contains separator ','. */
2061 static regexp_t
2062 gen_regexp_sequence (char *str)
2064 regexp_t sequence;
2065 char **sequence_vect;
2066 int els_num;
2067 int i;
2069 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
2070 if (els_num > 1)
2072 sequence = create_node (sizeof (struct regexp)
2073 + sizeof (regexp_t) * (els_num - 1));
2074 sequence->mode = rm_sequence;
2075 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2076 for (i = 0; i < els_num; i++)
2077 REGEXP_SEQUENCE (sequence)->regexps [i]
2078 = gen_regexp_oneof (sequence_vect [i]);
2079 return sequence;
2081 else
2082 return gen_regexp_oneof (str);
2085 /* Parse construction reservation STR. */
2086 static regexp_t
2087 gen_regexp (char *str)
2089 reserv_str = str;
2090 return gen_regexp_sequence (str);;
2093 /* Process a DEFINE_RESERVATION.
2095 This gives information about a reservation of cpu units. We fill
2096 in a struct reserv_decl with information used later by
2097 `expand_automata'. */
2098 void
2099 gen_reserv (rtx def)
2101 decl_t decl;
2103 decl = create_node (sizeof (struct decl));
2104 decl->mode = dm_reserv;
2105 decl->pos = 0;
2106 DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2107 DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2108 VLA_PTR_ADD (decls, decl);
2109 num_dfa_decls++;
2112 /* Process a DEFINE_INSN_RESERVATION.
2114 This gives information about the reservation of cpu units by an
2115 insn. We fill a struct insn_reserv_decl with information used
2116 later by `expand_automata'. */
2117 void
2118 gen_insn_reserv (rtx def)
2120 decl_t decl;
2122 decl = create_node (sizeof (struct decl));
2123 decl->mode = dm_insn_reserv;
2124 decl->pos = 0;
2125 DECL_INSN_RESERV (decl)->name
2126 = check_name ((char *) XSTR (def, 0), decl->pos);
2127 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2128 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2129 DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2130 VLA_PTR_ADD (decls, decl);
2131 num_dfa_decls++;
2136 /* The function evaluates hash value (0..UINT_MAX) of string. */
2137 static unsigned
2138 string_hash (const char *string)
2140 unsigned result, i;
2142 for (result = i = 0;*string++ != '\0'; i++)
2143 result += ((unsigned char) *string << (i % CHAR_BIT));
2144 return result;
2149 /* This page contains abstract data `table of automaton declarations'.
2150 Elements of the table is nodes representing automaton declarations.
2151 Key of the table elements is name of given automaton. Remember
2152 that automaton names have own space. */
2154 /* The function evaluates hash value of an automaton declaration. The
2155 function is used by abstract data `hashtab'. The function returns
2156 hash value (0..UINT_MAX) of given automaton declaration. */
2157 static hashval_t
2158 automaton_decl_hash (const void *automaton_decl)
2160 const decl_t decl = (decl_t) automaton_decl;
2162 if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
2163 abort ();
2164 return string_hash (DECL_AUTOMATON (decl)->name);
2167 /* The function tests automaton declarations on equality of their
2168 keys. The function is used by abstract data `hashtab'. The
2169 function returns 1 if the declarations have the same key, 0
2170 otherwise. */
2171 static int
2172 automaton_decl_eq_p (const void* automaton_decl_1,
2173 const void* automaton_decl_2)
2175 const decl_t decl1 = (decl_t) automaton_decl_1;
2176 const decl_t decl2 = (decl_t) automaton_decl_2;
2178 if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
2179 || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
2180 abort ();
2181 return strcmp (DECL_AUTOMATON (decl1)->name,
2182 DECL_AUTOMATON (decl2)->name) == 0;
2185 /* The automaton declaration table itself is represented by the
2186 following variable. */
2187 static htab_t automaton_decl_table;
2189 /* The function inserts automaton declaration into the table. The
2190 function does nothing if an automaton declaration with the same key
2191 exists already in the table. The function returns automaton
2192 declaration node in the table with the same key as given automaton
2193 declaration node. */
2194 static decl_t
2195 insert_automaton_decl (decl_t automaton_decl)
2197 void **entry_ptr;
2199 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
2200 if (*entry_ptr == NULL)
2201 *entry_ptr = (void *) automaton_decl;
2202 return (decl_t) *entry_ptr;
2205 /* The following variable value is node representing automaton
2206 declaration. The node used for searching automaton declaration
2207 with given name. */
2208 static struct decl work_automaton_decl;
2210 /* The function searches for automaton declaration in the table with
2211 the same key as node representing name of the automaton
2212 declaration. The function returns node found in the table, NULL if
2213 such node does not exist in the table. */
2214 static decl_t
2215 find_automaton_decl (char *name)
2217 void *entry;
2219 work_automaton_decl.mode = dm_automaton;
2220 DECL_AUTOMATON (&work_automaton_decl)->name = name;
2221 entry = htab_find (automaton_decl_table, &work_automaton_decl);
2222 return (decl_t) entry;
2225 /* The function creates empty automaton declaration table and node
2226 representing automaton declaration and used for searching automaton
2227 declaration with given name. The function must be called only once
2228 before any work with the automaton declaration table. */
2229 static void
2230 initiate_automaton_decl_table (void)
2232 work_automaton_decl.mode = dm_automaton;
2233 automaton_decl_table = htab_create (10, automaton_decl_hash,
2234 automaton_decl_eq_p, (htab_del) 0);
2237 /* The function deletes the automaton declaration table. Only call of
2238 function `initiate_automaton_decl_table' is possible immediately
2239 after this function call. */
2240 static void
2241 finish_automaton_decl_table (void)
2243 htab_delete (automaton_decl_table);
2248 /* This page contains abstract data `table of insn declarations'.
2249 Elements of the table is nodes representing insn declarations. Key
2250 of the table elements is name of given insn (in corresponding
2251 define_insn_reservation). Remember that insn names have own
2252 space. */
2254 /* The function evaluates hash value of an insn declaration. The
2255 function is used by abstract data `hashtab'. The function returns
2256 hash value (0..UINT_MAX) of given insn declaration. */
2257 static hashval_t
2258 insn_decl_hash (const void *insn_decl)
2260 const decl_t decl = (decl_t) insn_decl;
2262 if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
2263 abort ();
2264 return string_hash (DECL_INSN_RESERV (decl)->name);
2267 /* The function tests insn declarations on equality of their keys.
2268 The function is used by abstract data `hashtab'. The function
2269 returns 1 if declarations have the same key, 0 otherwise. */
2270 static int
2271 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
2273 const decl_t decl1 = (decl_t) insn_decl_1;
2274 const decl_t decl2 = (decl_t) insn_decl_2;
2276 if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
2277 || decl2->mode != dm_insn_reserv
2278 || DECL_INSN_RESERV (decl2)->name == NULL)
2279 abort ();
2280 return strcmp (DECL_INSN_RESERV (decl1)->name,
2281 DECL_INSN_RESERV (decl2)->name) == 0;
2284 /* The insn declaration table itself is represented by the following
2285 variable. The table does not contain insn reservation
2286 declarations. */
2287 static htab_t insn_decl_table;
2289 /* The function inserts insn declaration into the table. The function
2290 does nothing if an insn declaration with the same key exists
2291 already in the table. The function returns insn declaration node
2292 in the table with the same key as given insn declaration node. */
2293 static decl_t
2294 insert_insn_decl (decl_t insn_decl)
2296 void **entry_ptr;
2298 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2299 if (*entry_ptr == NULL)
2300 *entry_ptr = (void *) insn_decl;
2301 return (decl_t) *entry_ptr;
2304 /* The following variable value is node representing insn reservation
2305 declaration. The node used for searching insn reservation
2306 declaration with given name. */
2307 static struct decl work_insn_decl;
2309 /* The function searches for insn reservation declaration in the table
2310 with the same key as node representing name of the insn reservation
2311 declaration. The function returns node found in the table, NULL if
2312 such node does not exist in the table. */
2313 static decl_t
2314 find_insn_decl (char *name)
2316 void *entry;
2318 work_insn_decl.mode = dm_insn_reserv;
2319 DECL_INSN_RESERV (&work_insn_decl)->name = name;
2320 entry = htab_find (insn_decl_table, &work_insn_decl);
2321 return (decl_t) entry;
2324 /* The function creates empty insn declaration table and node
2325 representing insn declaration and used for searching insn
2326 declaration with given name. The function must be called only once
2327 before any work with the insn declaration table. */
2328 static void
2329 initiate_insn_decl_table (void)
2331 work_insn_decl.mode = dm_insn_reserv;
2332 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2333 (htab_del) 0);
2336 /* The function deletes the insn declaration table. Only call of
2337 function `initiate_insn_decl_table' is possible immediately after
2338 this function call. */
2339 static void
2340 finish_insn_decl_table (void)
2342 htab_delete (insn_decl_table);
2347 /* This page contains abstract data `table of declarations'. Elements
2348 of the table is nodes representing declarations (of units and
2349 reservations). Key of the table elements is names of given
2350 declarations. */
2352 /* The function evaluates hash value of a declaration. The function
2353 is used by abstract data `hashtab'. The function returns hash
2354 value (0..UINT_MAX) of given declaration. */
2355 static hashval_t
2356 decl_hash (const void *decl)
2358 const decl_t d = (const decl_t) decl;
2360 if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
2361 && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
2362 abort ();
2363 return string_hash (d->mode == dm_unit
2364 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
2367 /* The function tests declarations on equality of their keys. The
2368 function is used by abstract data `hashtab'. The function
2369 returns 1 if the declarations have the same key, 0 otherwise. */
2370 static int
2371 decl_eq_p (const void *decl_1, const void *decl_2)
2373 const decl_t d1 = (const decl_t) decl_1;
2374 const decl_t d2 = (const decl_t) decl_2;
2376 if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
2377 && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
2378 || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
2379 && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
2380 abort ();
2381 return strcmp ((d1->mode == dm_unit
2382 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
2383 (d2->mode == dm_unit
2384 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2387 /* The declaration table itself is represented by the following
2388 variable. */
2389 static htab_t decl_table;
2391 /* The function inserts declaration into the table. The function does
2392 nothing if a declaration with the same key exists already in the
2393 table. The function returns declaration node in the table with the
2394 same key as given declaration node. */
2396 static decl_t
2397 insert_decl (decl_t decl)
2399 void **entry_ptr;
2401 entry_ptr = htab_find_slot (decl_table, decl, 1);
2402 if (*entry_ptr == NULL)
2403 *entry_ptr = (void *) decl;
2404 return (decl_t) *entry_ptr;
2407 /* The following variable value is node representing declaration. The
2408 node used for searching declaration with given name. */
2409 static struct decl work_decl;
2411 /* The function searches for declaration in the table with the same
2412 key as node representing name of the declaration. The function
2413 returns node found in the table, NULL if such node does not exist
2414 in the table. */
2415 static decl_t
2416 find_decl (char *name)
2418 void *entry;
2420 work_decl.mode = dm_unit;
2421 DECL_UNIT (&work_decl)->name = name;
2422 entry = htab_find (decl_table, &work_decl);
2423 return (decl_t) entry;
2426 /* The function creates empty declaration table and node representing
2427 declaration and used for searching declaration with given name.
2428 The function must be called only once before any work with the
2429 declaration table. */
2430 static void
2431 initiate_decl_table (void)
2433 work_decl.mode = dm_unit;
2434 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2437 /* The function deletes the declaration table. Only call of function
2438 `initiate_declaration_table' is possible immediately after this
2439 function call. */
2440 static void
2441 finish_decl_table (void)
2443 htab_delete (decl_table);
2448 /* This page contains checker of pipeline hazard description. */
2450 /* Checking NAMES in an exclusion clause vector and returning formed
2451 unit_set_el_list. */
2452 static unit_set_el_t
2453 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2455 unit_set_el_t el_list;
2456 unit_set_el_t last_el;
2457 unit_set_el_t new_el;
2458 decl_t decl_in_table;
2459 int i;
2461 el_list = NULL;
2462 last_el = NULL;
2463 for (i = 0; i < num; i++)
2465 decl_in_table = find_decl (names [i]);
2466 if (decl_in_table == NULL)
2467 error ("unit `%s' in exclusion is not declared", names [i]);
2468 else if (decl_in_table->mode != dm_unit)
2469 error ("`%s' in exclusion is not unit", names [i]);
2470 else
2472 new_el = create_node (sizeof (struct unit_set_el));
2473 new_el->unit_decl = DECL_UNIT (decl_in_table);
2474 new_el->next_unit_set_el = NULL;
2475 if (last_el == NULL)
2476 el_list = last_el = new_el;
2477 else
2479 last_el->next_unit_set_el = new_el;
2480 last_el = last_el->next_unit_set_el;
2484 return el_list;
2487 /* The function adds each element from SOURCE_LIST to the exclusion
2488 list of the each element from DEST_LIST. Checking situation "unit
2489 excludes itself". */
2490 static void
2491 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2492 pos_t excl_pos ATTRIBUTE_UNUSED)
2494 unit_set_el_t dst;
2495 unit_set_el_t src;
2496 unit_set_el_t curr_el;
2497 unit_set_el_t prev_el;
2498 unit_set_el_t copy;
2500 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2501 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2503 if (dst->unit_decl == src->unit_decl)
2505 error ("unit `%s' excludes itself", src->unit_decl->name);
2506 continue;
2508 if (dst->unit_decl->automaton_name != NULL
2509 && src->unit_decl->automaton_name != NULL
2510 && strcmp (dst->unit_decl->automaton_name,
2511 src->unit_decl->automaton_name) != 0)
2513 error ("units `%s' and `%s' in exclusion set belong to different automata",
2514 src->unit_decl->name, dst->unit_decl->name);
2515 continue;
2517 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2518 curr_el != NULL;
2519 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2520 if (curr_el->unit_decl == src->unit_decl)
2521 break;
2522 if (curr_el == NULL)
2524 /* Element not found - insert. */
2525 copy = copy_node (src, sizeof (*src));
2526 copy->next_unit_set_el = NULL;
2527 if (prev_el == NULL)
2528 dst->unit_decl->excl_list = copy;
2529 else
2530 prev_el->next_unit_set_el = copy;
2535 /* Checking NAMES in presence/absence clause and returning the
2536 formed unit_set_el_list. The function is called only after
2537 processing all exclusion sets. */
2538 static unit_set_el_t
2539 process_presence_absence_names (char **names, int num,
2540 pos_t req_pos ATTRIBUTE_UNUSED,
2541 int presence_p, int final_p)
2543 unit_set_el_t el_list;
2544 unit_set_el_t last_el;
2545 unit_set_el_t new_el;
2546 decl_t decl_in_table;
2547 int i;
2549 el_list = NULL;
2550 last_el = NULL;
2551 for (i = 0; i < num; i++)
2553 decl_in_table = find_decl (names [i]);
2554 if (decl_in_table == NULL)
2555 error ((presence_p
2556 ? (final_p
2557 ? "unit `%s' in final presence set is not declared"
2558 : "unit `%s' in presence set is not declared")
2559 : (final_p
2560 ? "unit `%s' in final absence set is not declared"
2561 : "unit `%s' in absence set is not declared")), names [i]);
2562 else if (decl_in_table->mode != dm_unit)
2563 error ((presence_p
2564 ? (final_p
2565 ? "`%s' in final presence set is not unit"
2566 : "`%s' in presence set is not unit")
2567 : (final_p
2568 ? "`%s' in final absence set is not unit"
2569 : "`%s' in absence set is not unit")), names [i]);
2570 else
2572 new_el = create_node (sizeof (struct unit_set_el));
2573 new_el->unit_decl = DECL_UNIT (decl_in_table);
2574 new_el->next_unit_set_el = NULL;
2575 if (last_el == NULL)
2576 el_list = last_el = new_el;
2577 else
2579 last_el->next_unit_set_el = new_el;
2580 last_el = last_el->next_unit_set_el;
2584 return el_list;
2587 /* Checking NAMES in patterns of a presence/absence clause and
2588 returning the formed pattern_set_el_list. The function is called
2589 only after processing all exclusion sets. */
2590 static pattern_set_el_t
2591 process_presence_absence_patterns (char ***patterns, int num,
2592 pos_t req_pos ATTRIBUTE_UNUSED,
2593 int presence_p, int final_p)
2595 pattern_set_el_t el_list;
2596 pattern_set_el_t last_el;
2597 pattern_set_el_t new_el;
2598 decl_t decl_in_table;
2599 int i, j;
2601 el_list = NULL;
2602 last_el = NULL;
2603 for (i = 0; i < num; i++)
2605 for (j = 0; patterns [i] [j] != NULL; j++)
2607 new_el = create_node (sizeof (struct pattern_set_el)
2608 + sizeof (struct unit_decl *) * j);
2609 new_el->unit_decls
2610 = (struct unit_decl **) ((char *) new_el
2611 + sizeof (struct pattern_set_el));
2612 new_el->next_pattern_set_el = NULL;
2613 if (last_el == NULL)
2614 el_list = last_el = new_el;
2615 else
2617 last_el->next_pattern_set_el = new_el;
2618 last_el = last_el->next_pattern_set_el;
2620 new_el->units_num = 0;
2621 for (j = 0; patterns [i] [j] != NULL; j++)
2623 decl_in_table = find_decl (patterns [i] [j]);
2624 if (decl_in_table == NULL)
2625 error ((presence_p
2626 ? (final_p
2627 ? "unit `%s' in final presence set is not declared"
2628 : "unit `%s' in presence set is not declared")
2629 : (final_p
2630 ? "unit `%s' in final absence set is not declared"
2631 : "unit `%s' in absence set is not declared")),
2632 patterns [i] [j]);
2633 else if (decl_in_table->mode != dm_unit)
2634 error ((presence_p
2635 ? (final_p
2636 ? "`%s' in final presence set is not unit"
2637 : "`%s' in presence set is not unit")
2638 : (final_p
2639 ? "`%s' in final absence set is not unit"
2640 : "`%s' in absence set is not unit")),
2641 patterns [i] [j]);
2642 else
2644 new_el->unit_decls [new_el->units_num]
2645 = DECL_UNIT (decl_in_table);
2646 new_el->units_num++;
2650 return el_list;
2653 /* The function adds each element from PATTERN_LIST to presence (if
2654 PRESENCE_P) or absence list of the each element from DEST_LIST.
2655 Checking situations "unit requires own absence", and "unit excludes
2656 and requires presence of ...", "unit requires absence and presence
2657 of ...", "units in (final) presence set belong to different
2658 automata", and "units in (final) absence set belong to different
2659 automata". Remember that we process absence sets only after all
2660 presence sets. */
2661 static void
2662 add_presence_absence (unit_set_el_t dest_list,
2663 pattern_set_el_t pattern_list,
2664 pos_t req_pos ATTRIBUTE_UNUSED,
2665 int presence_p, int final_p)
2667 unit_set_el_t dst;
2668 pattern_set_el_t pat;
2669 struct unit_decl *unit;
2670 unit_set_el_t curr_excl_el;
2671 pattern_set_el_t curr_pat_el;
2672 pattern_set_el_t prev_el;
2673 pattern_set_el_t copy;
2674 int i;
2675 int no_error_flag;
2677 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2678 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2680 for (i = 0; i < pat->units_num; i++)
2682 unit = pat->unit_decls [i];
2683 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2685 error ("unit `%s' requires own absence", unit->name);
2686 continue;
2688 if (dst->unit_decl->automaton_name != NULL
2689 && unit->automaton_name != NULL
2690 && strcmp (dst->unit_decl->automaton_name,
2691 unit->automaton_name) != 0)
2693 error ((presence_p
2694 ? (final_p
2695 ? "units `%s' and `%s' in final presence set belong to different automata"
2696 : "units `%s' and `%s' in presence set belong to different automata")
2697 : (final_p
2698 ? "units `%s' and `%s' in final absence set belong to different automata"
2699 : "units `%s' and `%s' in absence set belong to different automata")),
2700 unit->name, dst->unit_decl->name);
2701 continue;
2703 no_error_flag = 1;
2704 if (presence_p)
2705 for (curr_excl_el = dst->unit_decl->excl_list;
2706 curr_excl_el != NULL;
2707 curr_excl_el = curr_excl_el->next_unit_set_el)
2709 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2711 if (!w_flag)
2713 error ("unit `%s' excludes and requires presence of `%s'",
2714 dst->unit_decl->name, unit->name);
2715 no_error_flag = 0;
2717 else
2718 warning
2719 ("unit `%s' excludes and requires presence of `%s'",
2720 dst->unit_decl->name, unit->name);
2723 else if (pat->units_num == 1)
2724 for (curr_pat_el = dst->unit_decl->presence_list;
2725 curr_pat_el != NULL;
2726 curr_pat_el = curr_pat_el->next_pattern_set_el)
2727 if (curr_pat_el->units_num == 1
2728 && unit == curr_pat_el->unit_decls [0])
2730 if (!w_flag)
2732 error
2733 ("unit `%s' requires absence and presence of `%s'",
2734 dst->unit_decl->name, unit->name);
2735 no_error_flag = 0;
2737 else
2738 warning
2739 ("unit `%s' requires absence and presence of `%s'",
2740 dst->unit_decl->name, unit->name);
2742 if (no_error_flag)
2744 for (prev_el = (presence_p
2745 ? (final_p
2746 ? dst->unit_decl->final_presence_list
2747 : dst->unit_decl->final_presence_list)
2748 : (final_p
2749 ? dst->unit_decl->final_absence_list
2750 : dst->unit_decl->absence_list));
2751 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2752 prev_el = prev_el->next_pattern_set_el)
2754 copy = copy_node (pat, sizeof (*pat));
2755 copy->next_pattern_set_el = NULL;
2756 if (prev_el == NULL)
2758 if (presence_p)
2760 if (final_p)
2761 dst->unit_decl->final_presence_list = copy;
2762 else
2763 dst->unit_decl->presence_list = copy;
2765 else if (final_p)
2766 dst->unit_decl->final_absence_list = copy;
2767 else
2768 dst->unit_decl->absence_list = copy;
2770 else
2771 prev_el->next_pattern_set_el = copy;
2778 /* The function searches for bypass with given IN_INSN_RESERV in given
2779 BYPASS_LIST. */
2780 static struct bypass_decl *
2781 find_bypass (struct bypass_decl *bypass_list,
2782 struct insn_reserv_decl *in_insn_reserv)
2784 struct bypass_decl *bypass;
2786 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2787 if (bypass->in_insn_reserv == in_insn_reserv)
2788 break;
2789 return bypass;
2792 /* The function processes pipeline description declarations, checks
2793 their correctness, and forms exclusion/presence/absence sets. */
2794 static void
2795 process_decls (void)
2797 decl_t decl;
2798 decl_t automaton_decl;
2799 decl_t decl_in_table;
2800 decl_t out_insn_reserv;
2801 decl_t in_insn_reserv;
2802 struct bypass_decl *bypass;
2803 int automaton_presence;
2804 int i;
2806 /* Checking repeated automata declarations. */
2807 automaton_presence = 0;
2808 for (i = 0; i < description->decls_num; i++)
2810 decl = description->decls [i];
2811 if (decl->mode == dm_automaton)
2813 automaton_presence = 1;
2814 decl_in_table = insert_automaton_decl (decl);
2815 if (decl_in_table != decl)
2817 if (!w_flag)
2818 error ("repeated declaration of automaton `%s'",
2819 DECL_AUTOMATON (decl)->name);
2820 else
2821 warning ("repeated declaration of automaton `%s'",
2822 DECL_AUTOMATON (decl)->name);
2826 /* Checking undeclared automata, repeated declarations (except for
2827 automata) and correctness of their attributes (insn latency times
2828 etc.). */
2829 for (i = 0; i < description->decls_num; i++)
2831 decl = description->decls [i];
2832 if (decl->mode == dm_insn_reserv)
2834 DECL_INSN_RESERV (decl)->condexp
2835 = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
2836 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2837 error ("define_insn_reservation `%s' has negative latency time",
2838 DECL_INSN_RESERV (decl)->name);
2839 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2840 description->insns_num++;
2841 decl_in_table = insert_insn_decl (decl);
2842 if (decl_in_table != decl)
2843 error ("`%s' is already used as insn reservation name",
2844 DECL_INSN_RESERV (decl)->name);
2846 else if (decl->mode == dm_bypass)
2848 if (DECL_BYPASS (decl)->latency < 0)
2849 error ("define_bypass `%s - %s' has negative latency time",
2850 DECL_BYPASS (decl)->out_insn_name,
2851 DECL_BYPASS (decl)->in_insn_name);
2853 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2855 if (decl->mode == dm_unit)
2857 DECL_UNIT (decl)->automaton_decl = NULL;
2858 if (DECL_UNIT (decl)->automaton_name != NULL)
2860 automaton_decl
2861 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2862 if (automaton_decl == NULL)
2863 error ("automaton `%s' is not declared",
2864 DECL_UNIT (decl)->automaton_name);
2865 else
2867 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2868 DECL_UNIT (decl)->automaton_decl
2869 = DECL_AUTOMATON (automaton_decl);
2872 else if (automaton_presence)
2873 error ("define_unit `%s' without automaton when one defined",
2874 DECL_UNIT (decl)->name);
2875 DECL_UNIT (decl)->unit_num = description->units_num;
2876 description->units_num++;
2877 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2879 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2880 continue;
2882 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2884 else
2886 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2888 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2889 continue;
2891 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2893 if (decl_in_table == NULL)
2894 decl_in_table = insert_decl (decl);
2895 else
2897 if (decl->mode == dm_unit)
2898 error ("repeated declaration of unit `%s'",
2899 DECL_UNIT (decl)->name);
2900 else
2901 error ("repeated declaration of reservation `%s'",
2902 DECL_RESERV (decl)->name);
2906 /* Check bypasses and form list of bypasses for each (output)
2907 insn. */
2908 for (i = 0; i < description->decls_num; i++)
2910 decl = description->decls [i];
2911 if (decl->mode == dm_bypass)
2913 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2914 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2915 if (out_insn_reserv == NULL)
2916 error ("there is no insn reservation `%s'",
2917 DECL_BYPASS (decl)->out_insn_name);
2918 else if (in_insn_reserv == NULL)
2919 error ("there is no insn reservation `%s'",
2920 DECL_BYPASS (decl)->in_insn_name);
2921 else
2923 DECL_BYPASS (decl)->out_insn_reserv
2924 = DECL_INSN_RESERV (out_insn_reserv);
2925 DECL_BYPASS (decl)->in_insn_reserv
2926 = DECL_INSN_RESERV (in_insn_reserv);
2927 bypass
2928 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2929 DECL_BYPASS (decl)->in_insn_reserv);
2930 if (bypass != NULL)
2932 if (DECL_BYPASS (decl)->latency == bypass->latency)
2934 if (!w_flag)
2935 error
2936 ("the same bypass `%s - %s' is already defined",
2937 DECL_BYPASS (decl)->out_insn_name,
2938 DECL_BYPASS (decl)->in_insn_name);
2939 else
2940 warning
2941 ("the same bypass `%s - %s' is already defined",
2942 DECL_BYPASS (decl)->out_insn_name,
2943 DECL_BYPASS (decl)->in_insn_name);
2945 else
2946 error ("bypass `%s - %s' is already defined",
2947 DECL_BYPASS (decl)->out_insn_name,
2948 DECL_BYPASS (decl)->in_insn_name);
2950 else
2952 DECL_BYPASS (decl)->next
2953 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2954 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2955 = DECL_BYPASS (decl);
2961 /* Check exclusion set declarations and form exclusion sets. */
2962 for (i = 0; i < description->decls_num; i++)
2964 decl = description->decls [i];
2965 if (decl->mode == dm_excl)
2967 unit_set_el_t unit_set_el_list;
2968 unit_set_el_t unit_set_el_list_2;
2970 unit_set_el_list
2971 = process_excls (DECL_EXCL (decl)->names,
2972 DECL_EXCL (decl)->first_list_length, decl->pos);
2973 unit_set_el_list_2
2974 = process_excls (&DECL_EXCL (decl)->names
2975 [DECL_EXCL (decl)->first_list_length],
2976 DECL_EXCL (decl)->all_names_num
2977 - DECL_EXCL (decl)->first_list_length,
2978 decl->pos);
2979 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2980 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2984 /* Check presence set declarations and form presence sets. */
2985 for (i = 0; i < description->decls_num; i++)
2987 decl = description->decls [i];
2988 if (decl->mode == dm_presence)
2990 unit_set_el_t unit_set_el_list;
2991 pattern_set_el_t pattern_set_el_list;
2993 unit_set_el_list
2994 = process_presence_absence_names
2995 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2996 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2997 pattern_set_el_list
2998 = process_presence_absence_patterns
2999 (DECL_PRESENCE (decl)->patterns,
3000 DECL_PRESENCE (decl)->patterns_num,
3001 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
3002 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3003 decl->pos, TRUE,
3004 DECL_PRESENCE (decl)->final_p);
3008 /* Check absence set declarations and form absence sets. */
3009 for (i = 0; i < description->decls_num; i++)
3011 decl = description->decls [i];
3012 if (decl->mode == dm_absence)
3014 unit_set_el_t unit_set_el_list;
3015 pattern_set_el_t pattern_set_el_list;
3017 unit_set_el_list
3018 = process_presence_absence_names
3019 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
3020 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3021 pattern_set_el_list
3022 = process_presence_absence_patterns
3023 (DECL_ABSENCE (decl)->patterns,
3024 DECL_ABSENCE (decl)->patterns_num,
3025 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
3026 add_presence_absence (unit_set_el_list, pattern_set_el_list,
3027 decl->pos, FALSE,
3028 DECL_ABSENCE (decl)->final_p);
3033 /* The following function checks that declared automaton is used. If
3034 the automaton is not used, the function fixes error/warning. The
3035 following function must be called only after `process_decls'. */
3036 static void
3037 check_automaton_usage (void)
3039 decl_t decl;
3040 int i;
3042 for (i = 0; i < description->decls_num; i++)
3044 decl = description->decls [i];
3045 if (decl->mode == dm_automaton
3046 && !DECL_AUTOMATON (decl)->automaton_is_used)
3048 if (!w_flag)
3049 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
3050 else
3051 warning ("automaton `%s' is not used",
3052 DECL_AUTOMATON (decl)->name);
3057 /* The following recursive function processes all regexp in order to
3058 fix usage of units or reservations and to fix errors of undeclared
3059 name. The function may change unit_regexp onto reserv_regexp.
3060 Remember that reserv_regexp does not exist before the function
3061 call. */
3062 static regexp_t
3063 process_regexp (regexp_t regexp)
3065 decl_t decl_in_table;
3066 regexp_t new_regexp;
3067 int i;
3069 if (regexp->mode == rm_unit)
3071 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
3072 if (decl_in_table == NULL)
3073 error ("undeclared unit or reservation `%s'",
3074 REGEXP_UNIT (regexp)->name);
3075 else if (decl_in_table->mode == dm_unit)
3077 DECL_UNIT (decl_in_table)->unit_is_used = 1;
3078 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
3080 else if (decl_in_table->mode == dm_reserv)
3082 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
3083 new_regexp = create_node (sizeof (struct regexp));
3084 new_regexp->mode = rm_reserv;
3085 new_regexp->pos = regexp->pos;
3086 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
3087 REGEXP_RESERV (new_regexp)->reserv_decl
3088 = DECL_RESERV (decl_in_table);
3089 regexp = new_regexp;
3091 else
3092 abort ();
3094 else if (regexp->mode == rm_sequence)
3095 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3096 REGEXP_SEQUENCE (regexp)->regexps [i]
3097 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
3098 else if (regexp->mode == rm_allof)
3099 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3100 REGEXP_ALLOF (regexp)->regexps [i]
3101 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
3102 else if (regexp->mode == rm_oneof)
3103 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3104 REGEXP_ONEOF (regexp)->regexps [i]
3105 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
3106 else if (regexp->mode == rm_repeat)
3107 REGEXP_REPEAT (regexp)->regexp
3108 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
3109 else if (regexp->mode != rm_nothing)
3110 abort ();
3111 return regexp;
3114 /* The following function processes regexp of define_reservation and
3115 define_insn_reservation with the aid of function
3116 `process_regexp'. */
3117 static void
3118 process_regexp_decls (void)
3120 decl_t decl;
3121 int i;
3123 for (i = 0; i < description->decls_num; i++)
3125 decl = description->decls [i];
3126 if (decl->mode == dm_reserv)
3127 DECL_RESERV (decl)->regexp
3128 = process_regexp (DECL_RESERV (decl)->regexp);
3129 else if (decl->mode == dm_insn_reserv)
3130 DECL_INSN_RESERV (decl)->regexp
3131 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3135 /* The following function checks that declared unit is used. If the
3136 unit is not used, the function fixes errors/warnings. The
3137 following function must be called only after `process_decls',
3138 `process_regexp_decls'. */
3139 static void
3140 check_usage (void)
3142 decl_t decl;
3143 int i;
3145 for (i = 0; i < description->decls_num; i++)
3147 decl = description->decls [i];
3148 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3150 if (!w_flag)
3151 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3152 else
3153 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3155 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3157 if (!w_flag)
3158 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3159 else
3160 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3165 /* The following variable value is number of reservation being
3166 processed on loop recognition. */
3167 static int curr_loop_pass_num;
3169 /* The following recursive function returns nonzero value if REGEXP
3170 contains given decl or reservations in given regexp refers for
3171 given decl. */
3172 static int
3173 loop_in_regexp (regexp_t regexp, decl_t start_decl)
3175 int i;
3177 if (regexp == NULL)
3178 return 0;
3179 if (regexp->mode == rm_unit)
3180 return 0;
3181 else if (regexp->mode == rm_reserv)
3183 if (start_decl->mode == dm_reserv
3184 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3185 return 1;
3186 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3187 == curr_loop_pass_num)
3188 /* declaration has been processed. */
3189 return 0;
3190 else
3192 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3193 = curr_loop_pass_num;
3194 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3195 start_decl);
3198 else if (regexp->mode == rm_sequence)
3200 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3201 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3202 return 1;
3203 return 0;
3205 else if (regexp->mode == rm_allof)
3207 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3208 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3209 return 1;
3210 return 0;
3212 else if (regexp->mode == rm_oneof)
3214 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3215 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3216 return 1;
3217 return 0;
3219 else if (regexp->mode == rm_repeat)
3220 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3221 else
3223 if (regexp->mode != rm_nothing)
3224 abort ();
3225 return 0;
3229 /* The following function fixes errors "cycle in definition ...". The
3230 function uses function `loop_in_regexp' for that. */
3231 static void
3232 check_loops_in_regexps (void)
3234 decl_t decl;
3235 int i;
3237 for (i = 0; i < description->decls_num; i++)
3239 decl = description->decls [i];
3240 if (decl->mode == dm_reserv)
3241 DECL_RESERV (decl)->loop_pass_num = 0;
3243 for (i = 0; i < description->decls_num; i++)
3245 decl = description->decls [i];
3246 curr_loop_pass_num = i;
3248 if (decl->mode == dm_reserv)
3250 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
3251 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3253 if (DECL_RESERV (decl)->regexp == NULL)
3254 abort ();
3255 error ("cycle in definition of reservation `%s'",
3256 DECL_RESERV (decl)->name);
3262 /* The function recursively processes IR of reservation and defines
3263 max and min cycle for reservation of unit. */
3264 static void
3265 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
3266 int min_start_cycle, int *max_finish_cycle,
3267 int *min_finish_cycle)
3269 int i;
3271 if (regexp->mode == rm_unit)
3273 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
3274 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
3275 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
3276 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
3277 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
3278 *max_finish_cycle = max_start_cycle;
3279 *min_finish_cycle = min_start_cycle;
3281 else if (regexp->mode == rm_reserv)
3282 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3283 max_start_cycle, min_start_cycle,
3284 max_finish_cycle, min_finish_cycle);
3285 else if (regexp->mode == rm_repeat)
3287 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3289 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3290 max_start_cycle, min_start_cycle,
3291 max_finish_cycle, min_finish_cycle);
3292 max_start_cycle = *max_finish_cycle + 1;
3293 min_start_cycle = *min_finish_cycle + 1;
3296 else if (regexp->mode == rm_sequence)
3298 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3300 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3301 max_start_cycle, min_start_cycle,
3302 max_finish_cycle, min_finish_cycle);
3303 max_start_cycle = *max_finish_cycle + 1;
3304 min_start_cycle = *min_finish_cycle + 1;
3307 else if (regexp->mode == rm_allof)
3309 int max_cycle = 0;
3310 int min_cycle = 0;
3312 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3314 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3315 max_start_cycle, min_start_cycle,
3316 max_finish_cycle, min_finish_cycle);
3317 if (max_cycle < *max_finish_cycle)
3318 max_cycle = *max_finish_cycle;
3319 if (i == 0 || min_cycle > *min_finish_cycle)
3320 min_cycle = *min_finish_cycle;
3322 *max_finish_cycle = max_cycle;
3323 *min_finish_cycle = min_cycle;
3325 else if (regexp->mode == rm_oneof)
3327 int max_cycle = 0;
3328 int min_cycle = 0;
3330 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3332 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3333 max_start_cycle, min_start_cycle,
3334 max_finish_cycle, min_finish_cycle);
3335 if (max_cycle < *max_finish_cycle)
3336 max_cycle = *max_finish_cycle;
3337 if (i == 0 || min_cycle > *min_finish_cycle)
3338 min_cycle = *min_finish_cycle;
3340 *max_finish_cycle = max_cycle;
3341 *min_finish_cycle = min_cycle;
3343 else
3345 if (regexp->mode != rm_nothing)
3346 abort ();
3347 *max_finish_cycle = max_start_cycle;
3348 *min_finish_cycle = min_start_cycle;
3352 /* The following function is called only for correct program. The
3353 function defines max reservation of insns in cycles. */
3354 static void
3355 evaluate_max_reserv_cycles (void)
3357 int max_insn_cycles_num;
3358 int min_insn_cycles_num;
3359 decl_t decl;
3360 int i;
3362 description->max_insn_reserv_cycles = 0;
3363 for (i = 0; i < description->decls_num; i++)
3365 decl = description->decls [i];
3366 if (decl->mode == dm_insn_reserv)
3368 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3369 &max_insn_cycles_num, &min_insn_cycles_num);
3370 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3371 description->max_insn_reserv_cycles = max_insn_cycles_num;
3374 description->max_insn_reserv_cycles++;
3377 /* The following function calls functions for checking all
3378 description. */
3379 static void
3380 check_all_description (void)
3382 process_decls ();
3383 check_automaton_usage ();
3384 process_regexp_decls ();
3385 check_usage ();
3386 check_loops_in_regexps ();
3387 if (!have_error)
3388 evaluate_max_reserv_cycles ();
3393 /* The page contains abstract data `ticker'. This data is used to
3394 report time of different phases of building automata. It is
3395 possibly to write a description for which automata will be built
3396 during several minutes even on fast machine. */
3398 /* The following function creates ticker and makes it active. */
3399 static ticker_t
3400 create_ticker (void)
3402 ticker_t ticker;
3404 ticker.modified_creation_time = get_run_time ();
3405 ticker.incremented_off_time = 0;
3406 return ticker;
3409 /* The following function switches off given ticker. */
3410 static void
3411 ticker_off (ticker_t *ticker)
3413 if (ticker->incremented_off_time == 0)
3414 ticker->incremented_off_time = get_run_time () + 1;
3417 /* The following function switches on given ticker. */
3418 static void
3419 ticker_on (ticker_t *ticker)
3421 if (ticker->incremented_off_time != 0)
3423 ticker->modified_creation_time
3424 += get_run_time () - ticker->incremented_off_time + 1;
3425 ticker->incremented_off_time = 0;
3429 /* The following function returns current time in milliseconds since
3430 the moment when given ticker was created. */
3431 static int
3432 active_time (ticker_t ticker)
3434 if (ticker.incremented_off_time != 0)
3435 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3436 else
3437 return get_run_time () - ticker.modified_creation_time;
3440 /* The following function returns string representation of active time
3441 of given ticker. The result is string representation of seconds
3442 with accuracy of 1/100 second. Only result of the last call of the
3443 function exists. Therefore the following code is not correct
3445 printf ("parser time: %s\ngeneration time: %s\n",
3446 active_time_string (parser_ticker),
3447 active_time_string (generation_ticker));
3449 Correct code has to be the following
3451 printf ("parser time: %s\n", active_time_string (parser_ticker));
3452 printf ("generation time: %s\n",
3453 active_time_string (generation_ticker));
3456 static void
3457 print_active_time (FILE *f, ticker_t ticker)
3459 int msecs;
3461 msecs = active_time (ticker);
3462 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3467 /* The following variable value is number of automaton which are
3468 really being created. This value is defined on the base of
3469 argument of option `-split'. If the variable has zero value the
3470 number of automata is defined by the constructions `%automaton'.
3471 This case occurs when option `-split' is absent or has zero
3472 argument. If constructions `define_automaton' is absent only one
3473 automaton is created. */
3474 static int automata_num;
3476 /* The following variable values are times of
3477 o transformation of regular expressions
3478 o building NDFA (DFA if !ndfa_flag)
3479 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3480 o DFA minimization
3481 o building insn equivalence classes
3482 o all previous ones
3483 o code output */
3484 static ticker_t transform_time;
3485 static ticker_t NDFA_time;
3486 static ticker_t NDFA_to_DFA_time;
3487 static ticker_t minimize_time;
3488 static ticker_t equiv_time;
3489 static ticker_t automaton_generation_time;
3490 static ticker_t output_time;
3492 /* The following variable values are times of
3493 all checking
3494 all generation
3495 all pipeline hazard translator work */
3496 static ticker_t check_time;
3497 static ticker_t generation_time;
3498 static ticker_t all_time;
3502 /* Pseudo insn decl which denotes advancing cycle. */
3503 static decl_t advance_cycle_insn_decl;
3504 static void
3505 add_advance_cycle_insn_decl (void)
3507 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3508 advance_cycle_insn_decl->mode = dm_insn_reserv;
3509 advance_cycle_insn_decl->pos = no_pos;
3510 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3511 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
3512 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3513 = description->insns_num;
3514 description->decls [description->decls_num] = advance_cycle_insn_decl;
3515 description->decls_num++;
3516 description->insns_num++;
3517 num_dfa_decls++;
3521 /* Abstract data `alternative states' which represents
3522 nondeterministic nature of the description (see comments for
3523 structures alt_state and state). */
3525 /* List of free states. */
3526 static alt_state_t first_free_alt_state;
3528 #ifndef NDEBUG
3529 /* The following variables is maximal number of allocated nodes
3530 alt_state. */
3531 static int allocated_alt_states_num = 0;
3532 #endif
3534 /* The following function returns free node alt_state. It may be new
3535 allocated node or node freed earlier. */
3536 static alt_state_t
3537 get_free_alt_state (void)
3539 alt_state_t result;
3541 if (first_free_alt_state != NULL)
3543 result = first_free_alt_state;
3544 first_free_alt_state = first_free_alt_state->next_alt_state;
3546 else
3548 #ifndef NDEBUG
3549 allocated_alt_states_num++;
3550 #endif
3551 result = create_node (sizeof (struct alt_state));
3553 result->state = NULL;
3554 result->next_alt_state = NULL;
3555 result->next_sorted_alt_state = NULL;
3556 return result;
3559 /* The function frees node ALT_STATE. */
3560 static void
3561 free_alt_state (alt_state_t alt_state)
3563 if (alt_state == NULL)
3564 return;
3565 alt_state->next_alt_state = first_free_alt_state;
3566 first_free_alt_state = alt_state;
3569 /* The function frees list started with node ALT_STATE_LIST. */
3570 static void
3571 free_alt_states (alt_state_t alt_states_list)
3573 alt_state_t curr_alt_state;
3574 alt_state_t next_alt_state;
3576 for (curr_alt_state = alt_states_list;
3577 curr_alt_state != NULL;
3578 curr_alt_state = next_alt_state)
3580 next_alt_state = curr_alt_state->next_alt_state;
3581 free_alt_state (curr_alt_state);
3585 /* The function compares unique numbers of alt states. */
3586 static int
3587 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3589 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3590 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3591 return 0;
3592 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3593 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3594 return -1;
3595 else
3596 return 1;
3599 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3600 states from the list. The comparison key is alt state unique
3601 number. */
3602 static alt_state_t
3603 uniq_sort_alt_states (alt_state_t alt_states_list)
3605 alt_state_t curr_alt_state;
3606 vla_ptr_t alt_states;
3607 size_t i;
3608 size_t prev_unique_state_ind;
3609 alt_state_t result;
3610 alt_state_t *result_ptr;
3612 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3613 for (curr_alt_state = alt_states_list;
3614 curr_alt_state != NULL;
3615 curr_alt_state = curr_alt_state->next_alt_state)
3616 VLA_PTR_ADD (alt_states, curr_alt_state);
3617 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3618 sizeof (alt_state_t), alt_state_cmp);
3619 if (VLA_PTR_LENGTH (alt_states) == 0)
3620 result = NULL;
3621 else
3623 result_ptr = VLA_PTR_BEGIN (alt_states);
3624 prev_unique_state_ind = 0;
3625 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3626 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3628 prev_unique_state_ind++;
3629 result_ptr [prev_unique_state_ind] = result_ptr [i];
3631 #if 0
3632 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3633 free_alt_state (result_ptr [i]);
3634 #endif
3635 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3636 result_ptr = VLA_PTR_BEGIN (alt_states);
3637 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3638 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3639 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3640 result = *result_ptr;
3642 VLA_PTR_DELETE (alt_states);
3643 return result;
3646 /* The function checks equality of alt state lists. Remember that the
3647 lists must be already sorted by the previous function. */
3648 static int
3649 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3651 while (alt_states_1 != NULL && alt_states_2 != NULL
3652 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3654 alt_states_1 = alt_states_1->next_sorted_alt_state;
3655 alt_states_2 = alt_states_2->next_sorted_alt_state;
3657 return alt_states_1 == alt_states_2;
3660 /* Initialization of the abstract data. */
3661 static void
3662 initiate_alt_states (void)
3664 first_free_alt_state = NULL;
3667 /* Finishing work with the abstract data. */
3668 static void
3669 finish_alt_states (void)
3675 /* The page contains macros for work with bits strings. We could use
3676 standard gcc bitmap or sbitmap but it would result in difficulties
3677 of building canadian cross. */
3679 /* Set bit number bitno in the bit string. The macro is not side
3680 effect proof. */
3681 #define SET_BIT(bitstring, bitno) \
3682 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3684 #define CLEAR_BIT(bitstring, bitno) \
3685 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3687 /* Test if bit number bitno in the bitstring is set. The macro is not
3688 side effect proof. */
3689 #define TEST_BIT(bitstring, bitno) \
3690 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3694 /* This page contains abstract data `state'. */
3696 /* Maximal length of reservations in cycles (>= 1). */
3697 static int max_cycles_num;
3699 /* Number of set elements (see type set_el_t) needed for
3700 representation of one cycle reservation. It is depended on units
3701 number. */
3702 static int els_in_cycle_reserv;
3704 /* Number of set elements (see type set_el_t) needed for
3705 representation of maximal length reservation. Deterministic
3706 reservation is stored as set (bit string) of length equal to the
3707 variable value * number of bits in set_el_t. */
3708 static int els_in_reservs;
3710 /* VLA for representation of array of pointers to unit
3711 declarations. */
3712 static vla_ptr_t units_container;
3714 /* The start address of the array. */
3715 static unit_decl_t *units_array;
3717 /* Temporary reservation of maximal length. */
3718 static reserv_sets_t temp_reserv;
3720 /* The state table itself is represented by the following variable. */
3721 static htab_t state_table;
3723 /* VLA for representation of array of pointers to free nodes
3724 `state'. */
3725 static vla_ptr_t free_states;
3727 static int curr_unique_state_num;
3729 #ifndef NDEBUG
3730 /* The following variables is maximal number of allocated nodes
3731 `state'. */
3732 static int allocated_states_num = 0;
3733 #endif
3735 /* Allocate new reservation set. */
3736 static reserv_sets_t
3737 alloc_empty_reserv_sets (void)
3739 reserv_sets_t result;
3741 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3742 result = (reserv_sets_t) obstack_base (&irp);
3743 obstack_finish (&irp);
3744 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3745 return result;
3748 /* Hash value of reservation set. */
3749 static unsigned
3750 reserv_sets_hash_value (reserv_sets_t reservs)
3752 set_el_t hash_value;
3753 unsigned result;
3754 int reservs_num, i;
3755 set_el_t *reserv_ptr;
3757 hash_value = 0;
3758 reservs_num = els_in_reservs;
3759 reserv_ptr = reservs;
3760 i = 0;
3761 while (reservs_num != 0)
3763 reservs_num--;
3764 hash_value += ((*reserv_ptr >> i)
3765 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3766 i++;
3767 if (i == sizeof (set_el_t) * CHAR_BIT)
3768 i = 0;
3769 reserv_ptr++;
3771 if (sizeof (set_el_t) <= sizeof (unsigned))
3772 return hash_value;
3773 result = 0;
3774 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3776 result += (unsigned) hash_value;
3777 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3779 return result;
3782 /* Comparison of given reservation sets. */
3783 static int
3784 reserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3786 int reservs_num;
3787 set_el_t *reserv_ptr_1;
3788 set_el_t *reserv_ptr_2;
3790 if (reservs_1 == NULL || reservs_2 == NULL)
3791 abort ();
3792 reservs_num = els_in_reservs;
3793 reserv_ptr_1 = reservs_1;
3794 reserv_ptr_2 = reservs_2;
3795 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3797 reservs_num--;
3798 reserv_ptr_1++;
3799 reserv_ptr_2++;
3801 if (reservs_num == 0)
3802 return 0;
3803 else if (*reserv_ptr_1 < *reserv_ptr_2)
3804 return -1;
3805 else
3806 return 1;
3809 /* The function checks equality of the reservation sets. */
3810 static int
3811 reserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3813 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3816 /* Set up in the reservation set that unit with UNIT_NUM is used on
3817 CYCLE_NUM. */
3818 static void
3819 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3821 if (cycle_num >= max_cycles_num)
3822 abort ();
3823 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3824 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3827 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3828 used on CYCLE_NUM. */
3829 static int
3830 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3832 if (cycle_num >= max_cycles_num)
3833 abort ();
3834 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3835 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3838 /* The function checks that the reservation set represents no one unit
3839 reservation. */
3840 static int
3841 it_is_empty_reserv_sets (reserv_sets_t operand)
3843 set_el_t *reserv_ptr;
3844 int reservs_num;
3846 if (operand == NULL)
3847 abort ();
3848 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3849 reservs_num != 0;
3850 reserv_ptr++, reservs_num--)
3851 if (*reserv_ptr != 0)
3852 return 0;
3853 return 1;
3856 /* The function checks that the reservation sets are intersected,
3857 i.e. there is a unit reservation on a cycle in both reservation
3858 sets. */
3859 static int
3860 reserv_sets_are_intersected (reserv_sets_t operand_1,
3861 reserv_sets_t operand_2)
3863 set_el_t *el_ptr_1;
3864 set_el_t *el_ptr_2;
3865 set_el_t *cycle_ptr_1;
3866 set_el_t *cycle_ptr_2;
3868 if (operand_1 == NULL || operand_2 == NULL)
3869 abort ();
3870 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3871 el_ptr_1 < operand_1 + els_in_reservs;
3872 el_ptr_1++, el_ptr_2++)
3873 if (*el_ptr_1 & *el_ptr_2)
3874 return 1;
3875 reserv_sets_or (temp_reserv, operand_1, operand_2);
3876 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3877 cycle_ptr_1 < operand_1 + els_in_reservs;
3878 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3880 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3881 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3882 el_ptr_1++, el_ptr_2++)
3883 if (*el_ptr_1 & *el_ptr_2)
3884 return 1;
3885 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3886 return 1;
3887 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3888 - operand_2),
3889 cycle_ptr_2, TRUE))
3890 return 1;
3891 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3892 return 1;
3893 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3894 cycle_ptr_2, TRUE))
3895 return 1;
3897 return 0;
3900 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3901 cpu cycle. The remaining bits of OPERAND (representing the last
3902 cycle unit reservations) are not changed. */
3903 static void
3904 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3906 int i;
3908 if (result == NULL || operand == NULL || result == operand)
3909 abort ();
3910 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3911 result [i - els_in_cycle_reserv] = operand [i];
3914 /* OR of the reservation sets. */
3915 static void
3916 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3917 reserv_sets_t operand_2)
3919 set_el_t *el_ptr_1;
3920 set_el_t *el_ptr_2;
3921 set_el_t *result_set_el_ptr;
3923 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3924 abort ();
3925 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3926 el_ptr_1 < operand_1 + els_in_reservs;
3927 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3928 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3931 /* AND of the reservation sets. */
3932 static void
3933 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3934 reserv_sets_t operand_2)
3936 set_el_t *el_ptr_1;
3937 set_el_t *el_ptr_2;
3938 set_el_t *result_set_el_ptr;
3940 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3941 abort ();
3942 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3943 el_ptr_1 < operand_1 + els_in_reservs;
3944 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3945 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3948 /* The function outputs string representation of units reservation on
3949 cycle START_CYCLE in the reservation set. The function uses repeat
3950 construction if REPETITION_NUM > 1. */
3951 static void
3952 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3953 int repetition_num)
3955 int unit_num;
3956 int reserved_units_num;
3958 reserved_units_num = 0;
3959 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3960 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3961 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3962 reserved_units_num++;
3963 if (repetition_num <= 0)
3964 abort ();
3965 if (repetition_num != 1 && reserved_units_num > 1)
3966 fprintf (f, "(");
3967 reserved_units_num = 0;
3968 for (unit_num = 0;
3969 unit_num < description->units_num;
3970 unit_num++)
3971 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3972 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3974 if (reserved_units_num != 0)
3975 fprintf (f, "+");
3976 reserved_units_num++;
3977 fprintf (f, "%s", units_array [unit_num]->name);
3979 if (reserved_units_num == 0)
3980 fprintf (f, NOTHING_NAME);
3981 if (repetition_num <= 0)
3982 abort ();
3983 if (repetition_num != 1 && reserved_units_num > 1)
3984 fprintf (f, ")");
3985 if (repetition_num != 1)
3986 fprintf (f, "*%d", repetition_num);
3989 /* The function outputs string representation of units reservation in
3990 the reservation set. */
3991 static void
3992 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3994 int start_cycle = 0;
3995 int cycle;
3996 int repetition_num;
3998 repetition_num = 0;
3999 for (cycle = 0; cycle < max_cycles_num; cycle++)
4000 if (repetition_num == 0)
4002 repetition_num++;
4003 start_cycle = cycle;
4005 else if (memcmp
4006 ((char *) reservs + start_cycle * els_in_cycle_reserv
4007 * sizeof (set_el_t),
4008 (char *) reservs + cycle * els_in_cycle_reserv
4009 * sizeof (set_el_t),
4010 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
4011 repetition_num++;
4012 else
4014 if (start_cycle != 0)
4015 fprintf (f, ", ");
4016 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
4017 repetition_num = 1;
4018 start_cycle = cycle;
4020 if (start_cycle < max_cycles_num)
4022 if (start_cycle != 0)
4023 fprintf (f, ", ");
4024 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
4028 /* The following function returns free node state for AUTOMATON. It
4029 may be new allocated node or node freed earlier. The function also
4030 allocates reservation set if WITH_RESERVS has nonzero value. */
4031 static state_t
4032 get_free_state (int with_reservs, automaton_t automaton)
4034 state_t result;
4036 if (max_cycles_num <= 0 || automaton == NULL)
4037 abort ();
4038 if (VLA_PTR_LENGTH (free_states) != 0)
4040 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
4041 VLA_PTR_SHORTEN (free_states, 1);
4042 result->automaton = automaton;
4043 result->first_out_arc = NULL;
4044 result->it_was_placed_in_stack_for_NDFA_forming = 0;
4045 result->it_was_placed_in_stack_for_DFA_forming = 0;
4046 result->component_states = NULL;
4047 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
4049 else
4051 #ifndef NDEBUG
4052 allocated_states_num++;
4053 #endif
4054 result = create_node (sizeof (struct state));
4055 result->automaton = automaton;
4056 result->first_out_arc = NULL;
4057 result->unique_num = curr_unique_state_num;
4058 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
4059 curr_unique_state_num++;
4061 if (with_reservs)
4063 if (result->reservs == NULL)
4064 result->reservs = alloc_empty_reserv_sets ();
4065 else
4066 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
4068 return result;
4071 /* The function frees node STATE. */
4072 static void
4073 free_state (state_t state)
4075 free_alt_states (state->component_states);
4076 VLA_PTR_ADD (free_states, state);
4079 /* Hash value of STATE. If STATE represents deterministic state it is
4080 simply hash value of the corresponding reservation set. Otherwise
4081 it is formed from hash values of the component deterministic
4082 states. One more key is order number of state automaton. */
4083 static hashval_t
4084 state_hash (const void *state)
4086 unsigned int hash_value;
4087 alt_state_t alt_state;
4089 if (((state_t) state)->component_states == NULL)
4090 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
4091 else
4093 hash_value = 0;
4094 for (alt_state = ((state_t) state)->component_states;
4095 alt_state != NULL;
4096 alt_state = alt_state->next_sorted_alt_state)
4097 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4098 | (hash_value << CHAR_BIT))
4099 + alt_state->state->unique_num);
4101 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4102 | (hash_value << CHAR_BIT))
4103 + ((state_t) state)->automaton->automaton_order_num);
4104 return hash_value;
4107 /* Return nonzero value if the states are the same. */
4108 static int
4109 state_eq_p (const void *state_1, const void *state_2)
4111 alt_state_t alt_state_1;
4112 alt_state_t alt_state_2;
4114 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
4115 return 0;
4116 else if (((state_t) state_1)->component_states == NULL
4117 && ((state_t) state_2)->component_states == NULL)
4118 return reserv_sets_eq (((state_t) state_1)->reservs,
4119 ((state_t) state_2)->reservs);
4120 else if (((state_t) state_1)->component_states != NULL
4121 && ((state_t) state_2)->component_states != NULL)
4123 for (alt_state_1 = ((state_t) state_1)->component_states,
4124 alt_state_2 = ((state_t) state_2)->component_states;
4125 alt_state_1 != NULL && alt_state_2 != NULL;
4126 alt_state_1 = alt_state_1->next_sorted_alt_state,
4127 alt_state_2 = alt_state_2->next_sorted_alt_state)
4128 /* All state in the list must be already in the hash table.
4129 Also the lists must be sorted. */
4130 if (alt_state_1->state != alt_state_2->state)
4131 return 0;
4132 return alt_state_1 == alt_state_2;
4134 else
4135 return 0;
4138 /* Insert STATE into the state table. */
4139 static state_t
4140 insert_state (state_t state)
4142 void **entry_ptr;
4144 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
4145 if (*entry_ptr == NULL)
4146 *entry_ptr = (void *) state;
4147 return (state_t) *entry_ptr;
4150 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4151 deterministic STATE. */
4152 static void
4153 set_state_reserv (state_t state, int cycle_num, int unit_num)
4155 set_unit_reserv (state->reservs, cycle_num, unit_num);
4158 /* Return nonzero value if the deterministic states contains a
4159 reservation of the same cpu unit on the same cpu cycle. */
4160 static int
4161 intersected_state_reservs_p (state_t state1, state_t state2)
4163 if (state1->automaton != state2->automaton)
4164 abort ();
4165 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
4168 /* Return deterministic state (inserted into the table) which
4169 representing the automaton state which is union of reservations of
4170 the deterministic states masked by RESERVS. */
4171 static state_t
4172 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
4174 state_t result;
4175 state_t state_in_table;
4177 if (state1->automaton != state2->automaton)
4178 abort ();
4179 result = get_free_state (1, state1->automaton);
4180 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
4181 reserv_sets_and (result->reservs, result->reservs, reservs);
4182 state_in_table = insert_state (result);
4183 if (result != state_in_table)
4185 free_state (result);
4186 result = state_in_table;
4188 return result;
4191 /* Return deterministic state (inserted into the table) which
4192 represent the automaton state is obtained from deterministic STATE
4193 by advancing cpu cycle and masking by RESERVS. */
4194 static state_t
4195 state_shift (state_t state, reserv_sets_t reservs)
4197 state_t result;
4198 state_t state_in_table;
4200 result = get_free_state (1, state->automaton);
4201 reserv_sets_shift (result->reservs, state->reservs);
4202 reserv_sets_and (result->reservs, result->reservs, reservs);
4203 state_in_table = insert_state (result);
4204 if (result != state_in_table)
4206 free_state (result);
4207 result = state_in_table;
4209 return result;
4212 /* Initialization of the abstract data. */
4213 static void
4214 initiate_states (void)
4216 decl_t decl;
4217 int i;
4219 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
4220 units_array
4221 = (description->decls_num && description->units_num
4222 ? VLA_PTR_BEGIN (units_container) : NULL);
4223 for (i = 0; i < description->decls_num; i++)
4225 decl = description->decls [i];
4226 if (decl->mode == dm_unit)
4227 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
4229 max_cycles_num = description->max_insn_reserv_cycles;
4230 els_in_cycle_reserv
4231 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
4232 / (sizeof (set_el_t) * CHAR_BIT));
4233 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
4234 curr_unique_state_num = 0;
4235 initiate_alt_states ();
4236 VLA_PTR_CREATE (free_states, 1500, "free states");
4237 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
4238 temp_reserv = alloc_empty_reserv_sets ();
4241 /* Finishing work with the abstract data. */
4242 static void
4243 finish_states (void)
4245 VLA_PTR_DELETE (units_container);
4246 htab_delete (state_table);
4247 VLA_PTR_DELETE (free_states);
4248 finish_alt_states ();
4253 /* Abstract data `arcs'. */
4255 /* List of free arcs. */
4256 static arc_t first_free_arc;
4258 #ifndef NDEBUG
4259 /* The following variables is maximal number of allocated nodes
4260 `arc'. */
4261 static int allocated_arcs_num = 0;
4262 #endif
4264 /* The function frees node ARC. */
4265 static void
4266 free_arc (arc_t arc)
4268 arc->next_out_arc = first_free_arc;
4269 first_free_arc = arc;
4272 /* The function removes and frees ARC staring from FROM_STATE. */
4273 static void
4274 remove_arc (state_t from_state, arc_t arc)
4276 arc_t prev_arc;
4277 arc_t curr_arc;
4279 if (arc == NULL)
4280 abort ();
4281 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
4282 curr_arc != NULL;
4283 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4284 if (curr_arc == arc)
4285 break;
4286 if (curr_arc == NULL)
4287 abort ();
4288 if (prev_arc == NULL)
4289 from_state->first_out_arc = arc->next_out_arc;
4290 else
4291 prev_arc->next_out_arc = arc->next_out_arc;
4292 free_arc (arc);
4295 /* The functions returns arc with given characteristics (or NULL if
4296 the arc does not exist). */
4297 static arc_t
4298 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
4300 arc_t arc;
4302 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4303 if (arc->to_state == to_state && arc->insn == insn)
4304 return arc;
4305 return NULL;
4308 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4309 and with given STATE_ALTS. The function returns added arc (or
4310 already existing arc). */
4311 static arc_t
4312 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn,
4313 int state_alts)
4315 arc_t new_arc;
4317 new_arc = find_arc (from_state, to_state, ainsn);
4318 if (new_arc != NULL)
4319 return new_arc;
4320 if (first_free_arc == NULL)
4322 #ifndef NDEBUG
4323 allocated_arcs_num++;
4324 #endif
4325 new_arc = create_node (sizeof (struct arc));
4326 new_arc->to_state = NULL;
4327 new_arc->insn = NULL;
4328 new_arc->next_out_arc = NULL;
4330 else
4332 new_arc = first_free_arc;
4333 first_free_arc = first_free_arc->next_out_arc;
4335 new_arc->to_state = to_state;
4336 new_arc->insn = ainsn;
4337 ainsn->arc_exists_p = 1;
4338 new_arc->next_out_arc = from_state->first_out_arc;
4339 from_state->first_out_arc = new_arc;
4340 new_arc->next_arc_marked_by_insn = NULL;
4341 new_arc->state_alts = state_alts;
4342 return new_arc;
4345 /* The function returns the first arc starting from STATE. */
4346 static arc_t
4347 first_out_arc (state_t state)
4349 return state->first_out_arc;
4352 /* The function returns next out arc after ARC. */
4353 static arc_t
4354 next_out_arc (arc_t arc)
4356 return arc->next_out_arc;
4359 /* Initialization of the abstract data. */
4360 static void
4361 initiate_arcs (void)
4363 first_free_arc = NULL;
4366 /* Finishing work with the abstract data. */
4367 static void
4368 finish_arcs (void)
4374 /* Abstract data `automata lists'. */
4376 /* List of free states. */
4377 static automata_list_el_t first_free_automata_list_el;
4379 /* The list being formed. */
4380 static automata_list_el_t current_automata_list;
4382 /* Hash table of automata lists. */
4383 static htab_t automata_list_table;
4385 /* The following function returns free automata list el. It may be
4386 new allocated node or node freed earlier. */
4387 static automata_list_el_t
4388 get_free_automata_list_el (void)
4390 automata_list_el_t result;
4392 if (first_free_automata_list_el != NULL)
4394 result = first_free_automata_list_el;
4395 first_free_automata_list_el
4396 = first_free_automata_list_el->next_automata_list_el;
4398 else
4399 result = create_node (sizeof (struct automata_list_el));
4400 result->automaton = NULL;
4401 result->next_automata_list_el = NULL;
4402 return result;
4405 /* The function frees node AUTOMATA_LIST_EL. */
4406 static void
4407 free_automata_list_el (automata_list_el_t automata_list_el)
4409 if (automata_list_el == NULL)
4410 return;
4411 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4412 first_free_automata_list_el = automata_list_el;
4415 /* The function frees list AUTOMATA_LIST. */
4416 static void
4417 free_automata_list (automata_list_el_t automata_list)
4419 automata_list_el_t curr_automata_list_el;
4420 automata_list_el_t next_automata_list_el;
4422 for (curr_automata_list_el = automata_list;
4423 curr_automata_list_el != NULL;
4424 curr_automata_list_el = next_automata_list_el)
4426 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4427 free_automata_list_el (curr_automata_list_el);
4431 /* Hash value of AUTOMATA_LIST. */
4432 static hashval_t
4433 automata_list_hash (const void *automata_list)
4435 unsigned int hash_value;
4436 automata_list_el_t curr_automata_list_el;
4438 hash_value = 0;
4439 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4440 curr_automata_list_el != NULL;
4441 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4442 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4443 | (hash_value << CHAR_BIT))
4444 + curr_automata_list_el->automaton->automaton_order_num);
4445 return hash_value;
4448 /* Return nonzero value if the automata_lists are the same. */
4449 static int
4450 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4452 automata_list_el_t automata_list_el_1;
4453 automata_list_el_t automata_list_el_2;
4455 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4456 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4457 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4458 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4459 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4460 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4461 return 0;
4462 return automata_list_el_1 == automata_list_el_2;
4465 /* Initialization of the abstract data. */
4466 static void
4467 initiate_automata_lists (void)
4469 first_free_automata_list_el = NULL;
4470 automata_list_table = htab_create (1500, automata_list_hash,
4471 automata_list_eq_p, (htab_del) 0);
4474 /* The following function starts new automata list and makes it the
4475 current one. */
4476 static void
4477 automata_list_start (void)
4479 current_automata_list = NULL;
4482 /* The following function adds AUTOMATON to the current list. */
4483 static void
4484 automata_list_add (automaton_t automaton)
4486 automata_list_el_t el;
4488 el = get_free_automata_list_el ();
4489 el->automaton = automaton;
4490 el->next_automata_list_el = current_automata_list;
4491 current_automata_list = el;
4494 /* The following function finishes forming the current list, inserts
4495 it into the table and returns it. */
4496 static automata_list_el_t
4497 automata_list_finish (void)
4499 void **entry_ptr;
4501 if (current_automata_list == NULL)
4502 return NULL;
4503 entry_ptr = htab_find_slot (automata_list_table,
4504 (void *) current_automata_list, 1);
4505 if (*entry_ptr == NULL)
4506 *entry_ptr = (void *) current_automata_list;
4507 else
4508 free_automata_list (current_automata_list);
4509 current_automata_list = NULL;
4510 return (automata_list_el_t) *entry_ptr;
4513 /* Finishing work with the abstract data. */
4514 static void
4515 finish_automata_lists (void)
4517 htab_delete (automata_list_table);
4522 /* The page contains abstract data for work with exclusion sets (see
4523 exclusion_set in file rtl.def). */
4525 /* The following variable refers to an exclusion set returned by
4526 get_excl_set. This is bit string of length equal to cpu units
4527 number. If exclusion set for given unit contains 1 for a unit,
4528 then simultaneous reservation of the units is prohibited. */
4529 static reserv_sets_t excl_set;
4531 /* The array contains exclusion sets for each unit. */
4532 static reserv_sets_t *unit_excl_set_table;
4534 /* The following function forms the array containing exclusion sets
4535 for each unit. */
4536 static void
4537 initiate_excl_sets (void)
4539 decl_t decl;
4540 reserv_sets_t unit_excl_set;
4541 unit_set_el_t el;
4542 int i;
4544 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4545 excl_set = (reserv_sets_t) obstack_base (&irp);
4546 obstack_finish (&irp);
4547 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4548 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4549 obstack_finish (&irp);
4550 /* Evaluate unit exclusion sets. */
4551 for (i = 0; i < description->decls_num; i++)
4553 decl = description->decls [i];
4554 if (decl->mode == dm_unit)
4556 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4557 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4558 obstack_finish (&irp);
4559 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4560 for (el = DECL_UNIT (decl)->excl_list;
4561 el != NULL;
4562 el = el->next_unit_set_el)
4564 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4565 el->unit_decl->in_set_p = TRUE;
4567 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4572 /* The function sets up and return EXCL_SET which is union of
4573 exclusion sets for each unit in IN_SET. */
4574 static reserv_sets_t
4575 get_excl_set (reserv_sets_t in_set)
4577 int excl_char_num;
4578 int chars_num;
4579 int i;
4580 int start_unit_num;
4581 int unit_num;
4583 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4584 memset (excl_set, 0, chars_num);
4585 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4586 if (((unsigned char *) in_set) [excl_char_num])
4587 for (i = CHAR_BIT - 1; i >= 0; i--)
4588 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4590 start_unit_num = excl_char_num * CHAR_BIT + i;
4591 if (start_unit_num >= description->units_num)
4592 return excl_set;
4593 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4595 excl_set [unit_num]
4596 |= unit_excl_set_table [start_unit_num] [unit_num];
4599 return excl_set;
4604 /* The page contains abstract data for work with presence/absence
4605 pattern sets (see presence_set/absence_set in file rtl.def). */
4607 /* The following arrays contain correspondingly presence, final
4608 presence, absence, and final absence patterns for each unit. */
4609 static pattern_reserv_t *unit_presence_set_table;
4610 static pattern_reserv_t *unit_final_presence_set_table;
4611 static pattern_reserv_t *unit_absence_set_table;
4612 static pattern_reserv_t *unit_final_absence_set_table;
4614 /* The following function forms list of reservation sets for given
4615 PATTERN_LIST. */
4616 static pattern_reserv_t
4617 form_reserv_sets_list (pattern_set_el_t pattern_list)
4619 pattern_set_el_t el;
4620 pattern_reserv_t first, curr, prev;
4621 int i;
4623 prev = first = NULL;
4624 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4626 curr = create_node (sizeof (struct pattern_reserv));
4627 curr->reserv = alloc_empty_reserv_sets ();
4628 curr->next_pattern_reserv = NULL;
4629 for (i = 0; i < el->units_num; i++)
4631 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4632 el->unit_decls [i]->in_set_p = TRUE;
4634 if (prev != NULL)
4635 prev->next_pattern_reserv = curr;
4636 else
4637 first = curr;
4638 prev = curr;
4640 return first;
4643 /* The following function forms the array containing presence and
4644 absence pattern sets for each unit. */
4645 static void
4646 initiate_presence_absence_pattern_sets (void)
4648 decl_t decl;
4649 int i;
4651 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4652 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4653 obstack_finish (&irp);
4654 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4655 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4656 obstack_finish (&irp);
4657 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4658 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4659 obstack_finish (&irp);
4660 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4661 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4662 obstack_finish (&irp);
4663 /* Evaluate unit presence/absence sets. */
4664 for (i = 0; i < description->decls_num; i++)
4666 decl = description->decls [i];
4667 if (decl->mode == dm_unit)
4669 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4670 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4671 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4672 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4673 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4674 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4675 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4676 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4681 /* The function checks that CHECKED_SET satisfies all presence pattern
4682 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4683 is ok. */
4684 static int
4685 check_presence_pattern_sets (reserv_sets_t checked_set,
4686 reserv_sets_t origional_set,
4687 int final_p)
4689 int char_num;
4690 int chars_num;
4691 int i;
4692 int start_unit_num;
4693 int unit_num;
4694 int presence_p;
4695 pattern_reserv_t pat_reserv;
4697 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4698 for (char_num = 0; char_num < chars_num; char_num++)
4699 if (((unsigned char *) origional_set) [char_num])
4700 for (i = CHAR_BIT - 1; i >= 0; i--)
4701 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4703 start_unit_num = char_num * CHAR_BIT + i;
4704 if (start_unit_num >= description->units_num)
4705 break;
4706 if ((final_p
4707 && unit_final_presence_set_table [start_unit_num] == NULL)
4708 || (!final_p
4709 && unit_presence_set_table [start_unit_num] == NULL))
4710 continue;
4711 presence_p = FALSE;
4712 for (pat_reserv = (final_p
4713 ? unit_final_presence_set_table [start_unit_num]
4714 : unit_presence_set_table [start_unit_num]);
4715 pat_reserv != NULL;
4716 pat_reserv = pat_reserv->next_pattern_reserv)
4718 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4719 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4720 != pat_reserv->reserv [unit_num])
4721 break;
4722 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4724 if (!presence_p)
4725 return FALSE;
4727 return TRUE;
4730 /* The function checks that CHECKED_SET satisfies all absence pattern
4731 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4732 is ok. */
4733 static int
4734 check_absence_pattern_sets (reserv_sets_t checked_set,
4735 reserv_sets_t origional_set,
4736 int final_p)
4738 int char_num;
4739 int chars_num;
4740 int i;
4741 int start_unit_num;
4742 int unit_num;
4743 pattern_reserv_t pat_reserv;
4745 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4746 for (char_num = 0; char_num < chars_num; char_num++)
4747 if (((unsigned char *) origional_set) [char_num])
4748 for (i = CHAR_BIT - 1; i >= 0; i--)
4749 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4751 start_unit_num = char_num * CHAR_BIT + i;
4752 if (start_unit_num >= description->units_num)
4753 break;
4754 for (pat_reserv = (final_p
4755 ? unit_final_absence_set_table [start_unit_num]
4756 : unit_absence_set_table [start_unit_num]);
4757 pat_reserv != NULL;
4758 pat_reserv = pat_reserv->next_pattern_reserv)
4760 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4761 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4762 != pat_reserv->reserv [unit_num]
4763 && pat_reserv->reserv [unit_num])
4764 break;
4765 if (unit_num >= els_in_cycle_reserv)
4766 return FALSE;
4769 return TRUE;
4774 /* This page contains code for transformation of original reservations
4775 described in .md file. The main goal of transformations is
4776 simplifying reservation and lifting up all `|' on the top of IR
4777 reservation representation. */
4780 /* The following function makes copy of IR representation of
4781 reservation. The function also substitutes all reservations
4782 defined by define_reservation by corresponding value during making
4783 the copy. */
4784 static regexp_t
4785 copy_insn_regexp (regexp_t regexp)
4787 regexp_t result;
4788 int i;
4790 if (regexp->mode == rm_reserv)
4791 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4792 else if (regexp->mode == rm_unit)
4793 result = copy_node (regexp, sizeof (struct regexp));
4794 else if (regexp->mode == rm_repeat)
4796 result = copy_node (regexp, sizeof (struct regexp));
4797 REGEXP_REPEAT (result)->regexp
4798 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4800 else if (regexp->mode == rm_sequence)
4802 result = copy_node (regexp,
4803 sizeof (struct regexp) + sizeof (regexp_t)
4804 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4805 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4806 REGEXP_SEQUENCE (result)->regexps [i]
4807 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4809 else if (regexp->mode == rm_allof)
4811 result = copy_node (regexp,
4812 sizeof (struct regexp) + sizeof (regexp_t)
4813 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4814 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4815 REGEXP_ALLOF (result)->regexps [i]
4816 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4818 else if (regexp->mode == rm_oneof)
4820 result = copy_node (regexp,
4821 sizeof (struct regexp) + sizeof (regexp_t)
4822 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4823 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4824 REGEXP_ONEOF (result)->regexps [i]
4825 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4827 else
4829 if (regexp->mode != rm_nothing)
4830 abort ();
4831 result = copy_node (regexp, sizeof (struct regexp));
4833 return result;
4836 /* The following variable is set up 1 if a transformation has been
4837 applied. */
4838 static int regexp_transformed_p;
4840 /* The function makes transformation
4841 A*N -> A, A, ... */
4842 static regexp_t
4843 transform_1 (regexp_t regexp)
4845 int i;
4846 int repeat_num;
4847 regexp_t operand;
4848 pos_t pos;
4850 if (regexp->mode == rm_repeat)
4852 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4853 if (repeat_num <= 1)
4854 abort ();
4855 operand = REGEXP_REPEAT (regexp)->regexp;
4856 pos = regexp->mode;
4857 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4858 * (repeat_num - 1));
4859 regexp->mode = rm_sequence;
4860 regexp->pos = pos;
4861 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4862 for (i = 0; i < repeat_num; i++)
4863 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4864 regexp_transformed_p = 1;
4866 return regexp;
4869 /* The function makes transformations
4870 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4871 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4872 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4873 static regexp_t
4874 transform_2 (regexp_t regexp)
4876 if (regexp->mode == rm_sequence)
4878 regexp_t sequence = NULL;
4879 regexp_t result;
4880 int sequence_index = 0;
4881 int i, j;
4883 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4884 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4886 sequence_index = i;
4887 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4888 break;
4890 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4892 if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
4893 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4894 abort ();
4895 result = create_node (sizeof (struct regexp)
4896 + sizeof (regexp_t)
4897 * (REGEXP_SEQUENCE (regexp)->regexps_num
4898 + REGEXP_SEQUENCE (sequence)->regexps_num
4899 - 2));
4900 result->mode = rm_sequence;
4901 result->pos = regexp->pos;
4902 REGEXP_SEQUENCE (result)->regexps_num
4903 = (REGEXP_SEQUENCE (regexp)->regexps_num
4904 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4905 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4906 if (i < sequence_index)
4907 REGEXP_SEQUENCE (result)->regexps [i]
4908 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4909 else if (i > sequence_index)
4910 REGEXP_SEQUENCE (result)->regexps
4911 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4912 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4913 else
4914 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4915 REGEXP_SEQUENCE (result)->regexps [i + j]
4916 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4917 regexp_transformed_p = 1;
4918 regexp = result;
4921 else if (regexp->mode == rm_allof)
4923 regexp_t allof = NULL;
4924 regexp_t result;
4925 int allof_index = 0;
4926 int i, j;
4928 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4929 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4931 allof_index = i;
4932 allof = REGEXP_ALLOF (regexp)->regexps [i];
4933 break;
4935 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4937 if (REGEXP_ALLOF (allof)->regexps_num <= 1
4938 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4939 abort ();
4940 result = create_node (sizeof (struct regexp)
4941 + sizeof (regexp_t)
4942 * (REGEXP_ALLOF (regexp)->regexps_num
4943 + REGEXP_ALLOF (allof)->regexps_num - 2));
4944 result->mode = rm_allof;
4945 result->pos = regexp->pos;
4946 REGEXP_ALLOF (result)->regexps_num
4947 = (REGEXP_ALLOF (regexp)->regexps_num
4948 + REGEXP_ALLOF (allof)->regexps_num - 1);
4949 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4950 if (i < allof_index)
4951 REGEXP_ALLOF (result)->regexps [i]
4952 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4953 else if (i > allof_index)
4954 REGEXP_ALLOF (result)->regexps
4955 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4956 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4957 else
4958 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4959 REGEXP_ALLOF (result)->regexps [i + j]
4960 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4961 regexp_transformed_p = 1;
4962 regexp = result;
4965 else if (regexp->mode == rm_oneof)
4967 regexp_t oneof = NULL;
4968 regexp_t result;
4969 int oneof_index = 0;
4970 int i, j;
4972 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4973 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4975 oneof_index = i;
4976 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4977 break;
4979 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4981 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4982 || REGEXP_ONEOF (regexp)->regexps_num <= 1)
4983 abort ();
4984 result = create_node (sizeof (struct regexp)
4985 + sizeof (regexp_t)
4986 * (REGEXP_ONEOF (regexp)->regexps_num
4987 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4988 result->mode = rm_oneof;
4989 result->pos = regexp->pos;
4990 REGEXP_ONEOF (result)->regexps_num
4991 = (REGEXP_ONEOF (regexp)->regexps_num
4992 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4993 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4994 if (i < oneof_index)
4995 REGEXP_ONEOF (result)->regexps [i]
4996 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4997 else if (i > oneof_index)
4998 REGEXP_ONEOF (result)->regexps
4999 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
5000 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
5001 else
5002 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
5003 REGEXP_ONEOF (result)->regexps [i + j]
5004 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
5005 regexp_transformed_p = 1;
5006 regexp = result;
5009 return regexp;
5012 /* The function makes transformations
5013 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
5014 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
5015 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
5016 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
5017 static regexp_t
5018 transform_3 (regexp_t regexp)
5020 if (regexp->mode == rm_sequence)
5022 regexp_t oneof = NULL;
5023 int oneof_index = 0;
5024 regexp_t result;
5025 regexp_t sequence;
5026 int i, j;
5028 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5029 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
5031 oneof_index = i;
5032 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
5033 break;
5035 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
5037 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5038 || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
5039 abort ();
5040 result = create_node (sizeof (struct regexp)
5041 + sizeof (regexp_t)
5042 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5043 result->mode = rm_oneof;
5044 result->pos = regexp->pos;
5045 REGEXP_ONEOF (result)->regexps_num
5046 = REGEXP_ONEOF (oneof)->regexps_num;
5047 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5049 sequence
5050 = create_node (sizeof (struct regexp)
5051 + sizeof (regexp_t)
5052 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
5053 sequence->mode = rm_sequence;
5054 sequence->pos = regexp->pos;
5055 REGEXP_SEQUENCE (sequence)->regexps_num
5056 = REGEXP_SEQUENCE (regexp)->regexps_num;
5057 REGEXP_ONEOF (result)->regexps [i] = sequence;
5058 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
5059 if (j != oneof_index)
5060 REGEXP_SEQUENCE (sequence)->regexps [j]
5061 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
5062 else
5063 REGEXP_SEQUENCE (sequence)->regexps [j]
5064 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5066 regexp_transformed_p = 1;
5067 regexp = result;
5070 else if (regexp->mode == rm_allof)
5072 regexp_t oneof = NULL;
5073 regexp_t seq;
5074 int oneof_index = 0;
5075 int max_seq_length, allof_length;
5076 regexp_t result;
5077 regexp_t allof = NULL;
5078 regexp_t allof_op = NULL;
5079 int i, j;
5081 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5082 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
5084 oneof_index = i;
5085 oneof = REGEXP_ALLOF (regexp)->regexps [i];
5086 break;
5088 if (i < REGEXP_ALLOF (regexp)->regexps_num)
5090 if (REGEXP_ONEOF (oneof)->regexps_num <= 1
5091 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5092 abort ();
5093 result = create_node (sizeof (struct regexp)
5094 + sizeof (regexp_t)
5095 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
5096 result->mode = rm_oneof;
5097 result->pos = regexp->pos;
5098 REGEXP_ONEOF (result)->regexps_num
5099 = REGEXP_ONEOF (oneof)->regexps_num;
5100 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
5102 allof
5103 = create_node (sizeof (struct regexp)
5104 + sizeof (regexp_t)
5105 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
5106 allof->mode = rm_allof;
5107 allof->pos = regexp->pos;
5108 REGEXP_ALLOF (allof)->regexps_num
5109 = REGEXP_ALLOF (regexp)->regexps_num;
5110 REGEXP_ONEOF (result)->regexps [i] = allof;
5111 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
5112 if (j != oneof_index)
5113 REGEXP_ALLOF (allof)->regexps [j]
5114 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
5115 else
5116 REGEXP_ALLOF (allof)->regexps [j]
5117 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
5119 regexp_transformed_p = 1;
5120 regexp = result;
5122 max_seq_length = 0;
5123 if (regexp->mode == rm_allof)
5124 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5126 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
5128 seq = REGEXP_ALLOF (regexp)->regexps [i];
5129 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
5130 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
5132 else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit
5133 && REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_nothing)
5135 max_seq_length = 0;
5136 break;
5139 if (max_seq_length != 0)
5141 if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5142 abort ();
5143 result = create_node (sizeof (struct regexp)
5144 + sizeof (regexp_t) * (max_seq_length - 1));
5145 result->mode = rm_sequence;
5146 result->pos = regexp->pos;
5147 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5148 for (i = 0; i < max_seq_length; i++)
5150 allof_length = 0;
5151 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5152 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5153 && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5154 ->regexps [j])->regexps_num)))
5156 allof_op
5157 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5158 ->regexps [i]);
5159 allof_length++;
5161 else if (i == 0
5162 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5163 == rm_unit
5164 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5165 == rm_nothing)))
5167 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5168 allof_length++;
5170 if (allof_length == 1)
5171 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5172 else
5174 allof = create_node (sizeof (struct regexp)
5175 + sizeof (regexp_t)
5176 * (allof_length - 1));
5177 allof->mode = rm_allof;
5178 allof->pos = regexp->pos;
5179 REGEXP_ALLOF (allof)->regexps_num = allof_length;
5180 REGEXP_SEQUENCE (result)->regexps [i] = allof;
5181 allof_length = 0;
5182 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5183 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5184 && (i <
5185 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5186 ->regexps [j])->regexps_num)))
5188 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5189 ->regexps [j])
5190 ->regexps [i]);
5191 REGEXP_ALLOF (allof)->regexps [allof_length]
5192 = allof_op;
5193 allof_length++;
5195 else if (i == 0
5196 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5197 == rm_unit
5198 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
5199 == rm_nothing)))
5201 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5202 REGEXP_ALLOF (allof)->regexps [allof_length]
5203 = allof_op;
5204 allof_length++;
5208 regexp_transformed_p = 1;
5209 regexp = result;
5212 return regexp;
5215 /* The function traverses IR of reservation and applies transformations
5216 implemented by FUNC. */
5217 static regexp_t
5218 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
5220 int i;
5222 if (regexp->mode == rm_sequence)
5223 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5224 REGEXP_SEQUENCE (regexp)->regexps [i]
5225 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5226 else if (regexp->mode == rm_allof)
5227 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5228 REGEXP_ALLOF (regexp)->regexps [i]
5229 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5230 else if (regexp->mode == rm_oneof)
5231 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5232 REGEXP_ONEOF (regexp)->regexps [i]
5233 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5234 else if (regexp->mode == rm_repeat)
5235 REGEXP_REPEAT (regexp)->regexp
5236 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5237 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5238 abort ();
5239 return (*func) (regexp);
5242 /* The function applies all transformations for IR representation of
5243 reservation REGEXP. */
5244 static regexp_t
5245 transform_regexp (regexp_t regexp)
5247 regexp = regexp_transform_func (regexp, transform_1);
5250 regexp_transformed_p = 0;
5251 regexp = regexp_transform_func (regexp, transform_2);
5252 regexp = regexp_transform_func (regexp, transform_3);
5254 while (regexp_transformed_p);
5255 return regexp;
5258 /* The function applies all transformations for reservations of all
5259 insn declarations. */
5260 static void
5261 transform_insn_regexps (void)
5263 decl_t decl;
5264 int i;
5266 transform_time = create_ticker ();
5267 add_advance_cycle_insn_decl ();
5268 fprintf (stderr, "Reservation transformation...");
5269 fflush (stderr);
5270 for (i = 0; i < description->decls_num; i++)
5272 decl = description->decls [i];
5273 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5274 DECL_INSN_RESERV (decl)->transformed_regexp
5275 = transform_regexp (copy_insn_regexp
5276 (DECL_INSN_RESERV (decl)->regexp));
5278 fprintf (stderr, "done\n");
5279 ticker_off (&transform_time);
5280 fflush (stderr);
5285 /* The following variable value is TRUE if the first annotated message
5286 about units to automata distribution has been output. */
5287 static int annotation_message_reported_p;
5289 /* The following structure describes usage of a unit in a reservation. */
5290 struct unit_usage
5292 unit_decl_t unit_decl;
5293 /* The following forms a list of units used on the same cycle in the
5294 same alternative. */
5295 struct unit_usage *next;
5298 /* Obstack for unit_usage structures. */
5299 static struct obstack unit_usages;
5301 /* VLA for representation of array of pointers to unit usage
5302 structures. There is an element for each combination of
5303 (alternative number, cycle). Unit usages on given cycle in
5304 alternative with given number are referred through element with
5305 index equals to the cycle * number of all alternatives in the regexp
5306 + the alternative number. */
5307 static vla_ptr_t cycle_alt_unit_usages;
5309 /* The following function creates the structure unit_usage for UNIT on
5310 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5311 accessed through cycle_alt_unit_usages. */
5312 static void
5313 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
5314 int alt_num)
5316 size_t i, length, old_length;
5317 unit_decl_t unit_decl;
5318 struct unit_usage *unit_usage_ptr;
5319 int index;
5321 if (regexp == NULL || regexp->mode != rm_oneof
5322 || alt_num >= REGEXP_ONEOF (regexp)->regexps_num)
5323 abort ();
5324 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5325 old_length = VLA_PTR_LENGTH (cycle_alt_unit_usages);
5326 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
5327 if (old_length < length)
5329 VLA_PTR_EXPAND (cycle_alt_unit_usages, length - old_length);
5330 for (i = old_length; i < length; i++)
5331 VLA_PTR (cycle_alt_unit_usages, i) = NULL;
5333 obstack_blank (&unit_usages, sizeof (struct unit_usage));
5334 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5335 obstack_finish (&unit_usages);
5336 unit_usage_ptr->unit_decl = unit_decl;
5337 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5338 unit_usage_ptr->next = VLA_PTR (cycle_alt_unit_usages, index);
5339 VLA_PTR (cycle_alt_unit_usages, index) = unit_usage_ptr;
5340 unit_decl->last_distribution_check_cycle = -1; /* undefined */
5343 /* The function processes given REGEXP to find units with the wrong
5344 distribution. */
5345 static void
5346 check_regexp_units_distribution (const char *insn_reserv_name,
5347 regexp_t regexp)
5349 int i, j, k, cycle;
5350 regexp_t seq, allof, unit;
5351 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
5353 if (regexp == NULL || regexp->mode != rm_oneof)
5354 return;
5355 /* Store all unit usages in the regexp: */
5356 obstack_init (&unit_usages);
5357 VLA_PTR_CREATE (cycle_alt_unit_usages, 100, "unit usages on cycles");
5358 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5360 seq = REGEXP_ONEOF (regexp)->regexps [i];
5361 if (seq->mode == rm_sequence)
5362 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5364 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5365 if (allof->mode == rm_allof)
5366 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5368 unit = REGEXP_ALLOF (allof)->regexps [k];
5369 if (unit->mode == rm_unit)
5370 store_alt_unit_usage (regexp, unit, j, i);
5371 else if (unit->mode != rm_nothing)
5372 abort ();
5374 else if (allof->mode == rm_unit)
5375 store_alt_unit_usage (regexp, allof, j, i);
5376 else if (allof->mode != rm_nothing)
5377 abort ();
5379 else if (seq->mode == rm_allof)
5380 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5382 unit = REGEXP_ALLOF (seq)->regexps [k];
5383 if (unit->mode == rm_unit)
5384 store_alt_unit_usage (regexp, unit, 0, i);
5385 else if (unit->mode != rm_nothing)
5386 abort ();
5388 else if (seq->mode == rm_unit)
5389 store_alt_unit_usage (regexp, seq, 0, i);
5390 else if (seq->mode != rm_nothing)
5391 abort ();
5393 /* Check distribution: */
5394 for (i = 0; i < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages); i++)
5396 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5397 for (unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages, i);
5398 unit_usage_ptr != NULL;
5399 unit_usage_ptr = unit_usage_ptr->next)
5400 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5402 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5403 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5404 k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages)
5405 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5406 k++)
5408 for (other_unit_usage_ptr = VLA_PTR (cycle_alt_unit_usages, k);
5409 other_unit_usage_ptr != NULL;
5410 other_unit_usage_ptr = other_unit_usage_ptr->next)
5411 if (unit_usage_ptr->unit_decl->automaton_decl
5412 == other_unit_usage_ptr->unit_decl->automaton_decl)
5413 break;
5414 if (other_unit_usage_ptr == NULL
5415 && VLA_PTR (cycle_alt_unit_usages, k) != NULL)
5416 break;
5418 if (k < (int) VLA_PTR_LENGTH (cycle_alt_unit_usages)
5419 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5421 if (!annotation_message_reported_p)
5423 fprintf (stderr, "\n");
5424 error ("The following units do not satisfy units-automata distribution rule");
5425 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5426 annotation_message_reported_p = TRUE;
5428 error ("Unit %s, reserv. %s, cycle %d",
5429 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5430 cycle);
5434 VLA_PTR_DELETE (cycle_alt_unit_usages);
5435 obstack_free (&unit_usages, NULL);
5438 /* The function finds units which violates units to automata
5439 distribution rule. If the units exist, report about them. */
5440 static void
5441 check_unit_distributions_to_automata (void)
5443 decl_t decl;
5444 int i;
5446 fprintf (stderr, "Check unit distributions to automata...");
5447 annotation_message_reported_p = FALSE;
5448 for (i = 0; i < description->decls_num; i++)
5450 decl = description->decls [i];
5451 if (decl->mode == dm_insn_reserv)
5452 check_regexp_units_distribution
5453 (DECL_INSN_RESERV (decl)->name,
5454 DECL_INSN_RESERV (decl)->transformed_regexp);
5456 fprintf (stderr, "done\n");
5461 /* The page contains code for building alt_states (see comments for
5462 IR) describing all possible insns reservations of an automaton. */
5464 /* Current state being formed for which the current alt_state
5465 refers. */
5466 static state_t state_being_formed;
5468 /* Current alt_state being formed. */
5469 static alt_state_t alt_state_being_formed;
5471 /* This recursive function processes `,' and units in reservation
5472 REGEXP for forming alt_states of AUTOMATON. It is believed that
5473 CURR_CYCLE is start cycle of all reservation REGEXP. */
5474 static int
5475 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5476 int curr_cycle)
5478 int i;
5480 if (regexp == NULL)
5481 return curr_cycle;
5482 else if (regexp->mode == rm_unit)
5484 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5485 == automaton->automaton_order_num)
5486 set_state_reserv (state_being_formed, curr_cycle,
5487 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5488 return curr_cycle;
5490 else if (regexp->mode == rm_sequence)
5492 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5493 curr_cycle
5494 = process_seq_for_forming_states
5495 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5496 return curr_cycle;
5498 else if (regexp->mode == rm_allof)
5500 int finish_cycle = 0;
5501 int cycle;
5503 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5505 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5506 ->regexps [i],
5507 automaton, curr_cycle);
5508 if (finish_cycle < cycle)
5509 finish_cycle = cycle;
5511 return finish_cycle;
5513 else
5515 if (regexp->mode != rm_nothing)
5516 abort ();
5517 return curr_cycle;
5521 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5522 inserts alt_state into the table. */
5523 static void
5524 finish_forming_alt_state (alt_state_t alt_state,
5525 automaton_t automaton ATTRIBUTE_UNUSED)
5527 state_t state_in_table;
5528 state_t corresponding_state;
5530 corresponding_state = alt_state->state;
5531 state_in_table = insert_state (corresponding_state);
5532 if (state_in_table != corresponding_state)
5534 free_state (corresponding_state);
5535 alt_state->state = state_in_table;
5539 /* The following variable value is current automaton insn for whose
5540 reservation the alt states are created. */
5541 static ainsn_t curr_ainsn;
5543 /* This recursive function processes `|' in reservation REGEXP for
5544 forming alt_states of AUTOMATON. List of the alt states should
5545 have the same order as in the description. */
5546 static void
5547 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5548 int inside_oneof_p)
5550 int i;
5552 if (regexp->mode != rm_oneof)
5554 alt_state_being_formed = get_free_alt_state ();
5555 state_being_formed = get_free_state (1, automaton);
5556 alt_state_being_formed->state = state_being_formed;
5557 /* We inserts in reverse order but we process alternatives also
5558 in reverse order. So we have the same order of alternative
5559 as in the description. */
5560 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5561 curr_ainsn->alt_states = alt_state_being_formed;
5562 (void) process_seq_for_forming_states (regexp, automaton, 0);
5563 finish_forming_alt_state (alt_state_being_formed, automaton);
5565 else
5567 if (inside_oneof_p)
5568 abort ();
5569 /* We processes it in reverse order to get list with the same
5570 order as in the description. See also the previous
5571 commentary. */
5572 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5573 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5574 automaton, 1);
5578 /* Create nodes alt_state for all AUTOMATON insns. */
5579 static void
5580 create_alt_states (automaton_t automaton)
5582 struct insn_reserv_decl *reserv_decl;
5584 for (curr_ainsn = automaton->ainsn_list;
5585 curr_ainsn != NULL;
5586 curr_ainsn = curr_ainsn->next_ainsn)
5588 reserv_decl = curr_ainsn->insn_reserv_decl;
5589 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5591 curr_ainsn->alt_states = NULL;
5592 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5593 automaton, 0);
5594 curr_ainsn->sorted_alt_states
5595 = uniq_sort_alt_states (curr_ainsn->alt_states);
5602 /* The page contains major code for building DFA(s) for fast pipeline
5603 hazards recognition. */
5605 /* The function forms list of ainsns of AUTOMATON with the same
5606 reservation. */
5607 static void
5608 form_ainsn_with_same_reservs (automaton_t automaton)
5610 ainsn_t curr_ainsn;
5611 size_t i;
5612 vla_ptr_t first_insns;
5613 vla_ptr_t last_insns;
5615 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5616 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5617 for (curr_ainsn = automaton->ainsn_list;
5618 curr_ainsn != NULL;
5619 curr_ainsn = curr_ainsn->next_ainsn)
5620 if (curr_ainsn->insn_reserv_decl
5621 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5623 curr_ainsn->next_same_reservs_insn = NULL;
5624 curr_ainsn->first_insn_with_same_reservs = 1;
5626 else
5628 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5629 if (alt_states_eq
5630 (curr_ainsn->sorted_alt_states,
5631 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5632 break;
5633 curr_ainsn->next_same_reservs_insn = NULL;
5634 if (i < VLA_PTR_LENGTH (first_insns))
5636 curr_ainsn->first_insn_with_same_reservs = 0;
5637 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5638 = curr_ainsn;
5639 VLA_PTR (last_insns, i) = curr_ainsn;
5641 else
5643 VLA_PTR_ADD (first_insns, curr_ainsn);
5644 VLA_PTR_ADD (last_insns, curr_ainsn);
5645 curr_ainsn->first_insn_with_same_reservs = 1;
5648 VLA_PTR_DELETE (first_insns);
5649 VLA_PTR_DELETE (last_insns);
5652 /* Forming unit reservations which can affect creating the automaton
5653 states achieved from a given state. It permits to build smaller
5654 automata in many cases. We would have the same automata after
5655 the minimization without such optimization, but the automaton
5656 right after the building could be huge. So in other words, usage
5657 of reservs_matter means some minimization during building the
5658 automaton. */
5659 static reserv_sets_t
5660 form_reservs_matter (automaton_t automaton)
5662 int cycle, unit;
5663 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5665 for (cycle = 0; cycle < max_cycles_num; cycle++)
5666 for (unit = 0; unit < description->units_num; unit++)
5667 if (units_array [unit]->automaton_decl
5668 == automaton->corresponding_automaton_decl
5669 && (cycle >= units_array [unit]->min_occ_cycle_num
5670 /* We can not remove queried unit from reservations. */
5671 || units_array [unit]->query_p
5672 /* We can not remove units which are used
5673 `exclusion_set', `presence_set',
5674 `final_presence_set', `absence_set', and
5675 `final_absence_set'. */
5676 || units_array [unit]->in_set_p))
5677 set_unit_reserv (reservs_matter, cycle, unit);
5678 return reservs_matter;
5681 /* The following function creates all states of nondeterministic (if
5682 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5683 static void
5684 make_automaton (automaton_t automaton)
5686 ainsn_t ainsn;
5687 struct insn_reserv_decl *insn_reserv_decl;
5688 alt_state_t alt_state;
5689 state_t state;
5690 state_t start_state;
5691 state_t state2;
5692 ainsn_t advance_cycle_ainsn;
5693 arc_t added_arc;
5694 vla_ptr_t state_stack;
5695 int states_n;
5696 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5698 VLA_PTR_CREATE (state_stack, 150, "state stack");
5699 /* Create the start state (empty state). */
5700 start_state = insert_state (get_free_state (1, automaton));
5701 automaton->start_state = start_state;
5702 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5703 VLA_PTR_ADD (state_stack, start_state);
5704 states_n = 1;
5705 while (VLA_PTR_LENGTH (state_stack) != 0)
5707 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5708 VLA_PTR_SHORTEN (state_stack, 1);
5709 advance_cycle_ainsn = NULL;
5710 for (ainsn = automaton->ainsn_list;
5711 ainsn != NULL;
5712 ainsn = ainsn->next_ainsn)
5713 if (ainsn->first_insn_with_same_reservs)
5715 insn_reserv_decl = ainsn->insn_reserv_decl;
5716 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5718 /* We process alt_states in the same order as they are
5719 present in the description. */
5720 added_arc = NULL;
5721 for (alt_state = ainsn->alt_states;
5722 alt_state != NULL;
5723 alt_state = alt_state->next_alt_state)
5725 state2 = alt_state->state;
5726 if (!intersected_state_reservs_p (state, state2))
5728 state2 = states_union (state, state2, reservs_matter);
5729 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5731 state2->it_was_placed_in_stack_for_NDFA_forming
5732 = 1;
5733 VLA_PTR_ADD (state_stack, state2);
5734 states_n++;
5735 if (states_n % 100 == 0)
5736 fprintf (stderr, "*");
5738 added_arc = add_arc (state, state2, ainsn, 1);
5739 if (!ndfa_flag)
5740 break;
5743 if (!ndfa_flag && added_arc != NULL)
5745 added_arc->state_alts = 0;
5746 for (alt_state = ainsn->alt_states;
5747 alt_state != NULL;
5748 alt_state = alt_state->next_alt_state)
5750 state2 = alt_state->state;
5751 if (!intersected_state_reservs_p (state, state2))
5752 added_arc->state_alts++;
5756 else
5757 advance_cycle_ainsn = ainsn;
5759 /* Add transition to advance cycle. */
5760 state2 = state_shift (state, reservs_matter);
5761 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5763 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5764 VLA_PTR_ADD (state_stack, state2);
5765 states_n++;
5766 if (states_n % 100 == 0)
5767 fprintf (stderr, "*");
5769 if (advance_cycle_ainsn == NULL)
5770 abort ();
5771 add_arc (state, state2, advance_cycle_ainsn, 1);
5773 VLA_PTR_DELETE (state_stack);
5776 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5777 static void
5778 form_arcs_marked_by_insn (state_t state)
5780 decl_t decl;
5781 arc_t arc;
5782 int i;
5784 for (i = 0; i < description->decls_num; i++)
5786 decl = description->decls [i];
5787 if (decl->mode == dm_insn_reserv)
5788 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5790 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5792 if (arc->insn == NULL)
5793 abort ();
5794 arc->next_arc_marked_by_insn
5795 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5796 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5800 /* The function creates composed state (see comments for IR) from
5801 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5802 same insn. If the composed state is not in STATE_STACK yet, it is
5803 pushed into STATE_STACK. */
5804 static int
5805 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5806 vla_ptr_t *state_stack)
5808 state_t state;
5809 alt_state_t alt_state, curr_alt_state;
5810 alt_state_t new_alt_state;
5811 arc_t curr_arc;
5812 arc_t next_arc;
5813 state_t state_in_table;
5814 state_t temp_state;
5815 alt_state_t canonical_alt_states_list;
5816 int alts_number;
5817 int new_state_p = 0;
5819 if (arcs_marked_by_insn == NULL)
5820 return new_state_p;
5821 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5822 state = arcs_marked_by_insn->to_state;
5823 else
5825 if (!ndfa_flag)
5826 abort ();
5827 /* Create composed state. */
5828 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5829 curr_alt_state = NULL;
5830 for (curr_arc = arcs_marked_by_insn;
5831 curr_arc != NULL;
5832 curr_arc = curr_arc->next_arc_marked_by_insn)
5833 if (curr_arc->to_state->component_states == NULL)
5835 new_alt_state = get_free_alt_state ();
5836 new_alt_state->next_alt_state = curr_alt_state;
5837 new_alt_state->state = curr_arc->to_state;
5838 curr_alt_state = new_alt_state;
5840 else
5841 for (alt_state = curr_arc->to_state->component_states;
5842 alt_state != NULL;
5843 alt_state = alt_state->next_sorted_alt_state)
5845 new_alt_state = get_free_alt_state ();
5846 new_alt_state->next_alt_state = curr_alt_state;
5847 new_alt_state->state = alt_state->state;
5848 if (alt_state->state->component_states != NULL)
5849 abort ();
5850 curr_alt_state = new_alt_state;
5852 /* There are not identical sets in the alt state list. */
5853 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5854 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5856 temp_state = state;
5857 state = canonical_alt_states_list->state;
5858 free_state (temp_state);
5860 else
5862 state->component_states = canonical_alt_states_list;
5863 state_in_table = insert_state (state);
5864 if (state_in_table != state)
5866 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5867 abort ();
5868 free_state (state);
5869 state = state_in_table;
5871 else
5873 if (state->it_was_placed_in_stack_for_DFA_forming)
5874 abort ();
5875 new_state_p = 1;
5876 for (curr_alt_state = state->component_states;
5877 curr_alt_state != NULL;
5878 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5879 for (curr_arc = first_out_arc (curr_alt_state->state);
5880 curr_arc != NULL;
5881 curr_arc = next_out_arc (curr_arc))
5882 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5884 arcs_marked_by_insn->to_state = state;
5885 for (alts_number = 0,
5886 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5887 curr_arc != NULL;
5888 curr_arc = next_arc)
5890 next_arc = curr_arc->next_arc_marked_by_insn;
5891 remove_arc (original_state, curr_arc);
5892 alts_number++;
5894 arcs_marked_by_insn->state_alts = alts_number;
5897 if (!state->it_was_placed_in_stack_for_DFA_forming)
5899 state->it_was_placed_in_stack_for_DFA_forming = 1;
5900 VLA_PTR_ADD (*state_stack, state);
5902 return new_state_p;
5905 /* The function transforms nondeterministic AUTOMATON into
5906 deterministic. */
5907 static void
5908 NDFA_to_DFA (automaton_t automaton)
5910 state_t start_state;
5911 state_t state;
5912 decl_t decl;
5913 vla_ptr_t state_stack;
5914 int i;
5915 int states_n;
5917 VLA_PTR_CREATE (state_stack, 150, "state stack");
5918 /* Create the start state (empty state). */
5919 start_state = automaton->start_state;
5920 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5921 VLA_PTR_ADD (state_stack, start_state);
5922 states_n = 1;
5923 while (VLA_PTR_LENGTH (state_stack) != 0)
5925 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5926 VLA_PTR_SHORTEN (state_stack, 1);
5927 form_arcs_marked_by_insn (state);
5928 for (i = 0; i < description->decls_num; i++)
5930 decl = description->decls [i];
5931 if (decl->mode == dm_insn_reserv
5932 && create_composed_state
5933 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5934 &state_stack))
5936 states_n++;
5937 if (states_n % 100 == 0)
5938 fprintf (stderr, "*");
5942 VLA_PTR_DELETE (state_stack);
5945 /* The following variable value is current number (1, 2, ...) of passing
5946 graph of states. */
5947 static int curr_state_graph_pass_num;
5949 /* This recursive function passes all states achieved from START_STATE
5950 and applies APPLIED_FUNC to them. */
5951 static void
5952 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5954 arc_t arc;
5956 if (start_state->pass_num == curr_state_graph_pass_num)
5957 return;
5958 start_state->pass_num = curr_state_graph_pass_num;
5959 (*applied_func) (start_state);
5960 for (arc = first_out_arc (start_state);
5961 arc != NULL;
5962 arc = next_out_arc (arc))
5963 pass_state_graph (arc->to_state, applied_func);
5966 /* This recursive function passes all states of AUTOMATON and applies
5967 APPLIED_FUNC to them. */
5968 static void
5969 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5971 curr_state_graph_pass_num++;
5972 pass_state_graph (automaton->start_state, applied_func);
5975 /* The function initializes code for passing of all states. */
5976 static void
5977 initiate_pass_states (void)
5979 curr_state_graph_pass_num = 0;
5982 /* The following vla is used for storing pointers to all achieved
5983 states. */
5984 static vla_ptr_t all_achieved_states;
5986 /* This function is called by function pass_states to add an achieved
5987 STATE. */
5988 static void
5989 add_achieved_state (state_t state)
5991 VLA_PTR_ADD (all_achieved_states, state);
5994 /* The function sets up equivalence numbers of insns which mark all
5995 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5996 nonzero value) or by equiv_class_num_2 of the destination state.
5997 The function returns number of out arcs of STATE. */
5998 static int
5999 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
6001 int state_out_arcs_num;
6002 arc_t arc;
6004 state_out_arcs_num = 0;
6005 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6007 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
6008 || arc->insn->insn_reserv_decl->state_alts != 0)
6009 abort ();
6010 state_out_arcs_num++;
6011 arc->insn->insn_reserv_decl->equiv_class_num
6012 = (odd_iteration_flag
6013 ? arc->to_state->equiv_class_num_1
6014 : arc->to_state->equiv_class_num_2);
6015 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
6016 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
6017 || arc->insn->insn_reserv_decl->state_alts <= 0)
6018 abort ();
6020 return state_out_arcs_num;
6023 /* The function clears equivalence numbers and alt_states in all insns
6024 which mark all out arcs of STATE. */
6025 static void
6026 clear_arc_insns_equiv_num (state_t state)
6028 arc_t arc;
6030 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6032 arc->insn->insn_reserv_decl->equiv_class_num = 0;
6033 arc->insn->insn_reserv_decl->state_alts = 0;
6037 /* The function copies pointers to equivalent states from vla FROM
6038 into vla TO. */
6039 static void
6040 copy_equiv_class (vla_ptr_t *to, const vla_ptr_t *from)
6042 state_t *class_ptr;
6044 VLA_PTR_NULLIFY (*to);
6045 for (class_ptr = VLA_PTR_BEGIN (*from);
6046 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
6047 class_ptr++)
6048 VLA_PTR_ADD (*to, *class_ptr);
6051 /* The following function returns TRUE if STATE reserves the unit with
6052 UNIT_NUM on the first cycle. */
6053 static int
6054 first_cycle_unit_presence (state_t state, int unit_num)
6056 int presence_p;
6058 if (state->component_states == NULL)
6059 presence_p = test_unit_reserv (state->reservs, 0, unit_num);
6060 else
6061 presence_p
6062 = test_unit_reserv (state->component_states->state->reservs,
6063 0, unit_num);
6064 return presence_p;
6067 /* The function returns nonzero value if STATE is not equivalent to
6068 ANOTHER_STATE from the same current partition on equivalence
6069 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
6070 output arcs. Iteration of making equivalence partition is defined
6071 by ODD_ITERATION_FLAG. */
6072 static int
6073 state_is_differed (state_t state, state_t another_state,
6074 int another_state_out_arcs_num, int odd_iteration_flag)
6076 arc_t arc;
6077 int state_out_arcs_num;
6078 int i, presence1_p, presence2_p;
6080 state_out_arcs_num = 0;
6081 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6083 state_out_arcs_num++;
6084 if ((odd_iteration_flag
6085 ? arc->to_state->equiv_class_num_1
6086 : arc->to_state->equiv_class_num_2)
6087 != arc->insn->insn_reserv_decl->equiv_class_num
6088 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
6089 return 1;
6091 if (state_out_arcs_num != another_state_out_arcs_num)
6092 return 1;
6093 /* Now we are looking at the states with the point of view of query
6094 units. */
6095 for (i = 0; i < description->units_num; i++)
6096 if (units_array [i]->query_p)
6098 presence1_p = first_cycle_unit_presence (state, i);
6099 presence2_p = first_cycle_unit_presence (another_state, i);
6100 if ((presence1_p && !presence2_p) || (!presence1_p && presence2_p))
6101 return 1;
6103 return 0;
6106 /* The function makes initial partition of STATES on equivalent
6107 classes. */
6108 static state_t
6109 init_equiv_class (state_t *states, int states_num)
6111 state_t *state_ptr;
6112 state_t result_equiv_class;
6114 result_equiv_class = NULL;
6115 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
6117 (*state_ptr)->equiv_class_num_1 = 1;
6118 (*state_ptr)->next_equiv_class_state = result_equiv_class;
6119 result_equiv_class = *state_ptr;
6121 return result_equiv_class;
6124 /* The function processes equivalence class given by its pointer
6125 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
6126 are not equivalent states, the function partitions the class
6127 removing nonequivalent states and placing them in
6128 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6129 assigns it to the state equivalence number. If the class has been
6130 partitioned, the function returns nonzero value. */
6131 static int
6132 partition_equiv_class (state_t *equiv_class_ptr, int odd_iteration_flag,
6133 vla_ptr_t *next_iteration_classes,
6134 int *new_equiv_class_num_ptr)
6136 state_t new_equiv_class;
6137 int partition_p;
6138 state_t first_state;
6139 state_t curr_state;
6140 state_t prev_state;
6141 state_t next_state;
6142 int out_arcs_num;
6144 partition_p = 0;
6145 if (*equiv_class_ptr == NULL)
6146 abort ();
6147 for (first_state = *equiv_class_ptr;
6148 first_state != NULL;
6149 first_state = new_equiv_class)
6151 new_equiv_class = NULL;
6152 if (first_state->next_equiv_class_state != NULL)
6154 /* There are more one states in the class equivalence. */
6155 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
6156 odd_iteration_flag);
6157 for (prev_state = first_state,
6158 curr_state = first_state->next_equiv_class_state;
6159 curr_state != NULL;
6160 curr_state = next_state)
6162 next_state = curr_state->next_equiv_class_state;
6163 if (state_is_differed (curr_state, first_state, out_arcs_num,
6164 odd_iteration_flag))
6166 /* Remove curr state from the class equivalence. */
6167 prev_state->next_equiv_class_state = next_state;
6168 /* Add curr state to the new class equivalence. */
6169 curr_state->next_equiv_class_state = new_equiv_class;
6170 if (new_equiv_class == NULL)
6171 (*new_equiv_class_num_ptr)++;
6172 if (odd_iteration_flag)
6173 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6174 else
6175 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6176 new_equiv_class = curr_state;
6177 partition_p = 1;
6179 else
6180 prev_state = curr_state;
6182 clear_arc_insns_equiv_num (first_state);
6184 if (new_equiv_class != NULL)
6185 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
6187 return partition_p;
6190 /* The function finds equivalent states of AUTOMATON. */
6191 static void
6192 evaluate_equiv_classes (automaton_t automaton, vla_ptr_t *equiv_classes)
6194 state_t new_equiv_class;
6195 int new_equiv_class_num;
6196 int odd_iteration_flag;
6197 int finish_flag;
6198 vla_ptr_t next_iteration_classes;
6199 state_t *equiv_class_ptr;
6200 state_t *state_ptr;
6202 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6203 pass_states (automaton, add_achieved_state);
6204 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6205 VLA_PTR_LENGTH (all_achieved_states));
6206 odd_iteration_flag = 0;
6207 new_equiv_class_num = 1;
6208 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6209 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6212 odd_iteration_flag = !odd_iteration_flag;
6213 finish_flag = 1;
6214 copy_equiv_class (equiv_classes, &next_iteration_classes);
6215 /* Transfer equiv numbers for the next iteration. */
6216 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6217 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6218 state_ptr++)
6219 if (odd_iteration_flag)
6220 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6221 else
6222 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6223 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6224 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6225 equiv_class_ptr++)
6226 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6227 &next_iteration_classes,
6228 &new_equiv_class_num))
6229 finish_flag = 0;
6231 while (!finish_flag);
6232 VLA_PTR_DELETE (next_iteration_classes);
6233 VLA_PTR_DELETE (all_achieved_states);
6236 /* The function merges equivalent states of AUTOMATON. */
6237 static void
6238 merge_states (automaton_t automaton, vla_ptr_t *equiv_classes)
6240 state_t *equiv_class_ptr;
6241 state_t curr_state;
6242 state_t new_state;
6243 state_t first_class_state;
6244 alt_state_t alt_states;
6245 alt_state_t alt_state, new_alt_state;
6246 arc_t curr_arc;
6247 arc_t next_arc;
6249 /* Create states corresponding to equivalence classes containing two
6250 or more states. */
6251 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6252 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6253 equiv_class_ptr++)
6254 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6256 /* There are more one states in the class equivalence. */
6257 /* Create new compound state. */
6258 new_state = get_free_state (0, automaton);
6259 alt_states = NULL;
6260 first_class_state = *equiv_class_ptr;
6261 for (curr_state = first_class_state;
6262 curr_state != NULL;
6263 curr_state = curr_state->next_equiv_class_state)
6265 curr_state->equiv_class_state = new_state;
6266 if (curr_state->component_states == NULL)
6268 new_alt_state = get_free_alt_state ();
6269 new_alt_state->state = curr_state;
6270 new_alt_state->next_alt_state = alt_states;
6271 alt_states = new_alt_state;
6273 else
6274 for (alt_state = curr_state->component_states;
6275 alt_state != NULL;
6276 alt_state = alt_state->next_sorted_alt_state)
6278 new_alt_state = get_free_alt_state ();
6279 new_alt_state->state = alt_state->state;
6280 new_alt_state->next_alt_state = alt_states;
6281 alt_states = new_alt_state;
6284 /* Its is important that alt states were sorted before and
6285 after merging to have the same querying results. */
6286 new_state->component_states = uniq_sort_alt_states (alt_states);
6288 else
6289 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6290 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6291 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6292 equiv_class_ptr++)
6293 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6295 first_class_state = *equiv_class_ptr;
6296 /* Create new arcs output from the state corresponding to
6297 equiv class. */
6298 for (curr_arc = first_out_arc (first_class_state);
6299 curr_arc != NULL;
6300 curr_arc = next_out_arc (curr_arc))
6301 add_arc (first_class_state->equiv_class_state,
6302 curr_arc->to_state->equiv_class_state,
6303 curr_arc->insn, curr_arc->state_alts);
6304 /* Delete output arcs from states of given class equivalence. */
6305 for (curr_state = first_class_state;
6306 curr_state != NULL;
6307 curr_state = curr_state->next_equiv_class_state)
6309 if (automaton->start_state == curr_state)
6310 automaton->start_state = curr_state->equiv_class_state;
6311 /* Delete the state and its output arcs. */
6312 for (curr_arc = first_out_arc (curr_state);
6313 curr_arc != NULL;
6314 curr_arc = next_arc)
6316 next_arc = next_out_arc (curr_arc);
6317 free_arc (curr_arc);
6321 else
6323 /* Change `to_state' of arcs output from the state of given
6324 equivalence class. */
6325 for (curr_arc = first_out_arc (*equiv_class_ptr);
6326 curr_arc != NULL;
6327 curr_arc = next_out_arc (curr_arc))
6328 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6332 /* The function sets up new_cycle_p for states if there is arc to the
6333 state marked by advance_cycle_insn_decl. */
6334 static void
6335 set_new_cycle_flags (state_t state)
6337 arc_t arc;
6339 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6340 if (arc->insn->insn_reserv_decl
6341 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6342 arc->to_state->new_cycle_p = 1;
6345 /* The top level function for minimization of deterministic
6346 AUTOMATON. */
6347 static void
6348 minimize_DFA (automaton_t automaton)
6350 vla_ptr_t equiv_classes;
6352 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6353 evaluate_equiv_classes (automaton, &equiv_classes);
6354 merge_states (automaton, &equiv_classes);
6355 pass_states (automaton, set_new_cycle_flags);
6356 VLA_PTR_DELETE (equiv_classes);
6359 /* Values of two variables are counted number of states and arcs in an
6360 automaton. */
6361 static int curr_counted_states_num;
6362 static int curr_counted_arcs_num;
6364 /* The function is called by function `pass_states' to count states
6365 and arcs of an automaton. */
6366 static void
6367 incr_states_and_arcs_nums (state_t state)
6369 arc_t arc;
6371 curr_counted_states_num++;
6372 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6373 curr_counted_arcs_num++;
6376 /* The function counts states and arcs of AUTOMATON. */
6377 static void
6378 count_states_and_arcs (automaton_t automaton, int *states_num,
6379 int *arcs_num)
6381 curr_counted_states_num = 0;
6382 curr_counted_arcs_num = 0;
6383 pass_states (automaton, incr_states_and_arcs_nums);
6384 *states_num = curr_counted_states_num;
6385 *arcs_num = curr_counted_arcs_num;
6388 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6389 recognition after checking and simplifying IR of the
6390 description. */
6391 static void
6392 build_automaton (automaton_t automaton)
6394 int states_num;
6395 int arcs_num;
6397 ticker_on (&NDFA_time);
6398 if (automaton->corresponding_automaton_decl == NULL)
6399 fprintf (stderr, "Create anonymous automaton (1 star is 100 new states):");
6400 else
6401 fprintf (stderr, "Create automaton `%s' (1 star is 100 new states):",
6402 automaton->corresponding_automaton_decl->name);
6403 make_automaton (automaton);
6404 fprintf (stderr, " done\n");
6405 ticker_off (&NDFA_time);
6406 count_states_and_arcs (automaton, &states_num, &arcs_num);
6407 automaton->NDFA_states_num = states_num;
6408 automaton->NDFA_arcs_num = arcs_num;
6409 ticker_on (&NDFA_to_DFA_time);
6410 if (automaton->corresponding_automaton_decl == NULL)
6411 fprintf (stderr, "Make anonymous DFA (1 star is 100 new states):");
6412 else
6413 fprintf (stderr, "Make DFA `%s' (1 star is 100 new states):",
6414 automaton->corresponding_automaton_decl->name);
6415 NDFA_to_DFA (automaton);
6416 fprintf (stderr, " done\n");
6417 ticker_off (&NDFA_to_DFA_time);
6418 count_states_and_arcs (automaton, &states_num, &arcs_num);
6419 automaton->DFA_states_num = states_num;
6420 automaton->DFA_arcs_num = arcs_num;
6421 if (!no_minimization_flag)
6423 ticker_on (&minimize_time);
6424 if (automaton->corresponding_automaton_decl == NULL)
6425 fprintf (stderr, "Minimize anonymous DFA...");
6426 else
6427 fprintf (stderr, "Minimize DFA `%s'...",
6428 automaton->corresponding_automaton_decl->name);
6429 minimize_DFA (automaton);
6430 fprintf (stderr, "done\n");
6431 ticker_off (&minimize_time);
6432 count_states_and_arcs (automaton, &states_num, &arcs_num);
6433 automaton->minimal_DFA_states_num = states_num;
6434 automaton->minimal_DFA_arcs_num = arcs_num;
6440 /* The page contains code for enumeration of all states of an automaton. */
6442 /* Variable used for enumeration of all states of an automaton. Its
6443 value is current number of automaton states. */
6444 static int curr_state_order_num;
6446 /* The function is called by function `pass_states' for enumerating
6447 states. */
6448 static void
6449 set_order_state_num (state_t state)
6451 state->order_state_num = curr_state_order_num;
6452 curr_state_order_num++;
6455 /* The function enumerates all states of AUTOMATON. */
6456 static void
6457 enumerate_states (automaton_t automaton)
6459 curr_state_order_num = 0;
6460 pass_states (automaton, set_order_state_num);
6461 automaton->achieved_states_num = curr_state_order_num;
6466 /* The page contains code for finding equivalent automaton insns
6467 (ainsns). */
6469 /* The function inserts AINSN into cyclic list
6470 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6471 static ainsn_t
6472 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6473 ainsn_t cyclic_equiv_class_insn_list)
6475 if (cyclic_equiv_class_insn_list == NULL)
6476 ainsn->next_equiv_class_insn = ainsn;
6477 else
6479 ainsn->next_equiv_class_insn
6480 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6481 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6483 return ainsn;
6486 /* The function deletes equiv_class_insn into cyclic list of
6487 equivalent ainsns. */
6488 static void
6489 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6491 ainsn_t curr_equiv_class_insn;
6492 ainsn_t prev_equiv_class_insn;
6494 prev_equiv_class_insn = equiv_class_insn;
6495 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6496 curr_equiv_class_insn != equiv_class_insn;
6497 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6498 prev_equiv_class_insn = curr_equiv_class_insn;
6499 if (prev_equiv_class_insn != equiv_class_insn)
6500 prev_equiv_class_insn->next_equiv_class_insn
6501 = equiv_class_insn->next_equiv_class_insn;
6504 /* The function processes AINSN of a state in order to find equivalent
6505 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6506 state. */
6507 static void
6508 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6510 ainsn_t next_insn;
6511 ainsn_t curr_insn;
6512 ainsn_t cyclic_insn_list;
6513 arc_t arc;
6515 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6516 abort ();
6517 curr_insn = ainsn;
6518 /* New class of ainsns which are not equivalent to given ainsn. */
6519 cyclic_insn_list = NULL;
6522 next_insn = curr_insn->next_equiv_class_insn;
6523 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6524 if (arc == NULL
6525 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6526 != arc->to_state))
6528 delete_ainsn_from_equiv_class (curr_insn);
6529 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6530 cyclic_insn_list);
6532 curr_insn = next_insn;
6534 while (curr_insn != ainsn);
6537 /* The function processes STATE in order to find equivalent ainsns. */
6538 static void
6539 process_state_for_insn_equiv_partition (state_t state)
6541 arc_t arc;
6542 arc_t *insn_arcs_array;
6543 int i;
6544 vla_ptr_t insn_arcs_vect;
6546 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6547 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6548 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6549 /* Process insns of the arcs. */
6550 for (i = 0; i < description->insns_num; i++)
6551 insn_arcs_array [i] = NULL;
6552 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6553 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6554 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6555 process_insn_equiv_class (arc->insn, insn_arcs_array);
6556 VLA_PTR_DELETE (insn_arcs_vect);
6559 /* The function searches for equivalent ainsns of AUTOMATON. */
6560 static void
6561 set_insn_equiv_classes (automaton_t automaton)
6563 ainsn_t ainsn;
6564 ainsn_t first_insn;
6565 ainsn_t curr_insn;
6566 ainsn_t cyclic_insn_list;
6567 ainsn_t insn_with_same_reservs;
6568 int equiv_classes_num;
6570 /* All insns are included in one equivalence class. */
6571 cyclic_insn_list = NULL;
6572 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6573 if (ainsn->first_insn_with_same_reservs)
6574 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6575 cyclic_insn_list);
6576 /* Process insns in order to make equivalence partition. */
6577 pass_states (automaton, process_state_for_insn_equiv_partition);
6578 /* Enumerate equiv classes. */
6579 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6580 /* Set undefined value. */
6581 ainsn->insn_equiv_class_num = -1;
6582 equiv_classes_num = 0;
6583 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6584 if (ainsn->insn_equiv_class_num < 0)
6586 first_insn = ainsn;
6587 if (!first_insn->first_insn_with_same_reservs)
6588 abort ();
6589 first_insn->first_ainsn_with_given_equialence_num = 1;
6590 curr_insn = first_insn;
6593 for (insn_with_same_reservs = curr_insn;
6594 insn_with_same_reservs != NULL;
6595 insn_with_same_reservs
6596 = insn_with_same_reservs->next_same_reservs_insn)
6597 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6598 curr_insn = curr_insn->next_equiv_class_insn;
6600 while (curr_insn != first_insn);
6601 equiv_classes_num++;
6603 automaton->insn_equiv_classes_num = equiv_classes_num;
6608 /* This page contains code for creating DFA(s) and calls functions
6609 building them. */
6612 /* The following value is used to prevent floating point overflow for
6613 estimating an automaton bound. The value should be less DBL_MAX on
6614 the host machine. We use here approximate minimum of maximal
6615 double floating point value required by ANSI C standard. It
6616 will work for non ANSI sun compiler too. */
6618 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6620 /* The function estimate size of the single DFA used by PHR (pipeline
6621 hazards recognizer). */
6622 static double
6623 estimate_one_automaton_bound (void)
6625 decl_t decl;
6626 double one_automaton_estimation_bound;
6627 double root_value;
6628 int i;
6630 one_automaton_estimation_bound = 1.0;
6631 for (i = 0; i < description->decls_num; i++)
6633 decl = description->decls [i];
6634 if (decl->mode == dm_unit)
6636 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6637 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6638 / automata_num);
6639 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6640 > one_automaton_estimation_bound)
6641 one_automaton_estimation_bound *= root_value;
6644 return one_automaton_estimation_bound;
6647 /* The function compares unit declarations according to their maximal
6648 cycle in reservations. */
6649 static int
6650 compare_max_occ_cycle_nums (const void *unit_decl_1,
6651 const void *unit_decl_2)
6653 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6654 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6655 return 1;
6656 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6657 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6658 return 0;
6659 else
6660 return -1;
6663 /* The function makes heuristic assigning automata to units. Actually
6664 efficacy of the algorithm has been checked yet??? */
6665 static void
6666 units_to_automata_heuristic_distr (void)
6668 double estimation_bound;
6669 decl_t decl;
6670 decl_t *unit_decl_ptr;
6671 int automaton_num;
6672 int rest_units_num;
6673 double bound_value;
6674 vla_ptr_t unit_decls;
6675 int i;
6677 if (description->units_num == 0)
6678 return;
6679 estimation_bound = estimate_one_automaton_bound ();
6680 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6681 for (i = 0; i < description->decls_num; i++)
6683 decl = description->decls [i];
6684 if (decl->mode == dm_unit)
6685 VLA_PTR_ADD (unit_decls, decl);
6687 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6688 sizeof (decl_t), compare_max_occ_cycle_nums);
6689 automaton_num = 0;
6690 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6691 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6692 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6693 for (unit_decl_ptr++;
6694 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6695 unit_decl_ptr++)
6697 rest_units_num
6698 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6699 if (automata_num - automaton_num - 1 > rest_units_num)
6700 abort ();
6701 if (automaton_num < automata_num - 1
6702 && ((automata_num - automaton_num - 1 == rest_units_num)
6703 || (bound_value
6704 > (estimation_bound
6705 / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6707 bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6708 automaton_num++;
6710 else
6711 bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6712 DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6714 if (automaton_num != automata_num - 1)
6715 abort ();
6716 VLA_PTR_DELETE (unit_decls);
6719 /* The functions creates automaton insns for each automata. Automaton
6720 insn is simply insn for given automaton which makes reservation
6721 only of units of the automaton. */
6722 static ainsn_t
6723 create_ainsns (void)
6725 decl_t decl;
6726 ainsn_t first_ainsn;
6727 ainsn_t curr_ainsn;
6728 ainsn_t prev_ainsn;
6729 int i;
6731 first_ainsn = NULL;
6732 prev_ainsn = NULL;
6733 for (i = 0; i < description->decls_num; i++)
6735 decl = description->decls [i];
6736 if (decl->mode == dm_insn_reserv)
6738 curr_ainsn = create_node (sizeof (struct ainsn));
6739 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6740 curr_ainsn->important_p = FALSE;
6741 curr_ainsn->next_ainsn = NULL;
6742 if (prev_ainsn == NULL)
6743 first_ainsn = curr_ainsn;
6744 else
6745 prev_ainsn->next_ainsn = curr_ainsn;
6746 prev_ainsn = curr_ainsn;
6749 return first_ainsn;
6752 /* The function assigns automata to units according to constructions
6753 `define_automaton' in the description. */
6754 static void
6755 units_to_automata_distr (void)
6757 decl_t decl;
6758 int i;
6760 for (i = 0; i < description->decls_num; i++)
6762 decl = description->decls [i];
6763 if (decl->mode == dm_unit)
6765 if (DECL_UNIT (decl)->automaton_decl == NULL
6766 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6767 == NULL))
6768 /* Distribute to the first automaton. */
6769 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6770 else
6771 DECL_UNIT (decl)->corresponding_automaton_num
6772 = (DECL_UNIT (decl)->automaton_decl
6773 ->corresponding_automaton->automaton_order_num);
6778 /* The function creates DFA(s) for fast pipeline hazards recognition
6779 after checking and simplifying IR of the description. */
6780 static void
6781 create_automata (void)
6783 automaton_t curr_automaton;
6784 automaton_t prev_automaton;
6785 decl_t decl;
6786 int curr_automaton_num;
6787 int i;
6789 if (automata_num != 0)
6791 units_to_automata_heuristic_distr ();
6792 for (prev_automaton = NULL, curr_automaton_num = 0;
6793 curr_automaton_num < automata_num;
6794 curr_automaton_num++, prev_automaton = curr_automaton)
6796 curr_automaton = create_node (sizeof (struct automaton));
6797 curr_automaton->ainsn_list = create_ainsns ();
6798 curr_automaton->corresponding_automaton_decl = NULL;
6799 curr_automaton->next_automaton = NULL;
6800 curr_automaton->automaton_order_num = curr_automaton_num;
6801 if (prev_automaton == NULL)
6802 description->first_automaton = curr_automaton;
6803 else
6804 prev_automaton->next_automaton = curr_automaton;
6807 else
6809 curr_automaton_num = 0;
6810 prev_automaton = NULL;
6811 for (i = 0; i < description->decls_num; i++)
6813 decl = description->decls [i];
6814 if (decl->mode == dm_automaton
6815 && DECL_AUTOMATON (decl)->automaton_is_used)
6817 curr_automaton = create_node (sizeof (struct automaton));
6818 curr_automaton->ainsn_list = create_ainsns ();
6819 curr_automaton->corresponding_automaton_decl
6820 = DECL_AUTOMATON (decl);
6821 curr_automaton->next_automaton = NULL;
6822 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6823 curr_automaton->automaton_order_num = curr_automaton_num;
6824 if (prev_automaton == NULL)
6825 description->first_automaton = curr_automaton;
6826 else
6827 prev_automaton->next_automaton = curr_automaton;
6828 curr_automaton_num++;
6829 prev_automaton = curr_automaton;
6832 if (curr_automaton_num == 0)
6834 curr_automaton = create_node (sizeof (struct automaton));
6835 curr_automaton->ainsn_list = create_ainsns ();
6836 curr_automaton->corresponding_automaton_decl = NULL;
6837 curr_automaton->next_automaton = NULL;
6838 description->first_automaton = curr_automaton;
6840 units_to_automata_distr ();
6842 NDFA_time = create_ticker ();
6843 ticker_off (&NDFA_time);
6844 NDFA_to_DFA_time = create_ticker ();
6845 ticker_off (&NDFA_to_DFA_time);
6846 minimize_time = create_ticker ();
6847 ticker_off (&minimize_time);
6848 equiv_time = create_ticker ();
6849 ticker_off (&equiv_time);
6850 for (curr_automaton = description->first_automaton;
6851 curr_automaton != NULL;
6852 curr_automaton = curr_automaton->next_automaton)
6854 if (curr_automaton->corresponding_automaton_decl == NULL)
6855 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6856 else
6857 fprintf (stderr, "Prepare automaton `%s' creation...",
6858 curr_automaton->corresponding_automaton_decl->name);
6859 create_alt_states (curr_automaton);
6860 form_ainsn_with_same_reservs (curr_automaton);
6861 fprintf (stderr, "done\n");
6862 build_automaton (curr_automaton);
6863 enumerate_states (curr_automaton);
6864 ticker_on (&equiv_time);
6865 set_insn_equiv_classes (curr_automaton);
6866 ticker_off (&equiv_time);
6872 /* This page contains code for forming string representation of
6873 regexp. The representation is formed on IR obstack. So you should
6874 not work with IR obstack between regexp_representation and
6875 finish_regexp_representation calls. */
6877 /* This recursive function forms string representation of regexp
6878 (without tailing '\0'). */
6879 static void
6880 form_regexp (regexp_t regexp)
6882 int i;
6884 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6886 const char *name = (regexp->mode == rm_unit
6887 ? REGEXP_UNIT (regexp)->name
6888 : REGEXP_RESERV (regexp)->name);
6890 obstack_grow (&irp, name, strlen (name));
6892 else if (regexp->mode == rm_sequence)
6893 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6895 if (i != 0)
6896 obstack_1grow (&irp, ',');
6897 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6899 else if (regexp->mode == rm_allof)
6901 obstack_1grow (&irp, '(');
6902 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6904 if (i != 0)
6905 obstack_1grow (&irp, '+');
6906 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6907 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6908 obstack_1grow (&irp, '(');
6909 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6910 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6911 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6912 obstack_1grow (&irp, ')');
6914 obstack_1grow (&irp, ')');
6916 else if (regexp->mode == rm_oneof)
6917 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6919 if (i != 0)
6920 obstack_1grow (&irp, '|');
6921 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6922 obstack_1grow (&irp, '(');
6923 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6924 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6925 obstack_1grow (&irp, ')');
6927 else if (regexp->mode == rm_repeat)
6929 char digits [30];
6931 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6932 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6933 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6934 obstack_1grow (&irp, '(');
6935 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6936 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6937 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6938 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6939 obstack_1grow (&irp, ')');
6940 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6941 obstack_grow (&irp, digits, strlen (digits));
6943 else if (regexp->mode == rm_nothing)
6944 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6945 else
6946 abort ();
6949 /* The function returns string representation of REGEXP on IR
6950 obstack. */
6951 static const char *
6952 regexp_representation (regexp_t regexp)
6954 form_regexp (regexp);
6955 obstack_1grow (&irp, '\0');
6956 return obstack_base (&irp);
6959 /* The function frees memory allocated for last formed string
6960 representation of regexp. */
6961 static void
6962 finish_regexp_representation (void)
6964 int length = obstack_object_size (&irp);
6966 obstack_blank_fast (&irp, -length);
6971 /* This page contains code for output PHR (pipeline hazards recognizer). */
6973 /* The function outputs minimal C type which is sufficient for
6974 representation numbers in range min_range_value and
6975 max_range_value. Because host machine and build machine may be
6976 different, we use here minimal values required by ANSI C standard
6977 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6978 approximation. */
6980 static void
6981 output_range_type (FILE *f, long int min_range_value,
6982 long int max_range_value)
6984 if (min_range_value >= 0 && max_range_value <= 255)
6985 fprintf (f, "unsigned char");
6986 else if (min_range_value >= -127 && max_range_value <= 127)
6987 fprintf (f, "signed char");
6988 else if (min_range_value >= 0 && max_range_value <= 65535)
6989 fprintf (f, "unsigned short");
6990 else if (min_range_value >= -32767 && max_range_value <= 32767)
6991 fprintf (f, "short");
6992 else
6993 fprintf (f, "int");
6996 /* The following macro value is used as value of member
6997 `longest_path_length' of state when we are processing path and the
6998 state on the path. */
7000 #define ON_THE_PATH -2
7002 /* The following recursive function searches for the length of the
7003 longest path starting from STATE which does not contain cycles and
7004 `cycle advance' arcs. */
7006 static int
7007 longest_path_length (state_t state)
7009 arc_t arc;
7010 int length, result;
7012 if (state->longest_path_length == ON_THE_PATH)
7013 /* We don't expect the path cycle here. Our graph may contain
7014 only cycles with one state on the path not containing `cycle
7015 advance' arcs -- see comment below. */
7016 abort ();
7017 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
7018 /* We already visited the state. */
7019 return state->longest_path_length;
7021 result = 0;
7022 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7023 /* Ignore cycles containing one state and `cycle advance' arcs. */
7024 if (arc->to_state != state
7025 && (arc->insn->insn_reserv_decl
7026 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
7028 length = longest_path_length (arc->to_state);
7029 if (length > result)
7030 result = length;
7032 state->longest_path_length = result + 1;
7033 return result;
7036 /* The following variable value is value of the corresponding global
7037 variable in the automaton based pipeline interface. */
7039 static int max_dfa_issue_rate;
7041 /* The following function processes the longest path length staring
7042 from STATE to find MAX_DFA_ISSUE_RATE. */
7044 static void
7045 process_state_longest_path_length (state_t state)
7047 int value;
7049 value = longest_path_length (state);
7050 if (value > max_dfa_issue_rate)
7051 max_dfa_issue_rate = value;
7054 /* The following macro value is name of the corresponding global
7055 variable in the automaton based pipeline interface. */
7057 #define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
7059 /* The following function calculates value of the corresponding
7060 global variable and outputs its declaration. */
7062 static void
7063 output_dfa_max_issue_rate (void)
7065 automaton_t automaton;
7067 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
7068 abort ();
7069 max_dfa_issue_rate = 0;
7070 for (automaton = description->first_automaton;
7071 automaton != NULL;
7072 automaton = automaton->next_automaton)
7073 pass_states (automaton, process_state_longest_path_length);
7074 fprintf (output_file, "\nint %s = %d;\n",
7075 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
7078 /* The function outputs all initialization values of VECT with length
7079 vect_length. */
7080 static void
7081 output_vect (vect_el_t *vect, int vect_length)
7083 int els_on_line;
7085 els_on_line = 1;
7086 if (vect_length == 0)
7087 fprintf (output_file,
7088 "0 /* This is dummy el because the vect is empty */");
7089 else
7093 fprintf (output_file, "%5ld", (long) *vect);
7094 vect_length--;
7095 if (els_on_line == 10)
7097 els_on_line = 0;
7098 fprintf (output_file, ",\n");
7100 else if (vect_length != 0)
7101 fprintf (output_file, ", ");
7102 els_on_line++;
7103 vect++;
7105 while (vect_length != 0);
7109 /* The following is name of the structure which represents DFA(s) for
7110 PHR. */
7111 #define CHIP_NAME "DFA_chip"
7113 /* The following is name of member which represents state of a DFA for
7114 PHR. */
7115 static void
7116 output_chip_member_name (FILE *f, automaton_t automaton)
7118 if (automaton->corresponding_automaton_decl == NULL)
7119 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
7120 else
7121 fprintf (f, "%s_automaton_state",
7122 automaton->corresponding_automaton_decl->name);
7125 /* The following is name of temporary variable which stores state of a
7126 DFA for PHR. */
7127 static void
7128 output_temp_chip_member_name (FILE *f, automaton_t automaton)
7130 fprintf (f, "_");
7131 output_chip_member_name (f, automaton);
7134 /* This is name of macro value which is code of pseudo_insn
7135 representing advancing cpu cycle. Its value is used as internal
7136 code unknown insn. */
7137 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7139 /* Output name of translate vector for given automaton. */
7140 static void
7141 output_translate_vect_name (FILE *f, automaton_t automaton)
7143 if (automaton->corresponding_automaton_decl == NULL)
7144 fprintf (f, "translate_%d", automaton->automaton_order_num);
7145 else
7146 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
7149 /* Output name for simple transition table representation. */
7150 static void
7151 output_trans_full_vect_name (FILE *f, automaton_t automaton)
7153 if (automaton->corresponding_automaton_decl == NULL)
7154 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7155 else
7156 fprintf (f, "%s_transitions",
7157 automaton->corresponding_automaton_decl->name);
7160 /* Output name of comb vector of the transition table for given
7161 automaton. */
7162 static void
7163 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
7165 if (automaton->corresponding_automaton_decl == NULL)
7166 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7167 else
7168 fprintf (f, "%s_transitions",
7169 automaton->corresponding_automaton_decl->name);
7172 /* Output name of check vector of the transition table for given
7173 automaton. */
7174 static void
7175 output_trans_check_vect_name (FILE *f, automaton_t automaton)
7177 if (automaton->corresponding_automaton_decl == NULL)
7178 fprintf (f, "check_%d", automaton->automaton_order_num);
7179 else
7180 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7183 /* Output name of base vector of the transition table for given
7184 automaton. */
7185 static void
7186 output_trans_base_vect_name (FILE *f, automaton_t automaton)
7188 if (automaton->corresponding_automaton_decl == NULL)
7189 fprintf (f, "base_%d", automaton->automaton_order_num);
7190 else
7191 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7194 /* Output name for simple alternatives number representation. */
7195 static void
7196 output_state_alts_full_vect_name (FILE *f, automaton_t automaton)
7198 if (automaton->corresponding_automaton_decl == NULL)
7199 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7200 else
7201 fprintf (f, "%s_state_alts",
7202 automaton->corresponding_automaton_decl->name);
7205 /* Output name of comb vector of the alternatives number table for given
7206 automaton. */
7207 static void
7208 output_state_alts_comb_vect_name (FILE *f, automaton_t automaton)
7210 if (automaton->corresponding_automaton_decl == NULL)
7211 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7212 else
7213 fprintf (f, "%s_state_alts",
7214 automaton->corresponding_automaton_decl->name);
7217 /* Output name of check vector of the alternatives number table for given
7218 automaton. */
7219 static void
7220 output_state_alts_check_vect_name (FILE *f, automaton_t automaton)
7222 if (automaton->corresponding_automaton_decl == NULL)
7223 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7224 else
7225 fprintf (f, "%s_check_state_alts",
7226 automaton->corresponding_automaton_decl->name);
7229 /* Output name of base vector of the alternatives number table for given
7230 automaton. */
7231 static void
7232 output_state_alts_base_vect_name (FILE *f, automaton_t automaton)
7234 if (automaton->corresponding_automaton_decl == NULL)
7235 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7236 else
7237 fprintf (f, "%s_base_state_alts",
7238 automaton->corresponding_automaton_decl->name);
7241 /* Output name of simple min issue delay table representation. */
7242 static void
7243 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
7245 if (automaton->corresponding_automaton_decl == NULL)
7246 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7247 else
7248 fprintf (f, "%s_min_issue_delay",
7249 automaton->corresponding_automaton_decl->name);
7252 /* Output name of deadlock vector for given automaton. */
7253 static void
7254 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
7256 if (automaton->corresponding_automaton_decl == NULL)
7257 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7258 else
7259 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7262 /* Output name of reserved units table for AUTOMATON into file F. */
7263 static void
7264 output_reserved_units_table_name (FILE *f, automaton_t automaton)
7266 if (automaton->corresponding_automaton_decl == NULL)
7267 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7268 else
7269 fprintf (f, "%s_reserved_units",
7270 automaton->corresponding_automaton_decl->name);
7273 /* Name of the PHR interface macro. */
7274 #define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7276 /* Name of the PHR interface macro. */
7277 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7279 /* Names of an internal functions: */
7280 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7282 /* This is external type of DFA(s) state. */
7283 #define STATE_TYPE_NAME "state_t"
7285 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7287 #define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7289 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7291 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7293 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7295 /* Name of cache of insn dfa codes. */
7296 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7298 /* Name of length of cache of insn dfa codes. */
7299 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7301 /* Names of the PHR interface functions: */
7302 #define SIZE_FUNC_NAME "state_size"
7304 #define TRANSITION_FUNC_NAME "state_transition"
7306 #define STATE_ALTS_FUNC_NAME "state_alts"
7308 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7310 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7312 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7314 #define RESET_FUNC_NAME "state_reset"
7316 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7318 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7320 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7322 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7324 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7326 #define DFA_START_FUNC_NAME "dfa_start"
7328 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7330 /* Names of parameters of the PHR interface functions. */
7331 #define STATE_NAME "state"
7333 #define INSN_PARAMETER_NAME "insn"
7335 #define INSN2_PARAMETER_NAME "insn2"
7337 #define CHIP_PARAMETER_NAME "chip"
7339 #define FILE_PARAMETER_NAME "f"
7341 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7343 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7345 /* Names of the variables whose values are internal insn code of rtx
7346 insn. */
7347 #define INTERNAL_INSN_CODE_NAME "insn_code"
7349 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7351 /* Names of temporary variables in some functions. */
7352 #define TEMPORARY_VARIABLE_NAME "temp"
7354 #define I_VARIABLE_NAME "i"
7356 /* Name of result variable in some functions. */
7357 #define RESULT_VARIABLE_NAME "res"
7359 /* Name of function (attribute) to translate insn into internal insn
7360 code. */
7361 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7363 /* Name of function (attribute) to translate insn into internal insn
7364 code with caching. */
7365 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7367 /* Name of function (attribute) to translate insn into internal insn
7368 code. */
7369 #define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7371 /* Name of function (attribute) to translate insn into internal insn
7372 code. */
7373 #define BYPASS_P_FUNC_NAME "bypass_p"
7375 /* Output C type which is used for representation of codes of states
7376 of AUTOMATON. */
7377 static void
7378 output_state_member_type (FILE *f, automaton_t automaton)
7380 output_range_type (f, 0, automaton->achieved_states_num);
7383 /* Output definition of the structure representing current DFA(s)
7384 state(s). */
7385 static void
7386 output_chip_definitions (void)
7388 automaton_t automaton;
7390 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7391 for (automaton = description->first_automaton;
7392 automaton != NULL;
7393 automaton = automaton->next_automaton)
7395 fprintf (output_file, " ");
7396 output_state_member_type (output_file, automaton);
7397 fprintf (output_file, " ");
7398 output_chip_member_name (output_file, automaton);
7399 fprintf (output_file, ";\n");
7401 fprintf (output_file, "};\n\n");
7402 #if 0
7403 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7404 #endif
7408 /* The function outputs translate vector of internal insn code into
7409 insn equivalence class number. The equivalence class number is
7410 used to access to table and vectors representing DFA(s). */
7411 static void
7412 output_translate_vect (automaton_t automaton)
7414 ainsn_t ainsn;
7415 int insn_value;
7416 vla_hwint_t translate_vect;
7418 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7419 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7420 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7421 /* Undefined value */
7422 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7423 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7424 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7425 = ainsn->insn_equiv_class_num;
7426 fprintf (output_file,
7427 "/* Vector translating external insn codes to internal ones.*/\n");
7428 fprintf (output_file, "static const ");
7429 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7430 fprintf (output_file, " ");
7431 output_translate_vect_name (output_file, automaton);
7432 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7433 output_vect (VLA_HWINT_BEGIN (translate_vect),
7434 VLA_HWINT_LENGTH (translate_vect));
7435 fprintf (output_file, "};\n\n");
7436 VLA_HWINT_DELETE (translate_vect);
7439 /* The value in a table state x ainsn -> something which represents
7440 undefined value. */
7441 static int undefined_vect_el_value;
7443 /* The following function returns nonzero value if the best
7444 representation of the table is comb vector. */
7445 static int
7446 comb_vect_p (state_ainsn_table_t tab)
7448 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7449 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7452 /* The following function creates new table for AUTOMATON. */
7453 static state_ainsn_table_t
7454 create_state_ainsn_table (automaton_t automaton)
7456 state_ainsn_table_t tab;
7457 int full_vect_length;
7458 int i;
7460 tab = create_node (sizeof (struct state_ainsn_table));
7461 tab->automaton = automaton;
7462 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7463 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7464 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7465 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7466 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7467 full_vect_length = (automaton->insn_equiv_classes_num
7468 * automaton->achieved_states_num);
7469 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7470 for (i = 0; i < full_vect_length; i++)
7471 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7472 tab->min_base_vect_el_value = 0;
7473 tab->max_base_vect_el_value = 0;
7474 tab->min_comb_vect_el_value = 0;
7475 tab->max_comb_vect_el_value = 0;
7476 return tab;
7479 /* The following function outputs the best C representation of the
7480 table TAB of given TABLE_NAME. */
7481 static void
7482 output_state_ainsn_table (state_ainsn_table_t tab, char *table_name,
7483 void (*output_full_vect_name_func) (FILE *, automaton_t),
7484 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7485 void (*output_check_vect_name_func) (FILE *, automaton_t),
7486 void (*output_base_vect_name_func) (FILE *, automaton_t))
7488 if (!comb_vect_p (tab))
7490 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7491 fprintf (output_file, "static const ");
7492 output_range_type (output_file, tab->min_comb_vect_el_value,
7493 tab->max_comb_vect_el_value);
7494 fprintf (output_file, " ");
7495 (*output_full_vect_name_func) (output_file, tab->automaton);
7496 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7497 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7498 VLA_HWINT_LENGTH (tab->full_vect));
7499 fprintf (output_file, "};\n\n");
7501 else
7503 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7504 fprintf (output_file, "static const ");
7505 output_range_type (output_file, tab->min_comb_vect_el_value,
7506 tab->max_comb_vect_el_value);
7507 fprintf (output_file, " ");
7508 (*output_comb_vect_name_func) (output_file, tab->automaton);
7509 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7510 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7511 VLA_HWINT_LENGTH (tab->comb_vect));
7512 fprintf (output_file, "};\n\n");
7513 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7514 fprintf (output_file, "static const ");
7515 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7516 fprintf (output_file, " ");
7517 (*output_check_vect_name_func) (output_file, tab->automaton);
7518 fprintf (output_file, "[] = {\n");
7519 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7520 VLA_HWINT_LENGTH (tab->check_vect));
7521 fprintf (output_file, "};\n\n");
7522 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7523 fprintf (output_file, "static const ");
7524 output_range_type (output_file, tab->min_base_vect_el_value,
7525 tab->max_base_vect_el_value);
7526 fprintf (output_file, " ");
7527 (*output_base_vect_name_func) (output_file, tab->automaton);
7528 fprintf (output_file, "[] = {\n");
7529 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7530 VLA_HWINT_LENGTH (tab->base_vect));
7531 fprintf (output_file, "};\n\n");
7535 /* The following function adds vector with length VECT_LENGTH and
7536 elements pointed by VECT to table TAB as its line with number
7537 VECT_NUM. */
7538 static void
7539 add_vect (state_ainsn_table_t tab, int vect_num, vect_el_t *vect,
7540 int vect_length)
7542 int real_vect_length;
7543 vect_el_t *comb_vect_start;
7544 vect_el_t *check_vect_start;
7545 int comb_vect_index;
7546 int comb_vect_els_num;
7547 int vect_index;
7548 int first_unempty_vect_index;
7549 int additional_els_num;
7550 int no_state_value;
7551 vect_el_t vect_el;
7552 int i;
7554 if (vect_length == 0)
7555 abort ();
7556 real_vect_length = tab->automaton->insn_equiv_classes_num;
7557 if (vect [vect_length - 1] == undefined_vect_el_value)
7558 abort ();
7559 /* Form full vector in the table: */
7560 for (i = 0; i < vect_length; i++)
7561 VLA_HWINT (tab->full_vect,
7562 i + tab->automaton->insn_equiv_classes_num * vect_num)
7563 = vect [i];
7564 /* Form comb vector in the table: */
7565 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7566 abort ();
7567 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7568 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7569 for (first_unempty_vect_index = 0;
7570 first_unempty_vect_index < vect_length;
7571 first_unempty_vect_index++)
7572 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7573 break;
7574 /* Search for the place in comb vect for the inserted vect. */
7575 for (comb_vect_index = 0;
7576 comb_vect_index < comb_vect_els_num;
7577 comb_vect_index++)
7579 for (vect_index = first_unempty_vect_index;
7580 vect_index < vect_length
7581 && vect_index + comb_vect_index < comb_vect_els_num;
7582 vect_index++)
7583 if (vect [vect_index] != undefined_vect_el_value
7584 && (comb_vect_start [vect_index + comb_vect_index]
7585 != undefined_vect_el_value))
7586 break;
7587 if (vect_index >= vect_length
7588 || vect_index + comb_vect_index >= comb_vect_els_num)
7589 break;
7591 /* Slot was found. */
7592 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7593 if (additional_els_num < 0)
7594 additional_els_num = 0;
7595 /* Expand comb and check vectors. */
7596 vect_el = undefined_vect_el_value;
7597 no_state_value = tab->automaton->achieved_states_num;
7598 while (additional_els_num > 0)
7600 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7601 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7602 additional_els_num--;
7604 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7605 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7606 if (VLA_HWINT_LENGTH (tab->comb_vect)
7607 < (size_t) (comb_vect_index + real_vect_length))
7608 abort ();
7609 /* Fill comb and check vectors. */
7610 for (vect_index = 0; vect_index < vect_length; vect_index++)
7611 if (vect [vect_index] != undefined_vect_el_value)
7613 if (comb_vect_start [comb_vect_index + vect_index]
7614 != undefined_vect_el_value)
7615 abort ();
7616 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7617 if (vect [vect_index] < 0)
7618 abort ();
7619 if (tab->max_comb_vect_el_value < vect [vect_index])
7620 tab->max_comb_vect_el_value = vect [vect_index];
7621 if (tab->min_comb_vect_el_value > vect [vect_index])
7622 tab->min_comb_vect_el_value = vect [vect_index];
7623 check_vect_start [comb_vect_index + vect_index] = vect_num;
7625 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7626 tab->max_comb_vect_el_value = undefined_vect_el_value;
7627 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7628 tab->min_comb_vect_el_value = undefined_vect_el_value;
7629 if (tab->max_base_vect_el_value < comb_vect_index)
7630 tab->max_base_vect_el_value = comb_vect_index;
7631 if (tab->min_base_vect_el_value > comb_vect_index)
7632 tab->min_base_vect_el_value = comb_vect_index;
7633 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7636 /* Return number of out arcs of STATE. */
7637 static int
7638 out_state_arcs_num (state_t state)
7640 int result;
7641 arc_t arc;
7643 result = 0;
7644 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7646 if (arc->insn == NULL)
7647 abort ();
7648 if (arc->insn->first_ainsn_with_given_equialence_num)
7649 result++;
7651 return result;
7654 /* Compare number of possible transitions from the states. */
7655 static int
7656 compare_transition_els_num (const void *state_ptr_1,
7657 const void *state_ptr_2)
7659 int transition_els_num_1;
7660 int transition_els_num_2;
7662 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7663 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7664 if (transition_els_num_1 < transition_els_num_2)
7665 return 1;
7666 else if (transition_els_num_1 == transition_els_num_2)
7667 return 0;
7668 else
7669 return -1;
7672 /* The function adds element EL_VALUE to vector VECT for a table state
7673 x AINSN. */
7674 static void
7675 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7677 int equiv_class_num;
7678 int vect_index;
7680 if (ainsn == NULL)
7681 abort ();
7682 equiv_class_num = ainsn->insn_equiv_class_num;
7683 for (vect_index = VLA_HWINT_LENGTH (*vect);
7684 vect_index <= equiv_class_num;
7685 vect_index++)
7686 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7687 VLA_HWINT (*vect, equiv_class_num) = el_value;
7690 /* This is for forming vector of states of an automaton. */
7691 static vla_ptr_t output_states_vect;
7693 /* The function is called by function pass_states. The function adds
7694 STATE to `output_states_vect'. */
7695 static void
7696 add_states_vect_el (state_t state)
7698 VLA_PTR_ADD (output_states_vect, state);
7701 /* Form and output vectors (comb, check, base or full vector)
7702 representing transition table of AUTOMATON. */
7703 static void
7704 output_trans_table (automaton_t automaton)
7706 state_t *state_ptr;
7707 arc_t arc;
7708 vla_hwint_t transition_vect;
7710 undefined_vect_el_value = automaton->achieved_states_num;
7711 automaton->trans_table = create_state_ainsn_table (automaton);
7712 /* Create vect of pointers to states ordered by num of transitions
7713 from the state (state with the maximum num is the first). */
7714 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7715 pass_states (automaton, add_states_vect_el);
7716 qsort (VLA_PTR_BEGIN (output_states_vect),
7717 VLA_PTR_LENGTH (output_states_vect),
7718 sizeof (state_t), compare_transition_els_num);
7719 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7720 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7721 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7722 state_ptr++)
7724 VLA_HWINT_NULLIFY (transition_vect);
7725 for (arc = first_out_arc (*state_ptr);
7726 arc != NULL;
7727 arc = next_out_arc (arc))
7729 if (arc->insn == NULL)
7730 abort ();
7731 if (arc->insn->first_ainsn_with_given_equialence_num)
7732 add_vect_el (&transition_vect, arc->insn,
7733 arc->to_state->order_state_num);
7735 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7736 VLA_HWINT_BEGIN (transition_vect),
7737 VLA_HWINT_LENGTH (transition_vect));
7739 output_state_ainsn_table
7740 (automaton->trans_table, (char *) "state transitions",
7741 output_trans_full_vect_name, output_trans_comb_vect_name,
7742 output_trans_check_vect_name, output_trans_base_vect_name);
7743 VLA_PTR_DELETE (output_states_vect);
7744 VLA_HWINT_DELETE (transition_vect);
7747 /* Form and output vectors (comb, check, base or simple vect)
7748 representing alts number table of AUTOMATON. The table is state x
7749 ainsn -> number of possible alternative reservations by the
7750 ainsn. */
7751 static void
7752 output_state_alts_table (automaton_t automaton)
7754 state_t *state_ptr;
7755 arc_t arc;
7756 vla_hwint_t state_alts_vect;
7758 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7759 automaton->state_alts_table = create_state_ainsn_table (automaton);
7760 /* Create vect of pointers to states ordered by num of transitions
7761 from the state (state with the maximum num is the first). */
7762 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7763 pass_states (automaton, add_states_vect_el);
7764 qsort (VLA_PTR_BEGIN (output_states_vect),
7765 VLA_PTR_LENGTH (output_states_vect),
7766 sizeof (state_t), compare_transition_els_num);
7767 /* Create base, comb, and check vectors. */
7768 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7769 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7770 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7771 state_ptr++)
7773 VLA_HWINT_NULLIFY (state_alts_vect);
7774 for (arc = first_out_arc (*state_ptr);
7775 arc != NULL;
7776 arc = next_out_arc (arc))
7778 if (arc->insn == NULL)
7779 abort ();
7780 if (arc->insn->first_ainsn_with_given_equialence_num)
7781 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7783 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7784 VLA_HWINT_BEGIN (state_alts_vect),
7785 VLA_HWINT_LENGTH (state_alts_vect));
7787 output_state_ainsn_table
7788 (automaton->state_alts_table, (char *) "state insn alternatives",
7789 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7790 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7791 VLA_PTR_DELETE (output_states_vect);
7792 VLA_HWINT_DELETE (state_alts_vect);
7795 /* The current number of passing states to find minimal issue delay
7796 value for an ainsn and state. */
7797 static int curr_state_pass_num;
7799 /* This recursive function passes states to find minimal issue delay
7800 value for AINSN. The state being visited is STATE. The function
7801 returns minimal issue delay value for AINSN in STATE or -1 if we
7802 enter into a loop. */
7803 static int
7804 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7806 arc_t arc;
7807 int min_insn_issue_delay, insn_issue_delay;
7809 if (state->state_pass_num == curr_state_pass_num
7810 || state->min_insn_issue_delay != -1)
7811 /* We've entered into a loop or already have the correct value for
7812 given state and ainsn. */
7813 return state->min_insn_issue_delay;
7814 state->state_pass_num = curr_state_pass_num;
7815 min_insn_issue_delay = -1;
7816 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7817 if (arc->insn == ainsn)
7819 min_insn_issue_delay = 0;
7820 break;
7822 else
7824 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7825 if (insn_issue_delay != -1)
7827 if (arc->insn->insn_reserv_decl
7828 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7829 insn_issue_delay++;
7830 if (min_insn_issue_delay == -1
7831 || min_insn_issue_delay > insn_issue_delay)
7833 min_insn_issue_delay = insn_issue_delay;
7834 if (insn_issue_delay == 0)
7835 break;
7839 return min_insn_issue_delay;
7842 /* The function searches minimal issue delay value for AINSN in STATE.
7843 The function can return negative value if we can not issue AINSN. We
7844 will report about it later. */
7845 static int
7846 min_issue_delay (state_t state, ainsn_t ainsn)
7848 curr_state_pass_num++;
7849 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7850 return state->min_insn_issue_delay;
7853 /* The function initiates code for finding minimal issue delay values.
7854 It should be called only once. */
7855 static void
7856 initiate_min_issue_delay_pass_states (void)
7858 curr_state_pass_num = 0;
7861 /* Form and output vectors representing minimal issue delay table of
7862 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7863 the ainsn. */
7864 static void
7865 output_min_issue_delay_table (automaton_t automaton)
7867 vla_hwint_t min_issue_delay_vect;
7868 vla_hwint_t compressed_min_issue_delay_vect;
7869 vect_el_t min_delay;
7870 ainsn_t ainsn;
7871 state_t *state_ptr;
7872 int i;
7874 /* Create vect of pointers to states ordered by num of transitions
7875 from the state (state with the maximum num is the first). */
7876 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7877 pass_states (automaton, add_states_vect_el);
7878 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7879 VLA_HWINT_EXPAND (min_issue_delay_vect,
7880 VLA_HWINT_LENGTH (output_states_vect)
7881 * automaton->insn_equiv_classes_num);
7882 for (i = 0;
7883 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7884 * automaton->insn_equiv_classes_num);
7885 i++)
7886 VLA_HWINT (min_issue_delay_vect, i) = 0;
7887 automaton->max_min_delay = 0;
7888 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7889 if (ainsn->first_ainsn_with_given_equialence_num)
7891 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7892 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7893 state_ptr++)
7894 (*state_ptr)->min_insn_issue_delay = -1;
7895 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7896 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7897 state_ptr++)
7899 min_delay = min_issue_delay (*state_ptr, ainsn);
7900 if (automaton->max_min_delay < min_delay)
7901 automaton->max_min_delay = min_delay;
7902 VLA_HWINT (min_issue_delay_vect,
7903 (*state_ptr)->order_state_num
7904 * automaton->insn_equiv_classes_num
7905 + ainsn->insn_equiv_class_num) = min_delay;
7908 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7909 fprintf (output_file, "static const ");
7910 output_range_type (output_file, 0, automaton->max_min_delay);
7911 fprintf (output_file, " ");
7912 output_min_issue_delay_vect_name (output_file, automaton);
7913 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7914 /* Compress the vector. */
7915 if (automaton->max_min_delay < 2)
7916 automaton->min_issue_delay_table_compression_factor = 8;
7917 else if (automaton->max_min_delay < 4)
7918 automaton->min_issue_delay_table_compression_factor = 4;
7919 else if (automaton->max_min_delay < 16)
7920 automaton->min_issue_delay_table_compression_factor = 2;
7921 else
7922 automaton->min_issue_delay_table_compression_factor = 1;
7923 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7924 "compressed min issue delay vector");
7925 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7926 (VLA_HWINT_LENGTH (min_issue_delay_vect)
7927 + automaton->min_issue_delay_table_compression_factor
7928 - 1)
7929 / automaton->min_issue_delay_table_compression_factor);
7930 for (i = 0;
7931 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7932 i++)
7933 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7934 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7935 VLA_HWINT (compressed_min_issue_delay_vect,
7936 i / automaton->min_issue_delay_table_compression_factor)
7937 |= (VLA_HWINT (min_issue_delay_vect, i)
7938 << (8 - (i % automaton->min_issue_delay_table_compression_factor
7939 + 1)
7940 * (8 / automaton->min_issue_delay_table_compression_factor)));
7941 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7942 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7943 fprintf (output_file, "};\n\n");
7944 VLA_PTR_DELETE (output_states_vect);
7945 VLA_HWINT_DELETE (min_issue_delay_vect);
7946 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7949 #ifndef NDEBUG
7950 /* Number of states which contains transition only by advancing cpu
7951 cycle. */
7952 static int locked_states_num;
7953 #endif
7955 /* Form and output vector representing the locked states of
7956 AUTOMATON. */
7957 static void
7958 output_dead_lock_vect (automaton_t automaton)
7960 state_t *state_ptr;
7961 arc_t arc;
7962 vla_hwint_t dead_lock_vect;
7964 /* Create vect of pointers to states ordered by num of
7965 transitions from the state (state with the maximum num is the
7966 first). */
7967 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7968 pass_states (automaton, add_states_vect_el);
7969 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7970 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7971 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7972 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7973 state_ptr++)
7975 arc = first_out_arc (*state_ptr);
7976 if (arc == NULL)
7977 abort ();
7978 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
7979 = (next_out_arc (arc) == NULL
7980 && (arc->insn->insn_reserv_decl
7981 == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
7982 #ifndef NDEBUG
7983 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
7984 locked_states_num++;
7985 #endif
7987 fprintf (output_file, "/* Vector for locked state flags. */\n");
7988 fprintf (output_file, "static const ");
7989 output_range_type (output_file, 0, 1);
7990 fprintf (output_file, " ");
7991 output_dead_lock_vect_name (output_file, automaton);
7992 fprintf (output_file, "[] = {\n");
7993 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
7994 VLA_HWINT_LENGTH (dead_lock_vect));
7995 fprintf (output_file, "};\n\n");
7996 VLA_HWINT_DELETE (dead_lock_vect);
7997 VLA_PTR_DELETE (output_states_vect);
8000 /* Form and output vector representing reserved units of the states of
8001 AUTOMATON. */
8002 static void
8003 output_reserved_units_table (automaton_t automaton)
8005 state_t *curr_state_ptr;
8006 vla_hwint_t reserved_units_table;
8007 size_t state_byte_size;
8008 int i;
8010 /* Create vect of pointers to states. */
8011 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
8012 pass_states (automaton, add_states_vect_el);
8013 /* Create vector. */
8014 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
8015 state_byte_size = (description->query_units_num + 7) / 8;
8016 VLA_HWINT_EXPAND (reserved_units_table,
8017 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8018 for (i = 0;
8019 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
8020 i++)
8021 VLA_HWINT (reserved_units_table, i) = 0;
8022 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
8023 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
8024 curr_state_ptr++)
8026 for (i = 0; i < description->units_num; i++)
8027 if (units_array [i]->query_p
8028 && first_cycle_unit_presence (*curr_state_ptr, i))
8029 VLA_HWINT (reserved_units_table,
8030 (*curr_state_ptr)->order_state_num * state_byte_size
8031 + units_array [i]->query_num / 8)
8032 += (1 << (units_array [i]->query_num % 8));
8034 fprintf (output_file, "/* Vector for reserved units of states. */\n");
8035 fprintf (output_file, "static const ");
8036 output_range_type (output_file, 0, 255);
8037 fprintf (output_file, " ");
8038 output_reserved_units_table_name (output_file, automaton);
8039 fprintf (output_file, "[] = {\n");
8040 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
8041 VLA_HWINT_LENGTH (reserved_units_table));
8042 fprintf (output_file, "};\n\n");
8043 VLA_HWINT_DELETE (reserved_units_table);
8044 VLA_PTR_DELETE (output_states_vect);
8047 /* The function outputs all tables representing DFA(s) used for fast
8048 pipeline hazards recognition. */
8049 static void
8050 output_tables (void)
8052 automaton_t automaton;
8054 #ifndef NDEBUG
8055 locked_states_num = 0;
8056 #endif
8057 initiate_min_issue_delay_pass_states ();
8058 for (automaton = description->first_automaton;
8059 automaton != NULL;
8060 automaton = automaton->next_automaton)
8062 output_translate_vect (automaton);
8063 output_trans_table (automaton);
8064 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
8065 output_state_alts_table (automaton);
8066 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8067 AUTOMATON_STATE_ALTS_MACRO_NAME);
8068 output_min_issue_delay_table (automaton);
8069 output_dead_lock_vect (automaton);
8070 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
8071 output_reserved_units_table (automaton);
8072 fprintf (output_file, "\n#endif /* #if %s */\n\n",
8073 CPU_UNITS_QUERY_MACRO_NAME);
8075 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
8076 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8079 /* The function outputs definition and value of PHR interface variable
8080 `max_insn_queue_index'. Its value is not less than maximal queue
8081 length needed for the insn scheduler. */
8082 static void
8083 output_max_insn_queue_index_def (void)
8085 int i, max, latency;
8086 decl_t decl;
8088 max = description->max_insn_reserv_cycles;
8089 for (i = 0; i < description->decls_num; i++)
8091 decl = description->decls [i];
8092 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8094 latency = DECL_INSN_RESERV (decl)->default_latency;
8095 if (latency > max)
8096 max = latency;
8098 else if (decl->mode == dm_bypass)
8100 latency = DECL_BYPASS (decl)->latency;
8101 if (latency > max)
8102 max = latency;
8105 for (i = 0; (1 << i) <= max; i++)
8107 if (i < 0)
8108 abort ();
8109 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
8113 /* The function outputs switch cases for insn reservations using
8114 function *output_automata_list_code. */
8115 static void
8116 output_insn_code_cases (void (*output_automata_list_code)
8117 (automata_list_el_t))
8119 decl_t decl, decl2;
8120 int i, j;
8122 for (i = 0; i < description->decls_num; i++)
8124 decl = description->decls [i];
8125 if (decl->mode == dm_insn_reserv)
8126 DECL_INSN_RESERV (decl)->processed_p = FALSE;
8128 for (i = 0; i < description->decls_num; i++)
8130 decl = description->decls [i];
8131 if (decl->mode == dm_insn_reserv
8132 && !DECL_INSN_RESERV (decl)->processed_p)
8134 for (j = i; j < description->decls_num; j++)
8136 decl2 = description->decls [j];
8137 if (decl2->mode == dm_insn_reserv
8138 && (DECL_INSN_RESERV (decl2)->important_automata_list
8139 == DECL_INSN_RESERV (decl)->important_automata_list))
8141 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8142 fprintf (output_file, " case %d: /* %s */\n",
8143 DECL_INSN_RESERV (decl2)->insn_num,
8144 DECL_INSN_RESERV (decl2)->name);
8147 (*output_automata_list_code)
8148 (DECL_INSN_RESERV (decl)->important_automata_list);
8154 /* The function outputs a code for evaluation of a minimal delay of
8155 issue of insns which have reservations in given AUTOMATA_LIST. */
8156 static void
8157 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
8159 automata_list_el_t el;
8160 automaton_t automaton;
8162 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8164 automaton = el->automaton;
8165 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8166 output_min_issue_delay_vect_name (output_file, automaton);
8167 fprintf (output_file,
8168 (automaton->min_issue_delay_table_compression_factor != 1
8169 ? " [(" : " ["));
8170 output_translate_vect_name (output_file, automaton);
8171 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8172 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8173 output_chip_member_name (output_file, automaton);
8174 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8175 if (automaton->min_issue_delay_table_compression_factor == 1)
8176 fprintf (output_file, "];\n");
8177 else
8179 fprintf (output_file, ") / %d];\n",
8180 automaton->min_issue_delay_table_compression_factor);
8181 fprintf (output_file, " %s = (%s >> (8 - (",
8182 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8183 output_translate_vect_name (output_file, automaton);
8184 fprintf
8185 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8186 INTERNAL_INSN_CODE_NAME,
8187 automaton->min_issue_delay_table_compression_factor,
8188 8 / automaton->min_issue_delay_table_compression_factor,
8189 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8190 - 1);
8192 if (el == automata_list)
8193 fprintf (output_file, " %s = %s;\n",
8194 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8195 else
8197 fprintf (output_file, " if (%s > %s)\n",
8198 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8199 fprintf (output_file, " %s = %s;\n",
8200 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8203 fprintf (output_file, " break;\n\n");
8206 /* Output function `internal_min_issue_delay'. */
8207 static void
8208 output_internal_min_issue_delay_func (void)
8210 fprintf (output_file,
8211 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8212 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8213 CHIP_NAME, CHIP_PARAMETER_NAME);
8214 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8215 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8216 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8217 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8218 fprintf (output_file,
8219 "\n default:\n %s = -1;\n break;\n }\n",
8220 RESULT_VARIABLE_NAME);
8221 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8222 fprintf (output_file, "}\n\n");
8225 /* The function outputs a code changing state after issue of insns
8226 which have reservations in given AUTOMATA_LIST. */
8227 static void
8228 output_automata_list_transition_code (automata_list_el_t automata_list)
8230 automata_list_el_t el, next_el;
8232 fprintf (output_file, " {\n");
8233 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8234 for (el = automata_list;; el = next_el)
8236 next_el = el->next_automata_list_el;
8237 if (next_el == NULL)
8238 break;
8239 fprintf (output_file, " ");
8240 output_state_member_type (output_file, el->automaton);
8241 fprintf (output_file, " ");
8242 output_temp_chip_member_name (output_file, el->automaton);
8243 fprintf (output_file, ";\n");
8245 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8246 if (comb_vect_p (el->automaton->trans_table))
8248 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8249 output_trans_base_vect_name (output_file, el->automaton);
8250 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8251 output_chip_member_name (output_file, el->automaton);
8252 fprintf (output_file, "] + ");
8253 output_translate_vect_name (output_file, el->automaton);
8254 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8255 fprintf (output_file, " if (");
8256 output_trans_check_vect_name (output_file, el->automaton);
8257 fprintf (output_file, " [%s] != %s->",
8258 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8259 output_chip_member_name (output_file, el->automaton);
8260 fprintf (output_file, ")\n");
8261 fprintf (output_file, " return %s (%s, %s);\n",
8262 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8263 CHIP_PARAMETER_NAME);
8264 fprintf (output_file, " else\n");
8265 fprintf (output_file, " ");
8266 if (el->next_automata_list_el != NULL)
8267 output_temp_chip_member_name (output_file, el->automaton);
8268 else
8270 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8271 output_chip_member_name (output_file, el->automaton);
8273 fprintf (output_file, " = ");
8274 output_trans_comb_vect_name (output_file, el->automaton);
8275 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8277 else
8279 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8280 output_trans_full_vect_name (output_file, el->automaton);
8281 fprintf (output_file, " [");
8282 output_translate_vect_name (output_file, el->automaton);
8283 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8284 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8285 output_chip_member_name (output_file, el->automaton);
8286 fprintf (output_file, " * %d];\n",
8287 el->automaton->insn_equiv_classes_num);
8288 fprintf (output_file, " if (%s >= %d)\n",
8289 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8290 fprintf (output_file, " return %s (%s, %s);\n",
8291 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8292 CHIP_PARAMETER_NAME);
8293 fprintf (output_file, " else\n ");
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, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8303 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8304 for (el = automata_list;; el = next_el)
8306 next_el = el->next_automata_list_el;
8307 if (next_el == NULL)
8308 break;
8309 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8310 output_chip_member_name (output_file, el->automaton);
8311 fprintf (output_file, " = ");
8312 output_temp_chip_member_name (output_file, el->automaton);
8313 fprintf (output_file, ";\n");
8315 fprintf (output_file, " return -1;\n");
8316 fprintf (output_file, " }\n");
8319 /* Output function `internal_state_transition'. */
8320 static void
8321 output_internal_trans_func (void)
8323 fprintf (output_file,
8324 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8325 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8326 CHIP_NAME, CHIP_PARAMETER_NAME);
8327 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8328 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8329 output_insn_code_cases (output_automata_list_transition_code);
8330 fprintf (output_file, "\n default:\n return -1;\n }\n");
8331 fprintf (output_file, "}\n\n");
8334 /* Output code
8336 if (insn != 0)
8338 insn_code = dfa_insn_code (insn);
8339 if (insn_code > DFA__ADVANCE_CYCLE)
8340 return code;
8342 else
8343 insn_code = DFA__ADVANCE_CYCLE;
8345 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8346 code denotes CODE. */
8347 static void
8348 output_internal_insn_code_evaluation (const char *insn_name,
8349 const char *insn_code_name,
8350 int code)
8352 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8353 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8354 DFA_INSN_CODE_FUNC_NAME, insn_name);
8355 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8356 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8357 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8358 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8362 /* This function outputs `dfa_insn_code' and its helper function
8363 `dfa_insn_code_enlarge'. */
8364 static void
8365 output_dfa_insn_code_func (void)
8367 /* Emacs c-mode gets really confused if there's a { or } in column 0
8368 inside a string, so don't do that. */
8369 fprintf (output_file, "\
8370 static void\n\
8371 dfa_insn_code_enlarge (int uid)\n\
8372 {\n\
8373 int i = %s;\n\
8374 %s = 2 * uid;\n\
8375 %s = xrealloc (%s,\n\
8376 %s * sizeof(int));\n\
8377 for (; i < %s; i++)\n\
8378 %s[i] = -1;\n}\n\n",
8379 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8380 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8381 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8382 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8383 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8384 DFA_INSN_CODES_VARIABLE_NAME);
8385 fprintf (output_file, "\
8386 static inline int\n%s (rtx %s)\n\
8387 {\n\
8388 int uid = INSN_UID (%s);\n\
8389 int %s;\n\n",
8390 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8391 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8393 fprintf (output_file,
8394 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8395 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8396 fprintf (output_file, " %s = %s[uid];\n",
8397 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8398 fprintf (output_file, "\
8399 if (%s < 0)\n\
8400 {\n\
8401 %s = %s (%s);\n\
8402 %s[uid] = %s;\n\
8403 }\n",
8404 INTERNAL_INSN_CODE_NAME,
8405 INTERNAL_INSN_CODE_NAME,
8406 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8407 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8408 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8411 /* The function outputs PHR interface function `state_transition'. */
8412 static void
8413 output_trans_func (void)
8415 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8416 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8417 INSN_PARAMETER_NAME);
8418 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8419 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8420 INTERNAL_INSN_CODE_NAME, -1);
8421 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8422 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8425 /* The function outputs a code for evaluation of alternative states
8426 number for insns which have reservations in given AUTOMATA_LIST. */
8427 static void
8428 output_automata_list_state_alts_code (automata_list_el_t automata_list)
8430 automata_list_el_t el;
8431 automaton_t automaton;
8433 fprintf (output_file, " {\n");
8434 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8435 if (comb_vect_p (el->automaton->state_alts_table))
8437 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8438 break;
8440 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8442 automaton = el->automaton;
8443 if (comb_vect_p (automaton->state_alts_table))
8445 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8446 output_state_alts_base_vect_name (output_file, automaton);
8447 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8448 output_chip_member_name (output_file, automaton);
8449 fprintf (output_file, "] + ");
8450 output_translate_vect_name (output_file, automaton);
8451 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8452 fprintf (output_file, " if (");
8453 output_state_alts_check_vect_name (output_file, automaton);
8454 fprintf (output_file, " [%s] != %s->",
8455 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8456 output_chip_member_name (output_file, automaton);
8457 fprintf (output_file, ")\n");
8458 fprintf (output_file, " return 0;\n");
8459 fprintf (output_file, " else\n");
8460 fprintf (output_file,
8461 (el == automata_list
8462 ? " %s = " : " %s += "),
8463 RESULT_VARIABLE_NAME);
8464 output_state_alts_comb_vect_name (output_file, automaton);
8465 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8467 else
8469 fprintf (output_file,
8470 (el == automata_list
8471 ? "\n %s = " : " %s += "),
8472 RESULT_VARIABLE_NAME);
8473 output_state_alts_full_vect_name (output_file, automaton);
8474 fprintf (output_file, " [");
8475 output_translate_vect_name (output_file, automaton);
8476 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8477 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8478 output_chip_member_name (output_file, automaton);
8479 fprintf (output_file, " * %d];\n",
8480 automaton->insn_equiv_classes_num);
8483 fprintf (output_file, " break;\n }\n\n");
8486 /* Output function `internal_state_alts'. */
8487 static void
8488 output_internal_state_alts_func (void)
8490 fprintf (output_file,
8491 "static int\n%s (int %s, struct %s *%s)\n",
8492 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8493 CHIP_NAME, CHIP_PARAMETER_NAME);
8494 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8495 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8496 output_insn_code_cases (output_automata_list_state_alts_code);
8497 fprintf (output_file,
8498 "\n default:\n %s = 0;\n break;\n }\n",
8499 RESULT_VARIABLE_NAME);
8500 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8501 fprintf (output_file, "}\n\n");
8504 /* The function outputs PHR interface function `state_alts'. */
8505 static void
8506 output_state_alts_func (void)
8508 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8509 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8510 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8511 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8512 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8513 INTERNAL_INSN_CODE_NAME, 0);
8514 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8515 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8518 /* Output function `min_issue_delay'. */
8519 static void
8520 output_min_issue_delay_func (void)
8522 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8523 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8524 INSN_PARAMETER_NAME);
8525 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8526 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8527 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8528 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8529 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8530 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8531 fprintf (output_file, " }\n else\n %s = %s;\n",
8532 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8533 fprintf (output_file, "\n return %s (%s, %s);\n",
8534 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8535 STATE_NAME);
8536 fprintf (output_file, "}\n\n");
8539 /* Output function `internal_dead_lock'. */
8540 static void
8541 output_internal_dead_lock_func (void)
8543 automaton_t automaton;
8545 fprintf (output_file, "static int\n%s (struct %s *%s)\n",
8546 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8547 fprintf (output_file, "{\n");
8548 for (automaton = description->first_automaton;
8549 automaton != NULL;
8550 automaton = automaton->next_automaton)
8552 fprintf (output_file, " if (");
8553 output_dead_lock_vect_name (output_file, automaton);
8554 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8555 output_chip_member_name (output_file, automaton);
8556 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8558 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8561 /* The function outputs PHR interface function `state_dead_lock_p'. */
8562 static void
8563 output_dead_lock_func (void)
8565 fprintf (output_file, "int\n%s (%s %s)\n",
8566 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8567 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8568 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8571 /* Output function `internal_reset'. */
8572 static void
8573 output_internal_reset_func (void)
8575 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8576 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8577 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8578 CHIP_PARAMETER_NAME, CHIP_NAME);
8581 /* The function outputs PHR interface function `state_size'. */
8582 static void
8583 output_size_func (void)
8585 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8586 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8589 /* The function outputs PHR interface function `state_reset'. */
8590 static void
8591 output_reset_func (void)
8593 fprintf (output_file, "void\n%s (%s %s)\n",
8594 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8595 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8596 STATE_NAME);
8599 /* Output function `min_insn_conflict_delay'. */
8600 static void
8601 output_min_insn_conflict_delay_func (void)
8603 fprintf (output_file,
8604 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8605 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8606 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8607 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8608 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8609 INTERNAL_INSN2_CODE_NAME);
8610 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8611 INTERNAL_INSN_CODE_NAME, 0);
8612 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8613 INTERNAL_INSN2_CODE_NAME, 0);
8614 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8615 CHIP_NAME, STATE_NAME, CHIP_NAME);
8616 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8617 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8618 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8619 fprintf (output_file, " return %s (%s, &%s);\n",
8620 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8621 CHIP_NAME);
8622 fprintf (output_file, "}\n\n");
8625 /* Output function `internal_insn_latency'. */
8626 static void
8627 output_internal_insn_latency_func (void)
8629 decl_t decl;
8630 struct bypass_decl *bypass;
8631 int i, j, col;
8632 const char *tabletype = "unsigned char";
8634 /* Find the smallest integer type that can hold all the default
8635 latency values. */
8636 for (i = 0; i < description->decls_num; i++)
8637 if (description->decls[i]->mode == dm_insn_reserv)
8639 decl = description->decls[i];
8640 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8641 && tabletype[0] != 'i') /* don't shrink it */
8642 tabletype = "unsigned short";
8643 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8644 tabletype = "int";
8647 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",
8648 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8649 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8650 INSN2_PARAMETER_NAME);
8651 fprintf (output_file, "{\n");
8653 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8655 fputs (" return 0;\n}\n\n", output_file);
8656 return;
8659 fprintf (output_file, " static const %s default_latencies[] =\n {",
8660 tabletype);
8662 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8663 if (description->decls[i]->mode == dm_insn_reserv
8664 && description->decls[i] != advance_cycle_insn_decl)
8666 if ((col = (col+1) % 8) == 0)
8667 fputs ("\n ", output_file);
8668 decl = description->decls[i];
8669 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
8670 abort ();
8671 fprintf (output_file, "% 4d,",
8672 DECL_INSN_RESERV (decl)->default_latency);
8674 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8675 abort ();
8676 fputs ("\n };\n", output_file);
8678 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8679 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8680 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8682 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8683 for (i = 0; i < description->decls_num; i++)
8684 if (description->decls[i]->mode == dm_insn_reserv
8685 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8687 decl = description->decls [i];
8688 fprintf (output_file,
8689 " case %d:\n switch (%s)\n {\n",
8690 DECL_INSN_RESERV (decl)->insn_num,
8691 INTERNAL_INSN2_CODE_NAME);
8692 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8693 bypass != NULL;
8694 bypass = bypass->next)
8696 if (bypass->in_insn_reserv->insn_num
8697 == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8698 abort ();
8699 fprintf (output_file, " case %d:\n",
8700 bypass->in_insn_reserv->insn_num);
8701 if (bypass->bypass_guard_name == NULL)
8702 fprintf (output_file, " return %d;\n",
8703 bypass->latency);
8704 else
8706 fprintf (output_file,
8707 " if (%s (%s, %s))\n",
8708 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8709 INSN2_PARAMETER_NAME);
8710 fprintf (output_file,
8711 " return %d;\n break;\n",
8712 bypass->latency);
8715 fputs (" }\n break;\n", output_file);
8718 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8719 INTERNAL_INSN_CODE_NAME);
8722 /* The function outputs PHR interface function `insn_latency'. */
8723 static void
8724 output_insn_latency_func (void)
8726 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8727 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8728 fprintf (output_file, "{\n int %s, %s;\n",
8729 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8730 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8731 INTERNAL_INSN_CODE_NAME, 0);
8732 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8733 INTERNAL_INSN2_CODE_NAME, 0);
8734 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8735 INTERNAL_INSN_LATENCY_FUNC_NAME,
8736 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8737 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8740 /* The function outputs PHR interface function `print_reservation'. */
8741 static void
8742 output_print_reservation_func (void)
8744 decl_t decl;
8745 int i, j;
8747 fprintf (output_file,
8748 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8749 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8750 INSN_PARAMETER_NAME);
8752 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8754 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8755 NOTHING_NAME, FILE_PARAMETER_NAME);
8756 return;
8760 fputs (" static const char *const reservation_names[] =\n {",
8761 output_file);
8763 for (i = 0, j = 0; i < description->decls_num; i++)
8765 decl = description->decls [i];
8766 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8768 if (j++ != DECL_INSN_RESERV (decl)->insn_num)
8769 abort ();
8770 fprintf (output_file, "\n \"%s\",",
8771 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8772 finish_regexp_representation ();
8775 if (j != DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num)
8776 abort ();
8778 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8779 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8781 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8782 INSN_PARAMETER_NAME,
8783 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8784 fprintf (output_file, " else\n\
8785 {\n\
8786 %s = %s (%s);\n\
8787 if (%s > %s)\n\
8788 %s = %s;\n\
8789 }\n",
8790 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8791 INSN_PARAMETER_NAME,
8792 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8793 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8795 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8796 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8799 /* The following function is used to sort unit declaration by their
8800 names. */
8801 static int
8802 units_cmp (const void *unit1, const void *unit2)
8804 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8805 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8807 return strcmp (u1->name, u2->name);
8810 /* The following macro value is name of struct containing unit name
8811 and unit code. */
8812 #define NAME_CODE_STRUCT_NAME "name_code"
8814 /* The following macro value is name of table of struct name_code. */
8815 #define NAME_CODE_TABLE_NAME "name_code_table"
8817 /* The following macro values are member names for struct name_code. */
8818 #define NAME_MEMBER_NAME "name"
8819 #define CODE_MEMBER_NAME "code"
8821 /* The following macro values are local variable names for function
8822 `get_cpu_unit_code'. */
8823 #define CMP_VARIABLE_NAME "cmp"
8824 #define LOW_VARIABLE_NAME "l"
8825 #define MIDDLE_VARIABLE_NAME "m"
8826 #define HIGH_VARIABLE_NAME "h"
8828 /* The following function outputs function to obtain internal cpu unit
8829 code by the cpu unit name. */
8830 static void
8831 output_get_cpu_unit_code_func (void)
8833 int i;
8834 unit_decl_t *units;
8836 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8837 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8838 CPU_UNIT_NAME_PARAMETER_NAME);
8839 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8840 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8841 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8842 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8843 fprintf (output_file, " static struct %s %s [] =\n {\n",
8844 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8845 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8846 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8847 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8848 for (i = 0; i < description->units_num; i++)
8849 if (units [i]->query_p)
8850 fprintf (output_file, " {\"%s\", %d},\n",
8851 units[i]->name, units[i]->query_num);
8852 fprintf (output_file, " };\n\n");
8853 fprintf (output_file, " /* The following is binary search: */\n");
8854 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8855 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8856 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8857 fprintf (output_file, " while (%s <= %s)\n {\n",
8858 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8859 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8860 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8861 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8862 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8863 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8864 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8865 fprintf (output_file, " %s = %s - 1;\n",
8866 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8867 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8868 fprintf (output_file, " %s = %s + 1;\n",
8869 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8870 fprintf (output_file, " else\n");
8871 fprintf (output_file, " return %s [%s].%s;\n }\n",
8872 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8873 fprintf (output_file, " return -1;\n}\n\n");
8874 free (units);
8877 /* The following function outputs function to check reservation of cpu
8878 unit (its internal code will be passed as the function argument) in
8879 given cpu state. */
8880 static void
8881 output_cpu_unit_reservation_p (void)
8883 automaton_t automaton;
8885 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8886 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8887 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8888 CPU_CODE_PARAMETER_NAME);
8889 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8890 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8891 description->query_units_num);
8892 for (automaton = description->first_automaton;
8893 automaton != NULL;
8894 automaton = automaton->next_automaton)
8896 fprintf (output_file, " if ((");
8897 output_reserved_units_table_name (output_file, automaton);
8898 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8899 output_chip_member_name (output_file, automaton);
8900 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8901 (description->query_units_num + 7) / 8,
8902 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8903 fprintf (output_file, " return 1;\n");
8905 fprintf (output_file, " return 0;\n}\n\n");
8908 /* The function outputs PHR interface function `dfa_clean_insn_cache'. */
8909 static void
8910 output_dfa_clean_insn_cache_func (void)
8912 fprintf (output_file,
8913 "void\n%s (void)\n{\n int %s;\n\n",
8914 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8915 fprintf (output_file,
8916 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8917 I_VARIABLE_NAME, I_VARIABLE_NAME,
8918 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8919 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8922 /* The function outputs PHR interface function `dfa_start'. */
8923 static void
8924 output_dfa_start_func (void)
8926 fprintf (output_file,
8927 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8928 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8929 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8930 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8931 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8934 /* The function outputs PHR interface function `dfa_finish'. */
8935 static void
8936 output_dfa_finish_func (void)
8938 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8939 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8944 /* The page contains code for output description file (readable
8945 representation of original description and generated DFA(s). */
8947 /* The function outputs string representation of IR reservation. */
8948 static void
8949 output_regexp (regexp_t regexp)
8951 fprintf (output_description_file, "%s", regexp_representation (regexp));
8952 finish_regexp_representation ();
8955 /* Output names of units in LIST separated by comma. */
8956 static void
8957 output_unit_set_el_list (unit_set_el_t list)
8959 unit_set_el_t el;
8961 for (el = list; el != NULL; el = el->next_unit_set_el)
8963 if (el != list)
8964 fprintf (output_description_file, ", ");
8965 fprintf (output_description_file, "%s", el->unit_decl->name);
8969 /* Output patterns in LIST separated by comma. */
8970 static void
8971 output_pattern_set_el_list (pattern_set_el_t list)
8973 pattern_set_el_t el;
8974 int i;
8976 for (el = list; el != NULL; el = el->next_pattern_set_el)
8978 if (el != list)
8979 fprintf (output_description_file, ", ");
8980 for (i = 0; i < el->units_num; i++)
8981 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8982 el->unit_decls [i]->name);
8986 /* The function outputs string representation of IR define_reservation
8987 and define_insn_reservation. */
8988 static void
8989 output_description (void)
8991 decl_t decl;
8992 int i;
8994 for (i = 0; i < description->decls_num; i++)
8996 decl = description->decls [i];
8997 if (decl->mode == dm_unit)
8999 if (DECL_UNIT (decl)->excl_list != NULL)
9001 fprintf (output_description_file, "unit %s exlusion_set: ",
9002 DECL_UNIT (decl)->name);
9003 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
9004 fprintf (output_description_file, "\n");
9006 if (DECL_UNIT (decl)->presence_list != NULL)
9008 fprintf (output_description_file, "unit %s presence_set: ",
9009 DECL_UNIT (decl)->name);
9010 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
9011 fprintf (output_description_file, "\n");
9013 if (DECL_UNIT (decl)->final_presence_list != NULL)
9015 fprintf (output_description_file, "unit %s final_presence_set: ",
9016 DECL_UNIT (decl)->name);
9017 output_pattern_set_el_list
9018 (DECL_UNIT (decl)->final_presence_list);
9019 fprintf (output_description_file, "\n");
9021 if (DECL_UNIT (decl)->absence_list != NULL)
9023 fprintf (output_description_file, "unit %s absence_set: ",
9024 DECL_UNIT (decl)->name);
9025 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
9026 fprintf (output_description_file, "\n");
9028 if (DECL_UNIT (decl)->final_absence_list != NULL)
9030 fprintf (output_description_file, "unit %s final_absence_set: ",
9031 DECL_UNIT (decl)->name);
9032 output_pattern_set_el_list
9033 (DECL_UNIT (decl)->final_absence_list);
9034 fprintf (output_description_file, "\n");
9038 fprintf (output_description_file, "\n");
9039 for (i = 0; i < description->decls_num; i++)
9041 decl = description->decls [i];
9042 if (decl->mode == dm_reserv)
9044 fprintf (output_description_file, "reservation %s: ",
9045 DECL_RESERV (decl)->name);
9046 output_regexp (DECL_RESERV (decl)->regexp);
9047 fprintf (output_description_file, "\n");
9049 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9051 fprintf (output_description_file, "insn reservation %s ",
9052 DECL_INSN_RESERV (decl)->name);
9053 print_rtl (output_description_file,
9054 DECL_INSN_RESERV (decl)->condexp);
9055 fprintf (output_description_file, ": ");
9056 output_regexp (DECL_INSN_RESERV (decl)->regexp);
9057 fprintf (output_description_file, "\n");
9059 else if (decl->mode == dm_bypass)
9060 fprintf (output_description_file, "bypass %d %s %s\n",
9061 DECL_BYPASS (decl)->latency,
9062 DECL_BYPASS (decl)->out_insn_name,
9063 DECL_BYPASS (decl)->in_insn_name);
9065 fprintf (output_description_file, "\n\f\n");
9068 /* The function outputs name of AUTOMATON. */
9069 static void
9070 output_automaton_name (FILE *f, automaton_t automaton)
9072 if (automaton->corresponding_automaton_decl == NULL)
9073 fprintf (f, "#%d", automaton->automaton_order_num);
9074 else
9075 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
9078 /* Maximal length of line for pretty printing into description
9079 file. */
9080 #define MAX_LINE_LENGTH 70
9082 /* The function outputs units name belonging to AUTOMATON. */
9083 static void
9084 output_automaton_units (automaton_t automaton)
9086 decl_t decl;
9087 char *name;
9088 int curr_line_length;
9089 int there_is_an_automaton_unit;
9090 int i;
9092 fprintf (output_description_file, "\n Coresponding units:\n");
9093 fprintf (output_description_file, " ");
9094 curr_line_length = 4;
9095 there_is_an_automaton_unit = 0;
9096 for (i = 0; i < description->decls_num; i++)
9098 decl = description->decls [i];
9099 if (decl->mode == dm_unit
9100 && (DECL_UNIT (decl)->corresponding_automaton_num
9101 == automaton->automaton_order_num))
9103 there_is_an_automaton_unit = 1;
9104 name = DECL_UNIT (decl)->name;
9105 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
9107 curr_line_length = strlen (name) + 4;
9108 fprintf (output_description_file, "\n ");
9110 else
9112 curr_line_length += strlen (name) + 1;
9113 fprintf (output_description_file, " ");
9115 fprintf (output_description_file, "%s", name);
9118 if (!there_is_an_automaton_unit)
9119 fprintf (output_description_file, "<None>");
9120 fprintf (output_description_file, "\n\n");
9123 /* The following variable is used for forming array of all possible cpu unit
9124 reservations described by the current DFA state. */
9125 static vla_ptr_t state_reservs;
9127 /* The function forms `state_reservs' for STATE. */
9128 static void
9129 add_state_reservs (state_t state)
9131 alt_state_t curr_alt_state;
9132 reserv_sets_t reservs;
9134 if (state->component_states != NULL)
9135 for (curr_alt_state = state->component_states;
9136 curr_alt_state != NULL;
9137 curr_alt_state = curr_alt_state->next_sorted_alt_state)
9138 add_state_reservs (curr_alt_state->state);
9139 else
9141 reservs = state->reservs;
9142 VLA_PTR_ADD (state_reservs, reservs);
9146 /* The function outputs readable representation of all out arcs of
9147 STATE. */
9148 static void
9149 output_state_arcs (state_t state)
9151 arc_t arc;
9152 ainsn_t ainsn;
9153 char *insn_name;
9154 int curr_line_length;
9156 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
9158 ainsn = arc->insn;
9159 if (!ainsn->first_insn_with_same_reservs)
9160 abort ();
9161 fprintf (output_description_file, " ");
9162 curr_line_length = 7;
9163 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
9166 insn_name = ainsn->insn_reserv_decl->name;
9167 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
9169 if (ainsn != arc->insn)
9171 fprintf (output_description_file, ",\n ");
9172 curr_line_length = strlen (insn_name) + 6;
9174 else
9175 curr_line_length += strlen (insn_name);
9177 else
9179 curr_line_length += strlen (insn_name);
9180 if (ainsn != arc->insn)
9182 curr_line_length += 2;
9183 fprintf (output_description_file, ", ");
9186 fprintf (output_description_file, "%s", insn_name);
9187 ainsn = ainsn->next_same_reservs_insn;
9189 while (ainsn != NULL);
9190 fprintf (output_description_file, " %d (%d)\n",
9191 arc->to_state->order_state_num, arc->state_alts);
9193 fprintf (output_description_file, "\n");
9196 /* The following function is used for sorting possible cpu unit
9197 reservation of a DFA state. */
9198 static int
9199 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
9201 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9202 *(reserv_sets_t *) reservs_ptr_2);
9205 /* The following function is used for sorting possible cpu unit
9206 reservation of a DFA state. */
9207 static void
9208 remove_state_duplicate_reservs (void)
9210 reserv_sets_t *reservs_ptr;
9211 reserv_sets_t *last_formed_reservs_ptr;
9213 last_formed_reservs_ptr = NULL;
9214 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9215 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9216 reservs_ptr++)
9217 if (last_formed_reservs_ptr == NULL)
9218 last_formed_reservs_ptr = reservs_ptr;
9219 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9221 ++last_formed_reservs_ptr;
9222 *last_formed_reservs_ptr = *reservs_ptr;
9224 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9227 /* The following function output readable representation of DFA(s)
9228 state used for fast recognition of pipeline hazards. State is
9229 described by possible (current and scheduled) cpu unit
9230 reservations. */
9231 static void
9232 output_state (state_t state)
9234 reserv_sets_t *reservs_ptr;
9236 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9237 fprintf (output_description_file, " State #%d", state->order_state_num);
9238 fprintf (output_description_file,
9239 state->new_cycle_p ? " (new cycle)\n" : "\n");
9240 add_state_reservs (state);
9241 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9242 sizeof (reserv_sets_t), state_reservs_cmp);
9243 remove_state_duplicate_reservs ();
9244 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9245 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9246 reservs_ptr++)
9248 fprintf (output_description_file, " ");
9249 output_reserv_sets (output_description_file, *reservs_ptr);
9250 fprintf (output_description_file, "\n");
9252 fprintf (output_description_file, "\n");
9253 output_state_arcs (state);
9254 VLA_PTR_DELETE (state_reservs);
9257 /* The following function output readable representation of
9258 DFAs used for fast recognition of pipeline hazards. */
9259 static void
9260 output_automaton_descriptions (void)
9262 automaton_t automaton;
9264 for (automaton = description->first_automaton;
9265 automaton != NULL;
9266 automaton = automaton->next_automaton)
9268 fprintf (output_description_file, "\nAutomaton ");
9269 output_automaton_name (output_description_file, automaton);
9270 fprintf (output_description_file, "\n");
9271 output_automaton_units (automaton);
9272 pass_states (automaton, output_state);
9278 /* The page contains top level function for generation DFA(s) used for
9279 PHR. */
9281 /* The function outputs statistics about work of different phases of
9282 DFA generator. */
9283 static void
9284 output_statistics (FILE *f)
9286 automaton_t automaton;
9287 int states_num;
9288 #ifndef NDEBUG
9289 int transition_comb_vect_els = 0;
9290 int transition_full_vect_els = 0;
9291 int state_alts_comb_vect_els = 0;
9292 int state_alts_full_vect_els = 0;
9293 int min_issue_delay_vect_els = 0;
9294 #endif
9296 for (automaton = description->first_automaton;
9297 automaton != NULL;
9298 automaton = automaton->next_automaton)
9300 fprintf (f, "\nAutomaton ");
9301 output_automaton_name (f, automaton);
9302 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9303 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9304 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9305 automaton->DFA_states_num, automaton->DFA_arcs_num);
9306 states_num = automaton->DFA_states_num;
9307 if (!no_minimization_flag)
9309 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9310 automaton->minimal_DFA_states_num,
9311 automaton->minimal_DFA_arcs_num);
9312 states_num = automaton->minimal_DFA_states_num;
9314 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9315 description->insns_num, automaton->insn_equiv_classes_num);
9316 #ifndef NDEBUG
9317 fprintf
9318 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9319 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9320 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9321 (comb_vect_p (automaton->trans_table)
9322 ? "use comb vect" : "use simple vect"));
9323 fprintf
9324 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9325 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9326 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9327 (comb_vect_p (automaton->state_alts_table)
9328 ? "use comb vect" : "use simple vect"));
9329 fprintf
9330 (f, "%5ld min delay table els, compression factor %d\n",
9331 (long) states_num * automaton->insn_equiv_classes_num,
9332 automaton->min_issue_delay_table_compression_factor);
9333 transition_comb_vect_els
9334 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9335 transition_full_vect_els
9336 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9337 state_alts_comb_vect_els
9338 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9339 state_alts_full_vect_els
9340 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9341 min_issue_delay_vect_els
9342 += states_num * automaton->insn_equiv_classes_num;
9343 #endif
9345 #ifndef NDEBUG
9346 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9347 allocated_states_num, allocated_arcs_num);
9348 fprintf (f, "%5d all allocated alternative states\n",
9349 allocated_alt_states_num);
9350 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9351 transition_comb_vect_els, transition_full_vect_els);
9352 fprintf
9353 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9354 state_alts_comb_vect_els, state_alts_full_vect_els);
9355 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9356 fprintf (f, "%5d locked states num\n", locked_states_num);
9357 #endif
9360 /* The function output times of work of different phases of DFA
9361 generator. */
9362 static void
9363 output_time_statistics (FILE *f)
9365 fprintf (f, "\n transformation: ");
9366 print_active_time (f, transform_time);
9367 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9368 print_active_time (f, NDFA_time);
9369 if (ndfa_flag)
9371 fprintf (f, ", NDFA -> DFA: ");
9372 print_active_time (f, NDFA_to_DFA_time);
9374 fprintf (f, "\n DFA minimization: ");
9375 print_active_time (f, minimize_time);
9376 fprintf (f, ", making insn equivalence: ");
9377 print_active_time (f, equiv_time);
9378 fprintf (f, "\n all automaton generation: ");
9379 print_active_time (f, automaton_generation_time);
9380 fprintf (f, ", output: ");
9381 print_active_time (f, output_time);
9382 fprintf (f, "\n");
9385 /* The function generates DFA (deterministic finite state automaton)
9386 for fast recognition of pipeline hazards. No errors during
9387 checking must be fixed before this function call. */
9388 static void
9389 generate (void)
9391 automata_num = split_argument;
9392 if (description->units_num < automata_num)
9393 automata_num = description->units_num;
9394 initiate_states ();
9395 initiate_arcs ();
9396 initiate_automata_lists ();
9397 initiate_pass_states ();
9398 initiate_excl_sets ();
9399 initiate_presence_absence_pattern_sets ();
9400 automaton_generation_time = create_ticker ();
9401 create_automata ();
9402 ticker_off (&automaton_generation_time);
9407 /* The following function creates insn attribute whose values are
9408 number alternatives in insn reservations. */
9409 static void
9410 make_insn_alts_attr (void)
9412 int i, insn_num;
9413 decl_t decl;
9414 rtx condexp;
9416 condexp = rtx_alloc (COND);
9417 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9418 XEXP (condexp, 1) = make_numeric_value (0);
9419 for (i = insn_num = 0; i < description->decls_num; i++)
9421 decl = description->decls [i];
9422 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9424 XVECEXP (condexp, 0, 2 * insn_num)
9425 = DECL_INSN_RESERV (decl)->condexp;
9426 XVECEXP (condexp, 0, 2 * insn_num + 1)
9427 = make_numeric_value
9428 (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9429 ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9430 ->transformed_regexp)->regexps_num);
9431 insn_num++;
9434 if (description->insns_num != insn_num + 1)
9435 abort ();
9436 make_internal_attr (attr_printf (sizeof ("*")
9437 + strlen (INSN_ALTS_FUNC_NAME) + 1,
9438 "*%s", INSN_ALTS_FUNC_NAME),
9439 condexp, ATTR_NONE);
9444 /* The following function creates attribute which is order number of
9445 insn in pipeline hazard description translator. */
9446 static void
9447 make_internal_dfa_insn_code_attr (void)
9449 int i, insn_num;
9450 decl_t decl;
9451 rtx condexp;
9453 condexp = rtx_alloc (COND);
9454 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9455 XEXP (condexp, 1)
9456 = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9457 ->insn_num + 1);
9458 for (i = insn_num = 0; i < description->decls_num; i++)
9460 decl = description->decls [i];
9461 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9463 XVECEXP (condexp, 0, 2 * insn_num)
9464 = DECL_INSN_RESERV (decl)->condexp;
9465 XVECEXP (condexp, 0, 2 * insn_num + 1)
9466 = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9467 insn_num++;
9470 if (description->insns_num != insn_num + 1)
9471 abort ();
9472 make_internal_attr
9473 (attr_printf (sizeof ("*")
9474 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9475 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9476 condexp, ATTR_STATIC);
9481 /* The following function creates attribute which order number of insn
9482 in pipeline hazard description translator. */
9483 static void
9484 make_default_insn_latency_attr (void)
9486 int i, insn_num;
9487 decl_t decl;
9488 rtx condexp;
9490 condexp = rtx_alloc (COND);
9491 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9492 XEXP (condexp, 1) = make_numeric_value (0);
9493 for (i = insn_num = 0; i < description->decls_num; i++)
9495 decl = description->decls [i];
9496 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9498 XVECEXP (condexp, 0, 2 * insn_num)
9499 = DECL_INSN_RESERV (decl)->condexp;
9500 XVECEXP (condexp, 0, 2 * insn_num + 1)
9501 = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9502 insn_num++;
9505 if (description->insns_num != insn_num + 1)
9506 abort ();
9507 make_internal_attr (attr_printf (sizeof ("*")
9508 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9509 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9510 condexp, ATTR_NONE);
9515 /* The following function creates attribute which returns 1 if given
9516 output insn has bypassing and 0 otherwise. */
9517 static void
9518 make_bypass_attr (void)
9520 int i, bypass_insn;
9521 int bypass_insns_num = 0;
9522 decl_t decl;
9523 rtx result_rtx;
9525 for (i = 0; i < description->decls_num; i++)
9527 decl = description->decls [i];
9528 if (decl->mode == dm_insn_reserv
9529 && DECL_INSN_RESERV (decl)->condexp != NULL
9530 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9531 bypass_insns_num++;
9533 if (bypass_insns_num == 0)
9534 result_rtx = make_numeric_value (0);
9535 else
9537 result_rtx = rtx_alloc (COND);
9538 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9539 XEXP (result_rtx, 1) = make_numeric_value (0);
9541 for (i = bypass_insn = 0; i < description->decls_num; i++)
9543 decl = description->decls [i];
9544 if (decl->mode == dm_insn_reserv
9545 && DECL_INSN_RESERV (decl)->condexp != NULL
9546 && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9548 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9549 = DECL_INSN_RESERV (decl)->condexp;
9550 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9551 = make_numeric_value (1);
9552 bypass_insn++;
9556 make_internal_attr (attr_printf (sizeof ("*")
9557 + strlen (BYPASS_P_FUNC_NAME) + 1,
9558 "*%s", BYPASS_P_FUNC_NAME),
9559 result_rtx, ATTR_NONE);
9564 /* This page mainly contains top level functions of pipeline hazards
9565 description translator. */
9567 /* The following macro value is suffix of name of description file of
9568 pipeline hazards description translator. */
9569 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9571 /* The function returns suffix of given file name. The returned
9572 string can not be changed. */
9573 static const char *
9574 file_name_suffix (const char *file_name)
9576 const char *last_period;
9578 for (last_period = NULL; *file_name != '\0'; file_name++)
9579 if (*file_name == '.')
9580 last_period = file_name;
9581 return (last_period == NULL ? file_name : last_period);
9584 /* The function returns base name of given file name, i.e. pointer to
9585 first char after last `/' (or `\' for WIN32) in given file name,
9586 given file name itself if the directory name is absent. The
9587 returned string can not be changed. */
9588 static const char *
9589 base_file_name (const char *file_name)
9591 int directory_name_length;
9593 directory_name_length = strlen (file_name);
9594 #ifdef WIN32
9595 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9596 && file_name[directory_name_length] != '\\')
9597 #else
9598 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9599 #endif
9600 directory_name_length--;
9601 return file_name + directory_name_length + 1;
9604 /* The following is top level function to initialize the work of
9605 pipeline hazards description translator. */
9606 void
9607 initiate_automaton_gen (int argc, char **argv)
9609 const char *base_name;
9610 int i;
9612 ndfa_flag = 0;
9613 split_argument = 0; /* default value */
9614 no_minimization_flag = 0;
9615 time_flag = 0;
9616 v_flag = 0;
9617 w_flag = 0;
9618 for (i = 2; i < argc; i++)
9619 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9620 no_minimization_flag = 1;
9621 else if (strcmp (argv [i], TIME_OPTION) == 0)
9622 time_flag = 1;
9623 else if (strcmp (argv [i], V_OPTION) == 0)
9624 v_flag = 1;
9625 else if (strcmp (argv [i], W_OPTION) == 0)
9626 w_flag = 1;
9627 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9628 ndfa_flag = 1;
9629 else if (strcmp (argv [i], "-split") == 0)
9631 if (i + 1 >= argc)
9632 fatal ("-split has no argument.");
9633 fatal ("option `-split' has not been implemented yet\n");
9634 /* split_argument = atoi (argument_vect [i + 1]); */
9636 VLA_PTR_CREATE (decls, 150, "decls");
9637 /* Initialize IR storage. */
9638 obstack_init (&irp);
9639 initiate_automaton_decl_table ();
9640 initiate_insn_decl_table ();
9641 initiate_decl_table ();
9642 output_file = stdout;
9643 output_description_file = NULL;
9644 base_name = base_file_name (argv[1]);
9645 obstack_grow (&irp, base_name,
9646 strlen (base_name) - strlen (file_name_suffix (base_name)));
9647 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9648 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9649 obstack_1grow (&irp, '\0');
9650 output_description_file_name = obstack_base (&irp);
9651 obstack_finish (&irp);
9654 /* The following function checks existence at least one arc marked by
9655 each insn. */
9656 static void
9657 check_automata_insn_issues (void)
9659 automaton_t automaton;
9660 ainsn_t ainsn, reserv_ainsn;
9662 for (automaton = description->first_automaton;
9663 automaton != NULL;
9664 automaton = automaton->next_automaton)
9666 for (ainsn = automaton->ainsn_list;
9667 ainsn != NULL;
9668 ainsn = ainsn->next_ainsn)
9669 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9671 for (reserv_ainsn = ainsn;
9672 reserv_ainsn != NULL;
9673 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9674 if (automaton->corresponding_automaton_decl != NULL)
9676 if (!w_flag)
9677 error ("Automaton `%s': Insn `%s' will never be issued",
9678 automaton->corresponding_automaton_decl->name,
9679 reserv_ainsn->insn_reserv_decl->name);
9680 else
9681 warning
9682 ("Automaton `%s': Insn `%s' will never be issued",
9683 automaton->corresponding_automaton_decl->name,
9684 reserv_ainsn->insn_reserv_decl->name);
9686 else
9688 if (!w_flag)
9689 error ("Insn `%s' will never be issued",
9690 reserv_ainsn->insn_reserv_decl->name);
9691 else
9692 warning ("Insn `%s' will never be issued",
9693 reserv_ainsn->insn_reserv_decl->name);
9699 /* The following vla is used for storing pointers to all achieved
9700 states. */
9701 static vla_ptr_t automaton_states;
9703 /* This function is called by function pass_states to add an achieved
9704 STATE. */
9705 static void
9706 add_automaton_state (state_t state)
9708 VLA_PTR_ADD (automaton_states, state);
9711 /* The following function forms list of important automata (whose
9712 states may be changed after the insn issue) for each insn. */
9713 static void
9714 form_important_insn_automata_lists (void)
9716 automaton_t automaton;
9717 state_t *state_ptr;
9718 decl_t decl;
9719 ainsn_t ainsn;
9720 arc_t arc;
9721 int i;
9723 VLA_PTR_CREATE (automaton_states, 1500,
9724 "automaton states for forming important insn automata sets");
9725 /* Mark important ainsns. */
9726 for (automaton = description->first_automaton;
9727 automaton != NULL;
9728 automaton = automaton->next_automaton)
9730 VLA_PTR_NULLIFY (automaton_states);
9731 pass_states (automaton, add_automaton_state);
9732 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9733 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9734 state_ptr++)
9736 for (arc = first_out_arc (*state_ptr);
9737 arc != NULL;
9738 arc = next_out_arc (arc))
9739 if (arc->to_state != *state_ptr)
9741 if (!arc->insn->first_insn_with_same_reservs)
9742 abort ();
9743 for (ainsn = arc->insn;
9744 ainsn != NULL;
9745 ainsn = ainsn->next_same_reservs_insn)
9746 ainsn->important_p = TRUE;
9750 VLA_PTR_DELETE (automaton_states);
9751 /* Create automata sets for the insns. */
9752 for (i = 0; i < description->decls_num; i++)
9754 decl = description->decls [i];
9755 if (decl->mode == dm_insn_reserv)
9757 automata_list_start ();
9758 for (automaton = description->first_automaton;
9759 automaton != NULL;
9760 automaton = automaton->next_automaton)
9761 for (ainsn = automaton->ainsn_list;
9762 ainsn != NULL;
9763 ainsn = ainsn->next_ainsn)
9764 if (ainsn->important_p
9765 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9767 automata_list_add (automaton);
9768 break;
9770 DECL_INSN_RESERV (decl)->important_automata_list
9771 = automata_list_finish ();
9777 /* The following is top level function to generate automat(a,on) for
9778 fast recognition of pipeline hazards. */
9779 void
9780 expand_automata (void)
9782 int i;
9784 description = create_node (sizeof (struct description)
9785 /* One entry for cycle advancing insn. */
9786 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9787 description->decls_num = VLA_PTR_LENGTH (decls);
9788 description->query_units_num = 0;
9789 for (i = 0; i < description->decls_num; i++)
9791 description->decls [i] = VLA_PTR (decls, i);
9792 if (description->decls [i]->mode == dm_unit
9793 && DECL_UNIT (description->decls [i])->query_p)
9794 DECL_UNIT (description->decls [i])->query_num
9795 = description->query_units_num++;
9797 all_time = create_ticker ();
9798 check_time = create_ticker ();
9799 fprintf (stderr, "Check description...");
9800 fflush (stderr);
9801 check_all_description ();
9802 fprintf (stderr, "done\n");
9803 ticker_off (&check_time);
9804 generation_time = create_ticker ();
9805 if (!have_error)
9807 transform_insn_regexps ();
9808 check_unit_distributions_to_automata ();
9810 if (!have_error)
9812 generate ();
9813 check_automata_insn_issues ();
9815 if (!have_error)
9817 form_important_insn_automata_lists ();
9818 fprintf (stderr, "Generation of attributes...");
9819 fflush (stderr);
9820 make_internal_dfa_insn_code_attr ();
9821 make_insn_alts_attr ();
9822 make_default_insn_latency_attr ();
9823 make_bypass_attr ();
9824 fprintf (stderr, "done\n");
9826 ticker_off (&generation_time);
9827 ticker_off (&all_time);
9828 fprintf (stderr, "All other genattrtab stuff...");
9829 fflush (stderr);
9832 /* The following is top level function to output PHR and to finish
9833 work with pipeline description translator. */
9834 void
9835 write_automata (void)
9837 fprintf (stderr, "done\n");
9838 if (have_error)
9839 fatal ("Errors in DFA description");
9840 ticker_on (&all_time);
9841 output_time = create_ticker ();
9842 fprintf (stderr, "Forming and outputting automata tables...");
9843 fflush (stderr);
9844 output_dfa_max_issue_rate ();
9845 output_tables ();
9846 fprintf (stderr, "done\n");
9847 fprintf (stderr, "Output functions to work with automata...");
9848 fflush (stderr);
9849 output_chip_definitions ();
9850 output_max_insn_queue_index_def ();
9851 output_internal_min_issue_delay_func ();
9852 output_internal_trans_func ();
9853 /* Cache of insn dfa codes: */
9854 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9855 fprintf (output_file, "\nstatic int %s;\n\n",
9856 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9857 output_dfa_insn_code_func ();
9858 output_trans_func ();
9859 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9860 output_internal_state_alts_func ();
9861 output_state_alts_func ();
9862 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9863 AUTOMATON_STATE_ALTS_MACRO_NAME);
9864 output_min_issue_delay_func ();
9865 output_internal_dead_lock_func ();
9866 output_dead_lock_func ();
9867 output_size_func ();
9868 output_internal_reset_func ();
9869 output_reset_func ();
9870 output_min_insn_conflict_delay_func ();
9871 output_internal_insn_latency_func ();
9872 output_insn_latency_func ();
9873 output_print_reservation_func ();
9874 /* Output function get_cpu_unit_code. */
9875 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9876 output_get_cpu_unit_code_func ();
9877 output_cpu_unit_reservation_p ();
9878 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9879 CPU_UNITS_QUERY_MACRO_NAME);
9880 output_dfa_clean_insn_cache_func ();
9881 output_dfa_start_func ();
9882 output_dfa_finish_func ();
9883 fprintf (stderr, "done\n");
9884 if (v_flag)
9886 output_description_file = fopen (output_description_file_name, "w");
9887 if (output_description_file == NULL)
9889 perror (output_description_file_name);
9890 exit (FATAL_EXIT_CODE);
9892 fprintf (stderr, "Output automata description...");
9893 fflush (stderr);
9894 output_description ();
9895 output_automaton_descriptions ();
9896 fprintf (stderr, "done\n");
9897 output_statistics (output_description_file);
9899 output_statistics (stderr);
9900 ticker_off (&output_time);
9901 output_time_statistics (stderr);
9902 finish_states ();
9903 finish_arcs ();
9904 finish_automata_lists ();
9905 if (time_flag)
9907 fprintf (stderr, "Summary:\n");
9908 fprintf (stderr, " check time ");
9909 print_active_time (stderr, check_time);
9910 fprintf (stderr, ", generation time ");
9911 print_active_time (stderr, generation_time);
9912 fprintf (stderr, ", all time ");
9913 print_active_time (stderr, all_time);
9914 fprintf (stderr, "\n");
9916 /* Finish all work. */
9917 if (output_description_file != NULL)
9919 fflush (output_description_file);
9920 if (ferror (stdout) != 0)
9921 fatal ("Error in writing DFA description file %s",
9922 output_description_file_name);
9923 fclose (output_description_file);
9925 finish_automaton_decl_table ();
9926 finish_insn_decl_table ();
9927 finish_decl_table ();
9928 obstack_free (&irp, NULL);
9929 if (have_error && output_description_file != NULL)
9930 remove (output_description_file_name);