genautomata.c revision 117395
1/* Pipeline hazard description translator.
2   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3
4   Written by Vladimir Makarov <vmakarov@redhat.com>
5
6This file is part of GNU CC.
7
8GNU CC is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 2, or (at your option) any
11later version.
12
13GNU CC is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU CC; see the file COPYING.  If not, write to the Free
20Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2102111-1307, USA.  */
22
23/* References:
24
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.
28
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.
32
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.
37
38   The current implementation is different from the 2nd article in the
39   following:
40
41   1. New operator `|' (alternative) is permitted in functional unit
42      reservation which can be treated deterministicly and
43      non-deterministicly.
44
45   2. Possibility of usage of nondeterministic automata too.
46
47   3. Possibility to query functional unit reservations for given
48      automaton state.
49
50   4. Several constructions to describe impossible reservations
51      (`exclusion_set', `presence_set', and `absence_set').
52
53   5. No reverse automata are generated.  Trace instruction scheduling
54      requires this.  It can be easily added in the future if we
55      really need this.
56
57   6. Union of automaton states are not generated yet.  It is planned
58      to be implemented.  Such feature is needed to make more accurate
59      interlock insn scheduling to get state describing functional
60      unit reservation in a joint CFG point.
61*/
62
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.
67
68   The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69   `gen_bypass', `gen_excl_set', `gen_presence_set',
70   `gen_absence_set', `gen_automaton', `gen_automata_option',
71   `gen_reserv', `gen_insn_reserv' are called from file
72   `genattrtab.c'.  They transform RTL constructions describing
73   automata in .md file into internal representation convenient for
74   further processing.
75
76   The translator major function `expand_automata' processes the
77   description internal representation into finite state automaton.
78   It can be divided on:
79
80     o checking correctness of the automaton pipeline description
81       (major function is `check_all_description').
82
83     o generating automaton (automata) from the description (major
84       function is `make_automaton').
85
86     o optional transformation of nondeterministic finite state
87       automata into deterministic ones if the alternative operator
88       `|' is treated nondeterministicly in the description (major
89       function is NDFA_to_DFA).
90
91     o optional minimization of the finite state automata by merging
92       equivalent automaton states (major function is `minimize_DFA').
93
94     o forming tables (some as comb vectors) and attributes
95       representing the automata (functions output_..._table).
96
97   Function `write_automata' outputs the created finite state
98   automaton as different tables and functions which works with the
99   automata to inquire automaton state and to change its state.  These
100   function are used by gcc instruction scheduler and may be some
101   other gcc code.  */
102
103#include "hconfig.h"
104#include "system.h"
105#include "rtl.h"
106#include "obstack.h"
107#include "errors.h"
108
109#include <math.h>
110#include "hashtab.h"
111#include "varray.h"
112
113#ifndef CHAR_BIT
114#define CHAR_BIT 8
115#endif
116
117#include "genattrtab.h"
118
119/* Positions in machine description file.  Now they are not used.  But
120   they could be used in the future for better diagnostic messages.  */
121typedef int pos_t;
122
123/* The following is element of vector of current (and planned in the
124   future) functional unit reservations.  */
125typedef unsigned HOST_WIDE_INT set_el_t;
126
127/* Reservations of function units are represented by value of the following
128   type.  */
129typedef set_el_t *reserv_sets_t;
130
131/* The following structure represents variable length array (vla) of
132   pointers and HOST WIDE INTs.  We could be use only varray.  But we
133   add new lay because we add elements very frequently and this could
134   stress OS allocator when varray is used only.  */
135typedef struct {
136  size_t length;      /* current size of vla.  */
137  varray_type varray; /* container for vla.  */
138} vla_ptr_t;
139
140typedef vla_ptr_t vla_hwint_t;
141
142/* The following structure describes a ticker.  */
143struct ticker
144{
145  /* The following member value is time of the ticker creation with
146     taking into account time when the ticker is off.  Active time of
147     the ticker is current time minus the value.  */
148  int modified_creation_time;
149  /* The following member value is time (incremented by one) when the
150     ticker was off.  Zero value means that now the ticker is on.  */
151  int incremented_off_time;
152};
153
154/* The ticker is represented by the following type.  */
155typedef struct ticker ticker_t;
156
157/* The following type describes elements of output vectors.  */
158typedef HOST_WIDE_INT vect_el_t;
159
160/* Forward declaration of structures of internal representation of
161   pipeline description based on NDFA.  */
162
163struct unit_decl;
164struct bypass_decl;
165struct result_decl;
166struct automaton_decl;
167struct unit_rel_decl;
168struct reserv_decl;
169struct insn_reserv_decl;
170struct decl;
171struct unit_regexp;
172struct result_regexp;
173struct reserv_regexp;
174struct nothing_regexp;
175struct sequence_regexp;
176struct repeat_regexp;
177struct allof_regexp;
178struct oneof_regexp;
179struct regexp;
180struct description;
181struct unit_set_el;
182struct state;
183struct alt_state;
184struct arc;
185struct ainsn;
186struct automaton;
187struct state_ainsn_table;
188
189/* The following typedefs are for brevity.  */
190typedef struct unit_decl *unit_decl_t;
191typedef struct decl *decl_t;
192typedef struct regexp *regexp_t;
193typedef struct unit_set_el *unit_set_el_t;
194typedef struct alt_state *alt_state_t;
195typedef struct state *state_t;
196typedef struct arc *arc_t;
197typedef struct ainsn *ainsn_t;
198typedef struct automaton *automaton_t;
199typedef struct automata_list_el *automata_list_el_t;
200typedef struct state_ainsn_table *state_ainsn_table_t;
201
202
203/* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
204   gen_bypass, gen_excl_set, gen_presence_set, gen_absence_set,
205   gen_automaton, gen_automata_option, gen_reserv, gen_insn_reserv,
206   initiate_automaton_gen, expand_automata, write_automata are
207   described on the file top because the functions are called from
208   function `main'.  */
209
210static void *create_node            PARAMS ((size_t));
211static void *copy_node              PARAMS ((const void *, size_t));
212static char *check_name             PARAMS ((char *, pos_t));
213static char *next_sep_el            PARAMS ((char **, int, int));
214static int n_sep_els                PARAMS ((char *, int, int));
215static char **get_str_vect          PARAMS ((char *, int *, int, int));
216static regexp_t gen_regexp_el       PARAMS ((char *));
217static regexp_t gen_regexp_repeat   PARAMS ((char *));
218static regexp_t gen_regexp_allof    PARAMS ((char *));
219static regexp_t gen_regexp_oneof    PARAMS ((char *));
220static regexp_t gen_regexp_sequence PARAMS ((char *));
221static regexp_t gen_regexp          PARAMS ((char *));
222
223static unsigned string_hash         PARAMS ((const char *));
224static hashval_t automaton_decl_hash PARAMS ((const void *));
225static int automaton_decl_eq_p      PARAMS ((const void *,
226						   const void *));
227static decl_t insert_automaton_decl       PARAMS ((decl_t));
228static decl_t find_automaton_decl         PARAMS ((char *));
229static void initiate_automaton_decl_table PARAMS ((void));
230static void finish_automaton_decl_table   PARAMS ((void));
231
232static hashval_t insn_decl_hash           PARAMS ((const void *));
233static int insn_decl_eq_p                 PARAMS ((const void *,
234						   const void *));
235static decl_t insert_insn_decl            PARAMS ((decl_t));
236static decl_t find_insn_decl              PARAMS ((char *));
237static void initiate_insn_decl_table      PARAMS ((void));
238static void finish_insn_decl_table        PARAMS ((void));
239
240static hashval_t decl_hash                PARAMS ((const void *));
241static int decl_eq_p                      PARAMS ((const void *,
242						   const void *));
243static decl_t insert_decl                 PARAMS ((decl_t));
244static decl_t find_decl                   PARAMS ((char *));
245static void initiate_decl_table           PARAMS ((void));
246static void finish_decl_table             PARAMS ((void));
247
248static unit_set_el_t process_excls       PARAMS ((char **, int, pos_t));
249static void add_excls                    PARAMS ((unit_set_el_t, unit_set_el_t,
250						  pos_t));
251static unit_set_el_t process_presence_absence
252					 PARAMS ((char **, int, pos_t, int));
253static void add_presence_absence	 PARAMS ((unit_set_el_t, unit_set_el_t,
254						  pos_t, int));
255static void process_decls                PARAMS ((void));
256static struct bypass_decl *find_bypass   PARAMS ((struct bypass_decl *,
257						  struct insn_reserv_decl *));
258static void check_automaton_usage        PARAMS ((void));
259static regexp_t process_regexp           PARAMS ((regexp_t));
260static void process_regexp_decls         PARAMS ((void));
261static void check_usage                  PARAMS ((void));
262static int loop_in_regexp                PARAMS ((regexp_t, decl_t));
263static void check_loops_in_regexps       PARAMS ((void));
264static int process_regexp_cycles         PARAMS ((regexp_t, int));
265static void evaluate_max_reserv_cycles   PARAMS ((void));
266static void check_all_description        PARAMS ((void));
267
268static ticker_t create_ticker               PARAMS ((void));
269static void ticker_off                      PARAMS ((ticker_t *));
270static void ticker_on                       PARAMS ((ticker_t *));
271static int active_time                      PARAMS ((ticker_t));
272static void print_active_time               PARAMS ((FILE *, ticker_t));
273
274static void add_advance_cycle_insn_decl     PARAMS ((void));
275
276static alt_state_t get_free_alt_state PARAMS ((void));
277static void free_alt_state              PARAMS ((alt_state_t));
278static void free_alt_states             PARAMS ((alt_state_t));
279static int alt_state_cmp                PARAMS ((const void *alt_state_ptr_1,
280						 const void *alt_state_ptr_2));
281static alt_state_t uniq_sort_alt_states PARAMS ((alt_state_t));
282static int alt_states_eq                PARAMS ((alt_state_t, alt_state_t));
283static void initiate_alt_states         PARAMS ((void));
284static void finish_alt_states           PARAMS ((void));
285
286static reserv_sets_t alloc_empty_reserv_sets PARAMS ((void));
287static unsigned reserv_sets_hash_value PARAMS ((reserv_sets_t));
288static int reserv_sets_cmp             PARAMS ((reserv_sets_t, reserv_sets_t));
289static int reserv_sets_eq              PARAMS ((reserv_sets_t, reserv_sets_t));
290static void set_unit_reserv            PARAMS ((reserv_sets_t, int, int));
291static int test_unit_reserv            PARAMS ((reserv_sets_t, int, int));
292static int it_is_empty_reserv_sets     PARAMS ((reserv_sets_t))
293                                            ATTRIBUTE_UNUSED;
294static int reserv_sets_are_intersected PARAMS ((reserv_sets_t, reserv_sets_t));
295static void reserv_sets_shift          PARAMS ((reserv_sets_t, reserv_sets_t));
296static void reserv_sets_or             PARAMS ((reserv_sets_t, reserv_sets_t,
297						reserv_sets_t));
298static void reserv_sets_and            PARAMS ((reserv_sets_t, reserv_sets_t,
299						reserv_sets_t))
300                                            ATTRIBUTE_UNUSED;
301static void output_cycle_reservs       PARAMS ((FILE *, reserv_sets_t,
302						int, int));
303static void output_reserv_sets         PARAMS ((FILE *, reserv_sets_t));
304static state_t get_free_state          PARAMS ((int, automaton_t));
305static void free_state                 PARAMS ((state_t));
306static hashval_t state_hash            PARAMS ((const void *));
307static int state_eq_p                  PARAMS ((const void *, const void *));
308static state_t insert_state            PARAMS ((state_t));
309static void set_state_reserv           PARAMS ((state_t, int, int));
310static int intersected_state_reservs_p PARAMS ((state_t, state_t));
311static state_t states_union            PARAMS ((state_t, state_t));
312static state_t state_shift             PARAMS ((state_t));
313static void initiate_states            PARAMS ((void));
314static void finish_states              PARAMS ((void));
315
316static void free_arc           PARAMS ((arc_t));
317static void remove_arc         PARAMS ((state_t, arc_t));
318static arc_t find_arc          PARAMS ((state_t, state_t, ainsn_t));
319static arc_t add_arc           PARAMS ((state_t, state_t, ainsn_t, int));
320static arc_t first_out_arc     PARAMS ((state_t));
321static arc_t next_out_arc      PARAMS ((arc_t));
322static void initiate_arcs      PARAMS ((void));
323static void finish_arcs        PARAMS ((void));
324
325static automata_list_el_t get_free_automata_list_el PARAMS ((void));
326static void free_automata_list_el PARAMS ((automata_list_el_t));
327static void free_automata_list PARAMS ((automata_list_el_t));
328static hashval_t automata_list_hash PARAMS ((const void *));
329static int automata_list_eq_p PARAMS ((const void *, const void *));
330static void initiate_automata_lists PARAMS ((void));
331static void automata_list_start PARAMS ((void));
332static void automata_list_add PARAMS ((automaton_t));
333static automata_list_el_t automata_list_finish PARAMS ((void));
334static void finish_automata_lists PARAMS ((void));
335
336static void initiate_excl_sets             PARAMS ((void));
337static reserv_sets_t get_excl_set          PARAMS ((reserv_sets_t));
338
339static void initiate_presence_absence_sets     PARAMS ((void));
340static reserv_sets_t get_presence_absence_set  PARAMS ((reserv_sets_t, int));
341
342static regexp_t copy_insn_regexp     PARAMS ((regexp_t));
343static regexp_t transform_1          PARAMS ((regexp_t));
344static regexp_t transform_2          PARAMS ((regexp_t));
345static regexp_t transform_3          PARAMS ((regexp_t));
346static regexp_t regexp_transform_func
347                       PARAMS ((regexp_t, regexp_t (*) (regexp_t)));
348static regexp_t transform_regexp            PARAMS ((regexp_t));
349static void transform_insn_regexps          PARAMS ((void));
350
351static void process_unit_to_form_the_same_automaton_unit_lists
352                                            PARAMS ((regexp_t, regexp_t, int));
353static void form_the_same_automaton_unit_lists_from_regexp PARAMS ((regexp_t));
354static void form_the_same_automaton_unit_lists PARAMS ((void));
355static void check_unit_distributions_to_automata PARAMS ((void));
356
357static int process_seq_for_forming_states   PARAMS ((regexp_t, automaton_t,
358						     int));
359static void finish_forming_alt_state        PARAMS ((alt_state_t,
360						     automaton_t));
361static void process_alts_for_forming_states PARAMS ((regexp_t,
362						     automaton_t, int));
363static void create_alt_states               PARAMS ((automaton_t));
364
365static void form_ainsn_with_same_reservs    PARAMS ((automaton_t));
366
367static void make_automaton           PARAMS ((automaton_t));
368static void form_arcs_marked_by_insn PARAMS ((state_t));
369static void create_composed_state    PARAMS ((state_t, arc_t, vla_ptr_t *));
370static void NDFA_to_DFA              PARAMS ((automaton_t));
371static void pass_state_graph         PARAMS ((state_t, void (*) (state_t)));
372static void pass_states              PARAMS ((automaton_t,
373					      void (*) (state_t)));
374static void initiate_pass_states       PARAMS ((void));
375static void add_achieved_state         PARAMS ((state_t));
376static int set_out_arc_insns_equiv_num PARAMS ((state_t, int));
377static void clear_arc_insns_equiv_num  PARAMS ((state_t));
378static void copy_equiv_class           PARAMS ((vla_ptr_t *to,
379						const vla_ptr_t *from));
380static int state_is_differed           PARAMS ((state_t, int, int));
381static state_t init_equiv_class        PARAMS ((state_t *states, int));
382static int partition_equiv_class       PARAMS ((state_t *, int,
383						vla_ptr_t *, int *));
384static void evaluate_equiv_classes     PARAMS ((automaton_t, vla_ptr_t *));
385static void merge_states               PARAMS ((automaton_t, vla_ptr_t *));
386static void set_new_cycle_flags        PARAMS ((state_t));
387static void minimize_DFA               PARAMS ((automaton_t));
388static void incr_states_and_arcs_nums  PARAMS ((state_t));
389static void count_states_and_arcs      PARAMS ((automaton_t, int *, int *));
390static void build_automaton            PARAMS ((automaton_t));
391
392static void set_order_state_num              PARAMS ((state_t));
393static void enumerate_states                 PARAMS ((automaton_t));
394
395static ainsn_t insert_ainsn_into_equiv_class       PARAMS ((ainsn_t, ainsn_t));
396static void delete_ainsn_from_equiv_class          PARAMS ((ainsn_t));
397static void process_insn_equiv_class               PARAMS ((ainsn_t, arc_t *));
398static void process_state_for_insn_equiv_partition PARAMS ((state_t));
399static void set_insn_equiv_classes                 PARAMS ((automaton_t));
400
401static double estimate_one_automaton_bound     PARAMS ((void));
402static int compare_max_occ_cycle_nums          PARAMS ((const void *,
403							const void *));
404static void units_to_automata_heuristic_distr  PARAMS ((void));
405static ainsn_t create_ainsns                   PARAMS ((void));
406static void units_to_automata_distr            PARAMS ((void));
407static void create_automata                    PARAMS ((void));
408
409static void form_regexp                      PARAMS ((regexp_t));
410static const char *regexp_representation     PARAMS ((regexp_t));
411static void finish_regexp_representation     PARAMS ((void));
412
413static void output_range_type            PARAMS ((FILE *, long int, long int));
414static int longest_path_length           PARAMS ((state_t));
415static void process_state_longest_path_length PARAMS ((state_t));
416static void output_dfa_max_issue_rate    PARAMS ((void));
417static void output_vect                  PARAMS ((vect_el_t *, int));
418static void output_chip_member_name      PARAMS ((FILE *, automaton_t));
419static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t));
420static void output_translate_vect_name   PARAMS ((FILE *, automaton_t));
421static void output_trans_full_vect_name  PARAMS ((FILE *, automaton_t));
422static void output_trans_comb_vect_name  PARAMS ((FILE *, automaton_t));
423static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t));
424static void output_trans_base_vect_name  PARAMS ((FILE *, automaton_t));
425static void output_state_alts_full_vect_name    PARAMS ((FILE *, automaton_t));
426static void output_state_alts_comb_vect_name    PARAMS ((FILE *, automaton_t));
427static void output_state_alts_check_vect_name   PARAMS ((FILE *, automaton_t));
428static void output_state_alts_base_vect_name    PARAMS ((FILE *, automaton_t));
429static void output_min_issue_delay_vect_name    PARAMS ((FILE *, automaton_t));
430static void output_dead_lock_vect_name   PARAMS ((FILE *, automaton_t));
431static void output_reserved_units_table_name    PARAMS ((FILE *, automaton_t));
432static void output_state_member_type     PARAMS ((FILE *, automaton_t));
433static void output_chip_definitions      PARAMS ((void));
434static void output_translate_vect        PARAMS ((automaton_t));
435static int comb_vect_p                   PARAMS ((state_ainsn_table_t));
436static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t));
437static void output_state_ainsn_table
438   PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
439	    void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
440	    void (*) (FILE *, automaton_t)));
441static void add_vect                     PARAMS ((state_ainsn_table_t,
442						  int, vect_el_t *, int));
443static int out_state_arcs_num            PARAMS ((state_t));
444static int compare_transition_els_num    PARAMS ((const void *, const void *));
445static void add_vect_el 	         PARAMS ((vla_hwint_t *,
446						  ainsn_t, int));
447static void add_states_vect_el           PARAMS ((state_t));
448static void output_trans_table           PARAMS ((automaton_t));
449static void output_state_alts_table      PARAMS ((automaton_t));
450static int min_issue_delay_pass_states  PARAMS ((state_t, ainsn_t));
451static int min_issue_delay               PARAMS ((state_t, ainsn_t));
452static void initiate_min_issue_delay_pass_states PARAMS ((void));
453static void output_min_issue_delay_table PARAMS ((automaton_t));
454static void output_dead_lock_vect        PARAMS ((automaton_t));
455static void output_reserved_units_table  PARAMS ((automaton_t));
456static void output_tables                PARAMS ((void));
457static void output_max_insn_queue_index_def PARAMS ((void));
458static void output_insn_code_cases   PARAMS ((void (*) (automata_list_el_t)));
459static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
460static void output_internal_min_issue_delay_func PARAMS ((void));
461static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
462static void output_internal_trans_func   PARAMS ((void));
463static void output_internal_insn_code_evaluation PARAMS ((const char *,
464							  const char *, int));
465static void output_dfa_insn_code_func	        PARAMS ((void));
466static void output_trans_func                   PARAMS ((void));
467static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
468static void output_internal_state_alts_func     PARAMS ((void));
469static void output_state_alts_func              PARAMS ((void));
470static void output_min_issue_delay_func         PARAMS ((void));
471static void output_internal_dead_lock_func      PARAMS ((void));
472static void output_dead_lock_func               PARAMS ((void));
473static void output_internal_reset_func          PARAMS ((void));
474static void output_size_func		        PARAMS ((void));
475static void output_reset_func                   PARAMS ((void));
476static void output_min_insn_conflict_delay_func PARAMS ((void));
477static void output_internal_insn_latency_func   PARAMS ((void));
478static void output_insn_latency_func            PARAMS ((void));
479static void output_print_reservation_func       PARAMS ((void));
480static int units_cmp			        PARAMS ((const void *,
481							 const void *));
482static void output_get_cpu_unit_code_func       PARAMS ((void));
483static void output_cpu_unit_reservation_p       PARAMS ((void));
484static void output_dfa_start_func	        PARAMS ((void));
485static void output_dfa_finish_func	        PARAMS ((void));
486
487static void output_regexp                  PARAMS ((regexp_t ));
488static void output_unit_set_el_list	   PARAMS ((unit_set_el_t));
489static void output_description             PARAMS ((void));
490static void output_automaton_name          PARAMS ((FILE *, automaton_t));
491static void output_automaton_units         PARAMS ((automaton_t));
492static void add_state_reservs              PARAMS ((state_t));
493static void output_state_arcs              PARAMS ((state_t));
494static int state_reservs_cmp               PARAMS ((const void *,
495						    const void *));
496static void remove_state_duplicate_reservs PARAMS ((void));
497static void output_state                   PARAMS ((state_t));
498static void output_automaton_descriptions  PARAMS ((void));
499static void output_statistics              PARAMS ((FILE *));
500static void output_time_statistics         PARAMS ((FILE *));
501static void generate                       PARAMS ((void));
502
503static void make_insn_alts_attr                PARAMS ((void));
504static void make_internal_dfa_insn_code_attr   PARAMS ((void));
505static void make_default_insn_latency_attr     PARAMS ((void));
506static void make_bypass_attr                   PARAMS ((void));
507static const char *file_name_suffix            PARAMS ((const char *));
508static const char *base_file_name              PARAMS ((const char *));
509static void check_automata_insn_issues	       PARAMS ((void));
510static void add_automaton_state                PARAMS ((state_t));
511static void form_important_insn_automata_lists PARAMS ((void));
512
513/* Undefined position.  */
514static pos_t no_pos = 0;
515
516/* All IR is stored in the following obstack.  */
517static struct obstack irp;
518
519
520
521/* This page contains code for work with variable length array (vla)
522   of pointers.  We could be use only varray.  But we add new lay
523   because we add elements very frequently and this could stress OS
524   allocator when varray is used only.  */
525
526/* Start work with vla.  */
527#define VLA_PTR_CREATE(vla, allocated_length, name)                   	\
528  do									\
529    {                                                                	\
530      vla_ptr_t *const vla_ptr = &(vla);                                \
531                                                                      	\
532      VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\
533      vla_ptr->length = 0;                                              \
534    }									\
535  while (0)
536
537/* Finish work with the vla.  */
538#define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
539
540/* Return start address of the vla.  */
541#define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
542
543/* Address of the last element of the vla.  Do not use side effects in
544   the macro argument.  */
545#define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray,         \
546                                                (vla).length - 1))
547/* Nullify the vla.  */
548#define VLA_PTR_NULLIFY(vla)  ((vla).length = 0)
549
550/* Shorten the vla on given number bytes.  */
551#define VLA_PTR_SHORTEN(vla, n)  ((vla).length -= (n))
552
553/* Expand the vla on N elements.  The values of new elements are
554   undefined.  */
555#define VLA_PTR_EXPAND(vla, n)                                        \
556  do {                                                                \
557    vla_ptr_t *const expand_vla_ptr = &(vla);                         \
558    const size_t new_length = (n) + expand_vla_ptr->length;           \
559                                                                      \
560    if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length)            \
561      VARRAY_GROW (expand_vla_ptr->varray,                            \
562                   (new_length - expand_vla_ptr->length < 128         \
563                    ? expand_vla_ptr->length + 128 : new_length));    \
564    expand_vla_ptr->length = new_length;                              \
565  } while (0)
566
567/* Add element to the end of the vla.  */
568#define VLA_PTR_ADD(vla, ptr)                                         \
569  do {                                                                \
570    vla_ptr_t *const vla_ptr = &(vla);                                \
571                                                                      \
572    VLA_PTR_EXPAND (*vla_ptr, 1);                                     \
573    VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\
574  } while (0)
575
576/* Length of the vla in elements.  */
577#define VLA_PTR_LENGTH(vla) ((vla).length)
578
579/* N-th element of the vla.  */
580#define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
581
582
583/* The following macros are analogous to the previous ones but for
584   VLAs of HOST WIDE INTs.  */
585
586#define VLA_HWINT_CREATE(vla, allocated_length, name)                 \
587  do {                                                                \
588    vla_hwint_t *const vla_ptr = &(vla);                              \
589                                                                      \
590    VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name);   \
591    vla_ptr->length = 0;                                              \
592  } while (0)
593
594#define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
595
596#define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
597
598#define VLA_HWINT_NULLIFY(vla)  ((vla).length = 0)
599
600#define VLA_HWINT_EXPAND(vla, n)                                      \
601  do {                                                                \
602    vla_hwint_t *const expand_vla_ptr = &(vla);                       \
603    const size_t new_length = (n) + expand_vla_ptr->length;           \
604                                                                      \
605    if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length)            \
606      VARRAY_GROW (expand_vla_ptr->varray,                            \
607                   (new_length - expand_vla_ptr->length < 128         \
608                    ? expand_vla_ptr->length + 128 : new_length));    \
609    expand_vla_ptr->length = new_length;                              \
610  } while (0)
611
612#define VLA_HWINT_ADD(vla, ptr)                                       \
613  do {                                                                \
614    vla_hwint_t *const vla_ptr = &(vla);                              \
615                                                                      \
616    VLA_HWINT_EXPAND (*vla_ptr, 1);                                   \
617    VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr);   \
618  } while (0)
619
620#define VLA_HWINT_LENGTH(vla) ((vla).length)
621
622#define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
623
624
625
626/* Options with the following names can be set up in automata_option
627   construction.  Because the strings occur more one time we use the
628   macros.  */
629
630#define NO_MINIMIZATION_OPTION "-no-minimization"
631
632#define TIME_OPTION "-time"
633
634#define V_OPTION "-v"
635
636#define W_OPTION "-w"
637
638#define NDFA_OPTION "-ndfa"
639
640/* The following flags are set up by function `initiate_automaton_gen'.  */
641
642/* Make automata with nondeterministic reservation by insns (`-ndfa').  */
643static int ndfa_flag;
644
645/* Do not make minimization of DFA (`-no-minimization').  */
646static int no_minimization_flag;
647
648/* Value of this variable is number of automata being generated.  The
649   actual number of automata may be less this value if there is not
650   sufficient number of units.  This value is defined by argument of
651   option `-split' or by constructions automaton if the value is zero
652   (it is default value of the argument).  */
653static int split_argument;
654
655/* Flag of output time statistics (`-time').  */
656static int time_flag;
657
658/* Flag of creation of description file which contains description of
659   result automaton and statistics information (`-v').  */
660static int v_flag;
661
662/* Flag of generating warning instead of error for non-critical errors
663   (`-w').  */
664static int w_flag;
665
666
667/* Output file for pipeline hazard recognizer (PHR) being generated.
668   The value is NULL if the file is not defined.  */
669static FILE *output_file;
670
671/* Description file of PHR.  The value is NULL if the file is not
672   created.  */
673static FILE *output_description_file;
674
675/* PHR description file name.  */
676static char *output_description_file_name;
677
678/* Value of the following variable is node representing description
679   being processed.  This is start point of IR.  */
680static struct description *description;
681
682
683
684/* This page contains description of IR structure (nodes).  */
685
686enum decl_mode
687{
688  dm_unit,
689  dm_bypass,
690  dm_automaton,
691  dm_excl,
692  dm_presence,
693  dm_absence,
694  dm_reserv,
695  dm_insn_reserv
696};
697
698/* This describes define_cpu_unit and define_query_cpu_unit (see file
699   rtl.def).  */
700struct unit_decl
701{
702  char *name;
703  /* NULL if the automaton name is absent.  */
704  char *automaton_name;
705  /* If the following value is not zero, the cpu unit reservation is
706     described in define_query_cpu_unit.  */
707  char query_p;
708
709  /* The following fields are defined by checker.  */
710
711  /* The following field value is nonzero if the unit is used in an
712     regexp.  */
713  char unit_is_used;
714
715  /* The following field value is used to form cyclic lists of units
716     which should be in the same automaton because the unit is
717     reserved not on all alternatives of a regexp on a cycle.  */
718  unit_decl_t the_same_automaton_unit;
719  /* The following field is TRUE if we already reported that the unit
720     is not in the same automaton.  */
721  int the_same_automaton_message_reported_p;
722
723  /* The following field value is order number (0, 1, ...) of given
724     unit.  */
725  int unit_num;
726  /* The following field value is corresponding declaration of
727     automaton which was given in description.  If the field value is
728     NULL then automaton in the unit declaration was absent.  */
729  struct automaton_decl *automaton_decl;
730  /* The following field value is maximal cycle number (1, ...) on
731     which given unit occurs in insns.  Zero value means that given
732     unit is not used in insns.  */
733  int max_occ_cycle_num;
734  /* The following list contains units which conflict with given
735     unit.  */
736  unit_set_el_t excl_list;
737  /* The following list contains units which are required to
738     reservation of given unit.  */
739  unit_set_el_t presence_list;
740  /* The following list contains units which should be not present in
741     reservation for given unit.  */
742  unit_set_el_t absence_list;
743  /* The following is used only when `query_p' has nonzero value.
744     This is query number for the unit.  */
745  int query_num;
746
747  /* The following fields are defined by automaton generator.  */
748
749  /* The following field value is number of the automaton to which
750     given unit belongs.  */
751  int corresponding_automaton_num;
752};
753
754/* This describes define_bypass (see file rtl.def).  */
755struct bypass_decl
756{
757  int latency;
758  char *out_insn_name;
759  char *in_insn_name;
760  char *bypass_guard_name;
761
762  /* The following fields are defined by checker.  */
763
764  /* output and input insns of given bypass.  */
765  struct insn_reserv_decl *out_insn_reserv;
766  struct insn_reserv_decl *in_insn_reserv;
767  /* The next bypass for given output insn.  */
768  struct bypass_decl *next;
769};
770
771/* This describes define_automaton (see file rtl.def).  */
772struct automaton_decl
773{
774  char *name;
775
776  /* The following fields are defined by automaton generator.  */
777
778  /* The following field value is nonzero if the automaton is used in
779     an regexp definition.  */
780  char automaton_is_used;
781
782  /* The following fields are defined by checker.  */
783
784  /* The following field value is the corresponding automaton.  This
785     field is not NULL only if the automaton is present in unit
786     declarations and the automatic partition on automata is not
787     used.  */
788  automaton_t corresponding_automaton;
789};
790
791/* This describes unit relations: exclusion_set, presence_set, or
792   absence_set (see file rtl.def).  */
793struct unit_rel_decl
794{
795  int names_num;
796  int first_list_length;
797  char *names [1];
798};
799
800/* This describes define_reservation (see file rtl.def).  */
801struct reserv_decl
802{
803  char *name;
804  regexp_t regexp;
805
806  /* The following fields are defined by checker.  */
807
808  /* The following field value is nonzero if the unit is used in an
809     regexp.  */
810  char reserv_is_used;
811  /* The following field is used to check up cycle in expression
812     definition.  */
813  int loop_pass_num;
814};
815
816/* This describes define_insn_reservartion (see file rtl.def).  */
817struct insn_reserv_decl
818{
819  rtx condexp;
820  int default_latency;
821  regexp_t regexp;
822  char *name;
823
824  /* The following fields are defined by checker.  */
825
826  /* The following field value is order number (0, 1, ...) of given
827     insn.  */
828  int insn_num;
829  /* The following field value is list of bypasses in which given insn
830     is output insn.  */
831  struct bypass_decl *bypass_list;
832
833  /* The following fields are defined by automaton generator.  */
834
835  /* The following field is the insn regexp transformed that
836     the regexp has not optional regexp, repetition regexp, and an
837     reservation name (i.e. reservation identifiers are changed by the
838     corresponding regexp) and all alternations are the topest level
839     of the regexp.  The value can be NULL only if it is special
840     insn `cycle advancing'.  */
841  regexp_t transformed_regexp;
842  /* The following field value is list of arcs marked given
843     insn.  The field is used in transfromation NDFA -> DFA.  */
844  arc_t arcs_marked_by_insn;
845  /* The two following fields are used during minimization of a finite state
846     automaton.  */
847  /* The field value is number of equivalence class of state into
848     which arc marked by given insn enters from a state (fixed during
849     an automaton minimization).  */
850  int equiv_class_num;
851  /* The field value is state_alts of arc leaving a state (fixed
852     during an automaton minimization) and marked by given insn
853     enters.  */
854  int state_alts;
855  /* The following member value is the list to automata which can be
856     changed by the insn issue.  */
857  automata_list_el_t important_automata_list;
858  /* The following member is used to process insn once for output.  */
859  int processed_p;
860};
861
862/* This contains a declaration mentioned above.  */
863struct decl
864{
865  /* What node in the union? */
866  enum decl_mode mode;
867  pos_t pos;
868  union
869  {
870    struct unit_decl unit;
871    struct bypass_decl bypass;
872    struct automaton_decl automaton;
873    struct unit_rel_decl excl;
874    struct unit_rel_decl presence;
875    struct unit_rel_decl absence;
876    struct reserv_decl reserv;
877    struct insn_reserv_decl insn_reserv;
878  } decl;
879};
880
881/* The following structures represent parsed reservation strings.  */
882enum regexp_mode
883{
884  rm_unit,
885  rm_reserv,
886  rm_nothing,
887  rm_sequence,
888  rm_repeat,
889  rm_allof,
890  rm_oneof
891};
892
893/* Cpu unit in reservation.  */
894struct unit_regexp
895{
896  char *name;
897  unit_decl_t unit_decl;
898};
899
900/* Define_reservation in a reservation.  */
901struct reserv_regexp
902{
903  char *name;
904  struct reserv_decl *reserv_decl;
905};
906
907/* Absence of reservation (represented by string `nothing').  */
908struct nothing_regexp
909{
910  /* This used to be empty but ISO C doesn't allow that.  */
911  char unused;
912};
913
914/* Representation of reservations separated by ',' (see file
915   rtl.def).  */
916struct sequence_regexp
917{
918  int regexps_num;
919  regexp_t regexps [1];
920};
921
922/* Representation of construction `repeat' (see file rtl.def).  */
923struct repeat_regexp
924{
925  int repeat_num;
926  regexp_t regexp;
927};
928
929/* Representation of reservations separated by '+' (see file
930   rtl.def).  */
931struct allof_regexp
932{
933  int regexps_num;
934  regexp_t regexps [1];
935};
936
937/* Representation of reservations separated by '|' (see file
938   rtl.def).  */
939struct oneof_regexp
940{
941  int regexps_num;
942  regexp_t regexps [1];
943};
944
945/* Representation of a reservation string.  */
946struct regexp
947{
948  /* What node in the union? */
949  enum regexp_mode mode;
950  pos_t pos;
951  union
952  {
953    struct unit_regexp unit;
954    struct reserv_regexp reserv;
955    struct nothing_regexp nothing;
956    struct sequence_regexp sequence;
957    struct repeat_regexp repeat;
958    struct allof_regexp allof;
959    struct oneof_regexp oneof;
960  } regexp;
961};
962
963/* Reperesents description of pipeline hazard description based on
964   NDFA.  */
965struct description
966{
967  int decls_num;
968
969  /* The following fields are defined by checker.  */
970
971  /* The following fields values are correspondingly number of all
972     units, query units, and insns in the description.  */
973  int units_num;
974  int query_units_num;
975  int insns_num;
976  /* The following field value is max length (in cycles) of
977     reservations of insns.  The field value is defined only for
978     correct programs.  */
979  int max_insn_reserv_cycles;
980
981  /* The following fields are defined by automaton generator.  */
982
983  /* The following field value is the first automaton.  */
984  automaton_t first_automaton;
985
986  /* The following field is created by pipeline hazard parser and
987     contains all declarations.  We allocate additional entry for
988     special insn "cycle advancing" which is added by the automaton
989     generator.  */
990  decl_t decls [1];
991};
992
993
994
995/* The following nodes are created in automaton checker.  */
996
997/* The following nodes represent exclusion, presence, absence set for
998   cpu units.  Each element are accessed through only one excl_list,
999   presence_list, absence_list.  */
1000struct unit_set_el
1001{
1002  unit_decl_t unit_decl;
1003  unit_set_el_t next_unit_set_el;
1004};
1005
1006
1007
1008/* The following nodes are created in automaton generator.  */
1009
1010/* The following node type describes state automaton.  The state may
1011   be deterministic or non-deterministic.  Non-deterministic state has
1012   several component states which represent alternative cpu units
1013   reservations.  The state also is used for describing a
1014   deterministic reservation of automaton insn.  */
1015struct state
1016{
1017  /* The following member value is nonzero if there is a transition by
1018     cycle advancing.  */
1019  int new_cycle_p;
1020  /* The following field is list of processor unit reservations on
1021     each cycle.  */
1022  reserv_sets_t reservs;
1023  /* The following field is unique number of given state between other
1024     states.  */
1025  int unique_num;
1026  /* The following field value is automaton to which given state
1027     belongs.  */
1028  automaton_t automaton;
1029  /* The following field value is the first arc output from given
1030     state.  */
1031  arc_t first_out_arc;
1032  /* The following field is used to form NDFA.  */
1033  char it_was_placed_in_stack_for_NDFA_forming;
1034  /* The following field is used to form DFA.  */
1035  char it_was_placed_in_stack_for_DFA_forming;
1036  /* The following field is used to transform NDFA to DFA.  The field
1037     value is not NULL if the state is a compound state.  In this case
1038     the value of field `unit_sets_list' is NULL.  All states in the
1039     list are in the hash table.  The list is formed through field
1040     `next_sorted_alt_state'.  */
1041  alt_state_t component_states;
1042  /* The following field is used for passing graph of states.  */
1043  int pass_num;
1044  /* The list of states belonging to one equivalence class is formed
1045     with the aid of the following field.  */
1046  state_t next_equiv_class_state;
1047  /* The two following fields are used during minimization of a finite
1048     state automaton.  */
1049  int equiv_class_num_1, equiv_class_num_2;
1050  /* The following field is used during minimization of a finite state
1051     automaton.  The field value is state corresponding to equivalence
1052     class to which given state belongs.  */
1053  state_t equiv_class_state;
1054  /* The following field value is the order number of given state.
1055     The states in final DFA is enumerated with the aid of the
1056     following field.  */
1057  int order_state_num;
1058  /* This member is used for passing states for searching minimal
1059     delay time.  */
1060  int state_pass_num;
1061  /* The following member is used to evaluate min issue delay of insn
1062     for a state.  */
1063  int min_insn_issue_delay;
1064  /* The following member is used to evaluate max issue rate of the
1065     processor.  The value of the member is maximal length of the path
1066     from given state no containing arcs marked by special insn `cycle
1067     advancing'.  */
1068  int longest_path_length;
1069};
1070
1071/* The following macro is an initial value of member
1072   `longest_path_length' of a state.  */
1073#define UNDEFINED_LONGEST_PATH_LENGTH -1
1074
1075/* Automaton arc.  */
1076struct arc
1077{
1078  /* The following field refers for the state into which given arc
1079     enters.  */
1080  state_t to_state;
1081  /* The following field describes that the insn issue (with cycle
1082     advancing for special insn `cycle advancing' and without cycle
1083     advancing for others) makes transition from given state to
1084     another given state.  */
1085  ainsn_t insn;
1086  /* The following field value is the next arc output from the same
1087     state.  */
1088  arc_t next_out_arc;
1089  /* List of arcs marked given insn is formed with the following
1090     field.  The field is used in transfromation NDFA -> DFA.  */
1091  arc_t next_arc_marked_by_insn;
1092  /* The following field is defined if NDFA_FLAG is zero.  The member
1093     value is number of alternative reservations which can be used for
1094     transition for given state by given insn.  */
1095  int state_alts;
1096};
1097
1098/* The following node type describes a deterministic alternative in
1099   non-deterministic state which characterizes cpu unit reservations
1100   of automaton insn or which is part of NDFA.  */
1101struct alt_state
1102{
1103  /* The following field is a determinist state which characterizes
1104     unit reservations of the instruction.  */
1105  state_t state;
1106  /* The following field refers to the next state which characterizes
1107     unit reservations of the instruction.  */
1108  alt_state_t next_alt_state;
1109  /* The following field refers to the next state in sorted list.  */
1110  alt_state_t next_sorted_alt_state;
1111};
1112
1113/* The following node type describes insn of automaton.  They are
1114   labels of FA arcs.  */
1115struct ainsn
1116{
1117  /* The following field value is the corresponding insn declaration
1118     of description.  */
1119  struct insn_reserv_decl *insn_reserv_decl;
1120  /* The following field value is the next insn declaration for an
1121     automaton.  */
1122  ainsn_t next_ainsn;
1123  /* The following field is states which characterize automaton unit
1124     reservations of the instruction.  The value can be NULL only if it
1125     is special insn `cycle advancing'.  */
1126  alt_state_t alt_states;
1127  /* The following field is sorted list of states which characterize
1128     automaton unit reservations of the instruction.  The value can be
1129     NULL only if it is special insn `cycle advancing'.  */
1130  alt_state_t sorted_alt_states;
1131  /* The following field refers the next automaton insn with
1132     the same reservations.  */
1133  ainsn_t next_same_reservs_insn;
1134  /* The following field is flag of the first automaton insn with the
1135     same reservations in the declaration list.  Only arcs marked such
1136     insn is present in the automaton.  This significantly decreases
1137     memory requirements especially when several automata are
1138     formed.  */
1139  char first_insn_with_same_reservs;
1140  /* The following member has nonzero value if there is arc from state of
1141     the automaton marked by the ainsn.  */
1142  char arc_exists_p;
1143  /* Cyclic list of insns of an equivalence class is formed with the
1144     aid of the following field.  */
1145  ainsn_t next_equiv_class_insn;
1146  /* The following field value is nonzero if the insn declaration is
1147     the first insn declaration with given equivalence number.  */
1148  char first_ainsn_with_given_equialence_num;
1149  /* The following field is number of class of equivalence of insns.
1150     It is necessary because many insns may be equivalent with the
1151     point of view of pipeline hazards.  */
1152  int insn_equiv_class_num;
1153  /* The following member value is TRUE if there is an arc in the
1154     automaton marked by the insn into another state.  In other
1155     words, the insn can change the state of the automaton.  */
1156  int important_p;
1157};
1158
1159/* The folowing describes an automaton for PHR.  */
1160struct automaton
1161{
1162  /* The following field value is the list of insn declarations for
1163     given automaton.  */
1164  ainsn_t ainsn_list;
1165  /* The following field value is the corresponding automaton
1166     declaration.  This field is not NULL only if the automatic
1167     partition on automata is not used.  */
1168  struct automaton_decl *corresponding_automaton_decl;
1169  /* The following field value is the next automaton.  */
1170  automaton_t next_automaton;
1171  /* The following field is start state of FA.  There are not unit
1172     reservations in the state.  */
1173  state_t start_state;
1174  /* The following field value is number of equivalence classes of
1175     insns (see field `insn_equiv_class_num' in
1176     `insn_reserv_decl').  */
1177  int insn_equiv_classes_num;
1178  /* The following field value is number of states of final DFA.  */
1179  int achieved_states_num;
1180  /* The following field value is the order number (0, 1, ...) of
1181     given automaton.  */
1182  int automaton_order_num;
1183  /* The following fields contain statistics information about
1184     building automaton.  */
1185  int NDFA_states_num, DFA_states_num;
1186  /* The following field value is defined only if minimization of DFA
1187     is used.  */
1188  int minimal_DFA_states_num;
1189  int NDFA_arcs_num, DFA_arcs_num;
1190  /* The following field value is defined only if minimization of DFA
1191     is used.  */
1192  int minimal_DFA_arcs_num;
1193  /* The following two members refer for two table state x ainsn ->
1194     int.  */
1195  state_ainsn_table_t trans_table;
1196  state_ainsn_table_t state_alts_table;
1197  /* The following member value is maximal value of min issue delay
1198     for insns of the automaton.  */
1199  int max_min_delay;
1200  /* Usually min issue delay is small and we can place several (2, 4,
1201     8) elements in one vector element.  So the compression factor can
1202     be 1 (no compression), 2, 4, 8.  */
1203  int min_issue_delay_table_compression_factor;
1204};
1205
1206/* The following is the element of the list of automata.  */
1207struct automata_list_el
1208{
1209  /* The automaton itself.  */
1210  automaton_t automaton;
1211  /* The next automata set element.  */
1212  automata_list_el_t next_automata_list_el;
1213};
1214
1215/* The following structure describes a table state X ainsn -> int(>= 0).  */
1216struct state_ainsn_table
1217{
1218  /* Automaton to which given table belongs.  */
1219  automaton_t automaton;
1220  /* The following tree vectors for comb vector implementation of the
1221     table.  */
1222  vla_hwint_t comb_vect;
1223  vla_hwint_t check_vect;
1224  vla_hwint_t base_vect;
1225  /* This is simple implementation of the table.  */
1226  vla_hwint_t full_vect;
1227  /* Minimal and maximal values of the previous vectors.  */
1228  int min_comb_vect_el_value, max_comb_vect_el_value;
1229  int min_base_vect_el_value, max_base_vect_el_value;
1230};
1231
1232/* Macros to access members of unions.  Use only them for access to
1233   union members of declarations and regexps.  */
1234
1235#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
1236
1237#define DECL_UNIT(d) __extension__					\
1238(({ struct decl *const _decl = (d);					\
1239     if (_decl->mode != dm_unit)					\
1240       decl_mode_check_failed (_decl->mode, "dm_unit",			\
1241			       __FILE__, __LINE__, __FUNCTION__);	\
1242     &(_decl)->decl.unit; }))
1243
1244#define DECL_BYPASS(d) __extension__					\
1245(({ struct decl *const _decl = (d);					\
1246     if (_decl->mode != dm_bypass)					\
1247       decl_mode_check_failed (_decl->mode, "dm_bypass",		\
1248			       __FILE__, __LINE__, __FUNCTION__);	\
1249     &(_decl)->decl.bypass; }))
1250
1251#define DECL_AUTOMATON(d) __extension__					\
1252(({ struct decl *const _decl = (d);				       	\
1253     if (_decl->mode != dm_automaton)					\
1254       decl_mode_check_failed (_decl->mode, "dm_automaton",		\
1255			       __FILE__, __LINE__, __FUNCTION__);	\
1256     &(_decl)->decl.automaton; }))
1257
1258#define DECL_EXCL(d) __extension__					\
1259(({ struct decl *const _decl = (d);				       	\
1260     if (_decl->mode != dm_excl)					\
1261       decl_mode_check_failed (_decl->mode, "dm_excl",			\
1262			       __FILE__, __LINE__, __FUNCTION__);	\
1263     &(_decl)->decl.excl; }))
1264
1265#define DECL_PRESENCE(d) __extension__					\
1266(({ struct decl *const _decl = (d);					\
1267     if (_decl->mode != dm_presence)					\
1268       decl_mode_check_failed (_decl->mode, "dm_presence",		\
1269			       __FILE__, __LINE__, __FUNCTION__);	\
1270     &(_decl)->decl.presence; }))
1271
1272#define DECL_ABSENCE(d) __extension__					\
1273(({ struct decl *const _decl = (d);				       	\
1274     if (_decl->mode != dm_absence)					\
1275       decl_mode_check_failed (_decl->mode, "dm_absence",		\
1276			       __FILE__, __LINE__, __FUNCTION__);	\
1277     &(_decl)->decl.absence; }))
1278
1279#define DECL_RESERV(d) __extension__					\
1280(({ struct decl *const _decl = (d);					\
1281     if (_decl->mode != dm_reserv)					\
1282       decl_mode_check_failed (_decl->mode, "dm_reserv",		\
1283			       __FILE__, __LINE__, __FUNCTION__);	\
1284     &(_decl)->decl.reserv; }))
1285
1286#define DECL_INSN_RESERV(d) __extension__				\
1287(({ struct decl *const _decl = (d);				       	\
1288     if (_decl->mode != dm_insn_reserv)					\
1289       decl_mode_check_failed (_decl->mode, "dm_insn_reserv",		\
1290			       __FILE__, __LINE__, __FUNCTION__);	\
1291     &(_decl)->decl.insn_reserv; }))
1292
1293static const char *decl_name PARAMS ((enum decl_mode));
1294static void decl_mode_check_failed PARAMS ((enum decl_mode, const char *,
1295					    const char *, int, const char *));
1296
1297/* Return string representation of declaration mode MODE.  */
1298static const char *
1299decl_name (mode)
1300     enum decl_mode mode;
1301{
1302  static char str [100];
1303
1304  if (mode == dm_unit)
1305    return "dm_unit";
1306  else if (mode == dm_bypass)
1307    return "dm_bypass";
1308  else if (mode == dm_automaton)
1309    return "dm_automaton";
1310  else if (mode == dm_excl)
1311    return "dm_excl";
1312  else if (mode == dm_presence)
1313    return "dm_presence";
1314  else if (mode == dm_absence)
1315    return "dm_absence";
1316  else if (mode == dm_reserv)
1317    return "dm_reserv";
1318  else if (mode == dm_insn_reserv)
1319    return "dm_insn_reserv";
1320  else
1321    sprintf (str, "unknown (%d)", (int) mode);
1322  return str;
1323}
1324
1325/* The function prints message about unexpected declaration and finish
1326   the program.  */
1327static void
1328decl_mode_check_failed (mode, expected_mode_str, file, line, func)
1329     enum decl_mode mode;
1330     const char *expected_mode_str;
1331     const char *file;
1332     int line;
1333     const char *func;
1334{
1335  fprintf
1336    (stderr,
1337     "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
1338     file, line, func, expected_mode_str, decl_name (mode));
1339  exit (1);
1340}
1341
1342
1343#define REGEXP_UNIT(r) __extension__					\
1344(({ struct regexp *const _regexp = (r);					\
1345     if (_regexp->mode != rm_unit)					\
1346       regexp_mode_check_failed (_regexp->mode, "rm_unit",		\
1347			       __FILE__, __LINE__, __FUNCTION__);	\
1348     &(_regexp)->regexp.unit; }))
1349
1350#define REGEXP_RESERV(r) __extension__					\
1351(({ struct regexp *const _regexp = (r);					\
1352     if (_regexp->mode != rm_reserv)					\
1353       regexp_mode_check_failed (_regexp->mode, "rm_reserv",		\
1354			       __FILE__, __LINE__, __FUNCTION__);	\
1355     &(_regexp)->regexp.reserv; }))
1356
1357#define REGEXP_SEQUENCE(r) __extension__				\
1358(({ struct regexp *const _regexp = (r);					\
1359     if (_regexp->mode != rm_sequence)					\
1360       regexp_mode_check_failed (_regexp->mode, "rm_sequence",		\
1361			       __FILE__, __LINE__, __FUNCTION__);	\
1362     &(_regexp)->regexp.sequence; }))
1363
1364#define REGEXP_REPEAT(r) __extension__					\
1365(({ struct regexp *const _regexp = (r);					\
1366     if (_regexp->mode != rm_repeat)					\
1367       regexp_mode_check_failed (_regexp->mode, "rm_repeat",		\
1368			       __FILE__, __LINE__, __FUNCTION__);	\
1369     &(_regexp)->regexp.repeat; }))
1370
1371#define REGEXP_ALLOF(r) __extension__					\
1372(({ struct regexp *const _regexp = (r);					\
1373     if (_regexp->mode != rm_allof)					\
1374       regexp_mode_check_failed (_regexp->mode, "rm_allof",		\
1375			       __FILE__, __LINE__, __FUNCTION__);	\
1376     &(_regexp)->regexp.allof; }))
1377
1378#define REGEXP_ONEOF(r) __extension__					\
1379(({ struct regexp *const _regexp = (r);					\
1380     if (_regexp->mode != rm_oneof)					\
1381       regexp_mode_check_failed (_regexp->mode, "rm_oneof",		\
1382			       __FILE__, __LINE__, __FUNCTION__);	\
1383     &(_regexp)->regexp.oneof; }))
1384
1385static const char *regexp_name PARAMS ((enum regexp_mode));
1386static void regexp_mode_check_failed PARAMS ((enum regexp_mode, const char *,
1387					      const char *, int,
1388					      const char *));
1389
1390
1391/* Return string representation of regexp mode MODE.  */
1392static const char *
1393regexp_name (mode)
1394     enum regexp_mode mode;
1395{
1396  static char str [100];
1397
1398  if (mode == rm_unit)
1399    return "rm_unit";
1400  else if (mode == rm_reserv)
1401    return "rm_reserv";
1402  else if (mode == rm_nothing)
1403    return "rm_nothing";
1404  else if (mode == rm_sequence)
1405    return "rm_sequence";
1406  else if (mode == rm_repeat)
1407    return "rm_repeat";
1408  else if (mode == rm_allof)
1409    return "rm_allof";
1410  else if (mode == rm_oneof)
1411    return "rm_oneof";
1412  else
1413    sprintf (str, "unknown (%d)", (int) mode);
1414  return str;
1415}
1416
1417/* The function prints message about unexpected regexp and finish the
1418   program.  */
1419static void
1420regexp_mode_check_failed (mode, expected_mode_str, file, line, func)
1421     enum regexp_mode mode;
1422     const char *expected_mode_str;
1423     const char *file;
1424     int line;
1425     const char *func;
1426{
1427  fprintf
1428    (stderr,
1429     "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1430     file, line, func, expected_mode_str, regexp_name (mode));
1431  exit (1);
1432}
1433
1434#else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1435
1436#define DECL_UNIT(d) (&(d)->decl.unit)
1437#define DECL_BYPASS(d) (&(d)->decl.bypass)
1438#define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1439#define DECL_EXCL(d) (&(d)->decl.excl)
1440#define DECL_PRESENCE(d) (&(d)->decl.presence)
1441#define DECL_ABSENCE(d) (&(d)->decl.absence)
1442#define DECL_RESERV(d) (&(d)->decl.reserv)
1443#define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1444
1445#define REGEXP_UNIT(r) (&(r)->regexp.unit)
1446#define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1447#define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1448#define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1449#define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1450#define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1451
1452#endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1453
1454/* Create IR structure (node).  */
1455static void *
1456create_node (size)
1457     size_t size;
1458{
1459  void *result;
1460
1461  obstack_blank (&irp, size);
1462  result = obstack_base (&irp);
1463  obstack_finish (&irp);
1464  /* Default values of members are NULL and zero.  */
1465  memset (result, 0, size);
1466  return result;
1467}
1468
1469/* Copy IR structure (node).  */
1470static void *
1471copy_node (from, size)
1472     const void *from;
1473     size_t size;
1474{
1475  void *const result = create_node (size);
1476  memcpy (result, from, size);
1477  return result;
1478}
1479
1480/* The function checks that NAME does not contain quotes (`"').  */
1481static char *
1482check_name (name, pos)
1483     char * name;
1484     pos_t pos ATTRIBUTE_UNUSED;
1485{
1486  const char *str;
1487
1488  for (str = name; *str != '\0'; str++)
1489    if (*str == '\"')
1490      error ("Name `%s' contains quotes", name);
1491  return name;
1492}
1493
1494/* Pointers top all declartions during IR generation are stored in the
1495   following.  */
1496static vla_ptr_t decls;
1497
1498/* Given a pointer to a (char *) and a separator, return an alloc'ed
1499   string containing the next separated element, taking parentheses
1500   into account if PAR_FLAG has nonzero value.  Advance the pointer to
1501   after the string scanned, or the end-of-string.  Return NULL if at
1502   end of string.  */
1503static char *
1504next_sep_el (pstr, sep, par_flag)
1505     char **pstr;
1506     int sep;
1507     int par_flag;
1508{
1509  char *out_str;
1510  char *p;
1511  int pars_num;
1512  int n_spaces;
1513
1514  /* Remove leading whitespaces.  */
1515  while (ISSPACE ((int) **pstr))
1516    (*pstr)++;
1517
1518  if (**pstr == '\0')
1519    return NULL;
1520
1521  n_spaces = 0;
1522  for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1523    {
1524      if (par_flag && *p == '(')
1525	pars_num++;
1526      else if (par_flag && *p == ')')
1527	pars_num--;
1528      else if (pars_num == 0 && *p == sep)
1529	break;
1530      if (pars_num == 0 && ISSPACE ((int) *p))
1531	n_spaces++;
1532      else
1533	{
1534	  for (; n_spaces != 0; n_spaces--)
1535	    obstack_1grow (&irp, p [-n_spaces]);
1536	  obstack_1grow (&irp, *p);
1537	}
1538    }
1539  obstack_1grow (&irp, '\0');
1540  out_str = obstack_base (&irp);
1541  obstack_finish (&irp);
1542
1543  *pstr = p;
1544  if (**pstr == sep)
1545    (*pstr)++;
1546
1547  return out_str;
1548}
1549
1550/* Given a string and a separator, return the number of separated
1551   elements in it, taking parentheses into account if PAR_FLAG has
1552   nonzero value.  Return 0 for the null string, -1 if parantheses is
1553   not balanced.  */
1554static int
1555n_sep_els (s, sep, par_flag)
1556     char *s;
1557     int sep;
1558     int par_flag;
1559{
1560  int n;
1561  int pars_num;
1562
1563  if (*s == '\0')
1564    return 0;
1565
1566  for (pars_num = 0, n = 1; *s; s++)
1567    if (par_flag && *s == '(')
1568      pars_num++;
1569    else if (par_flag && *s == ')')
1570      pars_num--;
1571    else if (pars_num == 0 && *s == sep)
1572      n++;
1573
1574  return (pars_num != 0 ? -1 : n);
1575}
1576
1577/* Given a string and a separator, return vector of strings which are
1578   elements in the string and number of elements through els_num.
1579   Take parentheses into account if PAR_FLAG has nonzero value.
1580   Return 0 for the null string, -1 if parantheses are not balanced.  */
1581static char **
1582get_str_vect (str, els_num, sep, par_flag)
1583     char *str;
1584     int *els_num;
1585     int sep;
1586     int par_flag;
1587{
1588  int i;
1589  char **vect;
1590  char **pstr;
1591
1592  *els_num = n_sep_els (str, sep, par_flag);
1593  if (*els_num <= 0)
1594    return NULL;
1595  obstack_blank (&irp, sizeof (char *) * (*els_num));
1596  vect = (char **) obstack_base (&irp);
1597  obstack_finish (&irp);
1598  pstr = &str;
1599  for (i = 0; i < *els_num; i++)
1600    vect [i] = next_sep_el (pstr, sep, par_flag);
1601  if (next_sep_el (pstr, sep, par_flag) != NULL)
1602    abort ();
1603  return vect;
1604}
1605
1606/* Process a DEFINE_CPU_UNIT.
1607
1608   This gives information about a unit contained in CPU.  We fill a
1609   struct unit_decl with information used later by `expand_automata'.  */
1610void
1611gen_cpu_unit (def)
1612     rtx def;
1613{
1614  decl_t decl;
1615  char **str_cpu_units;
1616  int vect_length;
1617  int i;
1618
1619  str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1620  if (str_cpu_units == NULL)
1621    fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1622  for (i = 0; i < vect_length; i++)
1623    {
1624      decl = create_node (sizeof (struct decl));
1625      decl->mode = dm_unit;
1626      decl->pos = 0;
1627      DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1628      DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1629      DECL_UNIT (decl)->query_p = 0;
1630      VLA_PTR_ADD (decls, decl);
1631      num_dfa_decls++;
1632    }
1633}
1634
1635/* Process a DEFINE_QUERY_CPU_UNIT.
1636
1637   This gives information about a unit contained in CPU.  We fill a
1638   struct unit_decl with information used later by `expand_automata'.  */
1639void
1640gen_query_cpu_unit (def)
1641     rtx def;
1642{
1643  decl_t decl;
1644  char **str_cpu_units;
1645  int vect_length;
1646  int i;
1647
1648  str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1649  if (str_cpu_units == NULL)
1650    fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1651  for (i = 0; i < vect_length; i++)
1652    {
1653      decl = create_node (sizeof (struct decl));
1654      decl->mode = dm_unit;
1655      decl->pos = 0;
1656      DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1657      DECL_UNIT (decl)->automaton_name = (char *) XSTR (def, 1);
1658      DECL_UNIT (decl)->query_p = 1;
1659      VLA_PTR_ADD (decls, decl);
1660      num_dfa_decls++;
1661    }
1662}
1663
1664/* Process a DEFINE_BYPASS.
1665
1666   This gives information about a unit contained in the CPU.  We fill
1667   in a struct bypass_decl with information used later by
1668   `expand_automata'.  */
1669void
1670gen_bypass (def)
1671     rtx def;
1672{
1673  decl_t decl;
1674  char **out_insns;
1675  int out_length;
1676  char **in_insns;
1677  int in_length;
1678  int i, j;
1679
1680  out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', 0);
1681  if (out_insns == NULL)
1682    fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1683  in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', 0);
1684  if (in_insns == NULL)
1685    fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1686  for (i = 0; i < out_length; i++)
1687    for (j = 0; j < in_length; j++)
1688      {
1689	decl = create_node (sizeof (struct decl));
1690	decl->mode = dm_bypass;
1691	decl->pos = 0;
1692	DECL_BYPASS (decl)->latency = XINT (def, 0);
1693	DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1694	DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1695	DECL_BYPASS (decl)->bypass_guard_name = (char *) XSTR (def, 3);
1696	VLA_PTR_ADD (decls, decl);
1697	num_dfa_decls++;
1698      }
1699}
1700
1701/* Process an EXCLUSION_SET.
1702
1703   This gives information about a cpu unit conflicts.  We fill a
1704   struct unit_rel_decl (excl) with information used later by
1705   `expand_automata'.  */
1706void
1707gen_excl_set (def)
1708     rtx def;
1709{
1710  decl_t decl;
1711  char **first_str_cpu_units;
1712  char **second_str_cpu_units;
1713  int first_vect_length;
1714  int length;
1715  int i;
1716
1717  first_str_cpu_units
1718    = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1719  if (first_str_cpu_units == NULL)
1720    fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1721  second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1722				       0);
1723  if (second_str_cpu_units == NULL)
1724    fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1725  length += first_vect_length;
1726  decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1727  decl->mode = dm_excl;
1728  decl->pos = 0;
1729  DECL_EXCL (decl)->names_num = length;
1730  DECL_EXCL (decl)->first_list_length = first_vect_length;
1731  for (i = 0; i < length; i++)
1732    if (i < first_vect_length)
1733      DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1734    else
1735      DECL_EXCL (decl)->names [i]
1736	= second_str_cpu_units [i - first_vect_length];
1737  VLA_PTR_ADD (decls, decl);
1738  num_dfa_decls++;
1739}
1740
1741/* Process a PRESENCE_SET.
1742
1743   This gives information about a cpu unit reservation requirements.
1744   We fill a struct unit_rel_decl (presence) with information used
1745   later by `expand_automata'.  */
1746void
1747gen_presence_set (def)
1748     rtx def;
1749{
1750  decl_t decl;
1751  char **first_str_cpu_units;
1752  char **second_str_cpu_units;
1753  int first_vect_length;
1754  int length;
1755  int i;
1756
1757  first_str_cpu_units
1758    = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1759  if (first_str_cpu_units == NULL)
1760    fatal ("invalid first string `%s' in presence_set", XSTR (def, 0));
1761  second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1762				       0);
1763  if (second_str_cpu_units == NULL)
1764    fatal ("invalid second string `%s' in presence_set", XSTR (def, 1));
1765  length += first_vect_length;
1766  decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1767  decl->mode = dm_presence;
1768  decl->pos = 0;
1769  DECL_PRESENCE (decl)->names_num = length;
1770  DECL_PRESENCE (decl)->first_list_length = first_vect_length;
1771  for (i = 0; i < length; i++)
1772    if (i < first_vect_length)
1773      DECL_PRESENCE (decl)->names [i] = first_str_cpu_units [i];
1774    else
1775      DECL_PRESENCE (decl)->names [i]
1776	= second_str_cpu_units [i - first_vect_length];
1777  VLA_PTR_ADD (decls, decl);
1778  num_dfa_decls++;
1779}
1780
1781/* Process an ABSENCE_SET.
1782
1783   This gives information about a cpu unit reservation requirements.
1784   We fill a struct unit_rel_decl (absence) with information used
1785   later by `expand_automata'.  */
1786void
1787gen_absence_set (def)
1788     rtx def;
1789{
1790  decl_t decl;
1791  char **first_str_cpu_units;
1792  char **second_str_cpu_units;
1793  int first_vect_length;
1794  int length;
1795  int i;
1796
1797  first_str_cpu_units
1798    = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1799  if (first_str_cpu_units == NULL)
1800    fatal ("invalid first string `%s' in absence_set", XSTR (def, 0));
1801  second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1802				       0);
1803  if (second_str_cpu_units == NULL)
1804    fatal ("invalid second string `%s' in absence_set", XSTR (def, 1));
1805  length += first_vect_length;
1806  decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1807  decl->mode = dm_absence;
1808  decl->pos = 0;
1809  DECL_ABSENCE (decl)->names_num = length;
1810  DECL_ABSENCE (decl)->first_list_length = first_vect_length;
1811  for (i = 0; i < length; i++)
1812    if (i < first_vect_length)
1813      DECL_ABSENCE (decl)->names [i] = first_str_cpu_units [i];
1814    else
1815      DECL_ABSENCE (decl)->names [i]
1816	= second_str_cpu_units [i - first_vect_length];
1817  VLA_PTR_ADD (decls, decl);
1818  num_dfa_decls++;
1819}
1820
1821/* Process a DEFINE_AUTOMATON.
1822
1823   This gives information about a finite state automaton used for
1824   recognizing pipeline hazards.  We fill a struct automaton_decl
1825   with information used later by `expand_automata'.  */
1826void
1827gen_automaton (def)
1828     rtx def;
1829{
1830  decl_t decl;
1831  char **str_automata;
1832  int vect_length;
1833  int i;
1834
1835  str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1836  if (str_automata == NULL)
1837    fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1838  for (i = 0; i < vect_length; i++)
1839    {
1840      decl = create_node (sizeof (struct decl));
1841      decl->mode = dm_automaton;
1842      decl->pos = 0;
1843      DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1844      VLA_PTR_ADD (decls, decl);
1845      num_dfa_decls++;
1846    }
1847}
1848
1849/* Process an AUTOMATA_OPTION.
1850
1851   This gives information how to generate finite state automaton used
1852   for recognizing pipeline hazards.  */
1853void
1854gen_automata_option (def)
1855     rtx def;
1856{
1857  if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1858    no_minimization_flag = 1;
1859  else if (strcmp ((char *) XSTR (def, 0), TIME_OPTION + 1) == 0)
1860    time_flag = 1;
1861  else if (strcmp ((char *) XSTR (def, 0), V_OPTION + 1) == 0)
1862    v_flag = 1;
1863  else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
1864    w_flag = 1;
1865  else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
1866    ndfa_flag = 1;
1867  else
1868    fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1869}
1870
1871/* Name in reservation to denote absence reservation.  */
1872#define NOTHING_NAME "nothing"
1873
1874/* The following string contains original reservation string being
1875   parsed.  */
1876static char *reserv_str;
1877
1878/* Parse an element in STR.  */
1879static regexp_t
1880gen_regexp_el (str)
1881     char *str;
1882{
1883  regexp_t regexp;
1884  int len;
1885
1886  if (*str == '(')
1887    {
1888      len = strlen (str);
1889      if (str [len - 1] != ')')
1890	fatal ("garbage after ) in reservation `%s'", reserv_str);
1891      str [len - 1] = '\0';
1892      regexp = gen_regexp_sequence (str + 1);
1893    }
1894  else if (strcmp (str, NOTHING_NAME) == 0)
1895    {
1896      regexp = create_node (sizeof (struct decl));
1897      regexp->mode = rm_nothing;
1898    }
1899  else
1900    {
1901      regexp = create_node (sizeof (struct decl));
1902      regexp->mode = rm_unit;
1903      REGEXP_UNIT (regexp)->name = str;
1904    }
1905  return regexp;
1906}
1907
1908/* Parse construction `repeat' in STR.  */
1909static regexp_t
1910gen_regexp_repeat (str)
1911     char *str;
1912{
1913  regexp_t regexp;
1914  regexp_t repeat;
1915  char **repeat_vect;
1916  int els_num;
1917  int i;
1918
1919  repeat_vect = get_str_vect (str, &els_num, '*', 1);
1920  if (repeat_vect == NULL)
1921    fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1922  if (els_num > 1)
1923    {
1924      regexp = gen_regexp_el (repeat_vect [0]);
1925      for (i = 1; i < els_num; i++)
1926	{
1927	  repeat = create_node (sizeof (struct regexp));
1928	  repeat->mode = rm_repeat;
1929	  REGEXP_REPEAT (repeat)->regexp = regexp;
1930	  REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1931          if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1932            fatal ("repetition `%s' <= 1 in reservation `%s'",
1933                   str, reserv_str);
1934          regexp = repeat;
1935	}
1936      return regexp;
1937    }
1938  else
1939    return gen_regexp_el (str);
1940}
1941
1942/* Parse reservation STR which possibly contains separator '+'.  */
1943static regexp_t
1944gen_regexp_allof (str)
1945     char *str;
1946{
1947  regexp_t allof;
1948  char **allof_vect;
1949  int els_num;
1950  int i;
1951
1952  allof_vect = get_str_vect (str, &els_num, '+', 1);
1953  if (allof_vect == NULL)
1954    fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1955  if (els_num > 1)
1956    {
1957      allof = create_node (sizeof (struct regexp)
1958			   + sizeof (regexp_t) * (els_num - 1));
1959      allof->mode = rm_allof;
1960      REGEXP_ALLOF (allof)->regexps_num = els_num;
1961      for (i = 0; i < els_num; i++)
1962	REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1963      return allof;
1964    }
1965  else
1966    return gen_regexp_repeat (str);
1967}
1968
1969/* Parse reservation STR which possibly contains separator '|'.  */
1970static regexp_t
1971gen_regexp_oneof (str)
1972     char *str;
1973{
1974  regexp_t oneof;
1975  char **oneof_vect;
1976  int els_num;
1977  int i;
1978
1979  oneof_vect = get_str_vect (str, &els_num, '|', 1);
1980  if (oneof_vect == NULL)
1981    fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1982  if (els_num > 1)
1983    {
1984      oneof = create_node (sizeof (struct regexp)
1985			   + sizeof (regexp_t) * (els_num - 1));
1986      oneof->mode = rm_oneof;
1987      REGEXP_ONEOF (oneof)->regexps_num = els_num;
1988      for (i = 0; i < els_num; i++)
1989	REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1990      return oneof;
1991    }
1992  else
1993    return gen_regexp_allof (str);
1994}
1995
1996/* Parse reservation STR which possibly contains separator ','.  */
1997static regexp_t
1998gen_regexp_sequence (str)
1999     char *str;
2000{
2001  regexp_t sequence;
2002  char **sequence_vect;
2003  int els_num;
2004  int i;
2005
2006  sequence_vect = get_str_vect (str, &els_num, ',', 1);
2007  if (els_num > 1)
2008    {
2009      sequence = create_node (sizeof (struct regexp)
2010			      + sizeof (regexp_t) * (els_num - 1));
2011      sequence->mode = rm_sequence;
2012      REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
2013      for (i = 0; i < els_num; i++)
2014	REGEXP_SEQUENCE (sequence)->regexps [i]
2015          = gen_regexp_oneof (sequence_vect [i]);
2016      return sequence;
2017    }
2018  else
2019    return gen_regexp_oneof (str);
2020}
2021
2022/* Parse construction reservation STR.  */
2023static regexp_t
2024gen_regexp (str)
2025     char *str;
2026{
2027  reserv_str = str;
2028  return gen_regexp_sequence (str);;
2029}
2030
2031/* Process a DEFINE_RESERVATION.
2032
2033   This gives information about a reservation of cpu units.  We fill
2034   in a struct reserv_decl with information used later by
2035   `expand_automata'.  */
2036void
2037gen_reserv (def)
2038     rtx def;
2039{
2040  decl_t decl;
2041
2042  decl = create_node (sizeof (struct decl));
2043  decl->mode = dm_reserv;
2044  decl->pos = 0;
2045  DECL_RESERV (decl)->name = check_name ((char *) XSTR (def, 0), decl->pos);
2046  DECL_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 1));
2047  VLA_PTR_ADD (decls, decl);
2048  num_dfa_decls++;
2049}
2050
2051/* Process a DEFINE_INSN_RESERVATION.
2052
2053   This gives information about the reservation of cpu units by an
2054   insn.  We fill a struct insn_reserv_decl with information used
2055   later by `expand_automata'.  */
2056void
2057gen_insn_reserv (def)
2058     rtx def;
2059{
2060  decl_t decl;
2061
2062  decl = create_node (sizeof (struct decl));
2063  decl->mode = dm_insn_reserv;
2064  decl->pos = 0;
2065  DECL_INSN_RESERV (decl)->name
2066    = check_name ((char *) XSTR (def, 0), decl->pos);
2067  DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
2068  DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
2069  DECL_INSN_RESERV (decl)->regexp = gen_regexp ((char *) XSTR (def, 3));
2070  VLA_PTR_ADD (decls, decl);
2071  num_dfa_decls++;
2072}
2073
2074
2075
2076/* The function evaluates hash value (0..UINT_MAX) of string.  */
2077static unsigned
2078string_hash (string)
2079     const char *string;
2080{
2081  unsigned result, i;
2082
2083  for (result = i = 0;*string++ != '\0'; i++)
2084    result += ((unsigned char) *string << (i % CHAR_BIT));
2085  return result;
2086}
2087
2088
2089
2090/* This page contains abstract data `table of automaton declarations'.
2091   Elements of the table is nodes representing automaton declarations.
2092   Key of the table elements is name of given automaton.  Rememeber
2093   that automaton names have own space.  */
2094
2095/* The function evaluates hash value of an automaton declaration.  The
2096   function is used by abstract data `hashtab'.  The function returns
2097   hash value (0..UINT_MAX) of given automaton declaration.  */
2098static hashval_t
2099automaton_decl_hash (automaton_decl)
2100     const void *automaton_decl;
2101{
2102  const decl_t decl = (decl_t) automaton_decl;
2103
2104  if (decl->mode == dm_automaton && DECL_AUTOMATON (decl)->name == NULL)
2105    abort ();
2106  return string_hash (DECL_AUTOMATON (decl)->name);
2107}
2108
2109/* The function tests automaton declarations on equality of their
2110   keys.  The function is used by abstract data `hashtab'.  The
2111   function returns 1 if the declarations have the same key, 0
2112   otherwise.  */
2113static int
2114automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
2115     const void* automaton_decl_1;
2116     const void* automaton_decl_2;
2117{
2118  const decl_t decl1 = (decl_t) automaton_decl_1;
2119  const decl_t decl2 = (decl_t) automaton_decl_2;
2120
2121  if (decl1->mode != dm_automaton || DECL_AUTOMATON (decl1)->name == NULL
2122      || decl2->mode != dm_automaton || DECL_AUTOMATON (decl2)->name == NULL)
2123    abort ();
2124  return strcmp (DECL_AUTOMATON (decl1)->name,
2125		 DECL_AUTOMATON (decl2)->name) == 0;
2126}
2127
2128/* The automaton declaration table itself is represented by the
2129   following variable.  */
2130static htab_t automaton_decl_table;
2131
2132/* The function inserts automaton declaration into the table.  The
2133   function does nothing if an automaton declaration with the same key
2134   exists already in the table.  The function returns automaton
2135   declaration node in the table with the same key as given automaton
2136   declaration node.  */
2137static decl_t
2138insert_automaton_decl (automaton_decl)
2139     decl_t automaton_decl;
2140{
2141  void **entry_ptr;
2142
2143  entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
2144  if (*entry_ptr == NULL)
2145    *entry_ptr = (void *) automaton_decl;
2146  return (decl_t) *entry_ptr;
2147}
2148
2149/* The following variable value is node representing automaton
2150   declaration.  The node used for searching automaton declaration
2151   with given name.  */
2152static struct decl work_automaton_decl;
2153
2154/* The function searches for automaton declaration in the table with
2155   the same key as node representing name of the automaton
2156   declaration.  The function returns node found in the table, NULL if
2157   such node does not exist in the table.  */
2158static decl_t
2159find_automaton_decl (name)
2160     char *name;
2161{
2162  void *entry;
2163
2164  work_automaton_decl.mode = dm_automaton;
2165  DECL_AUTOMATON (&work_automaton_decl)->name = name;
2166  entry = htab_find (automaton_decl_table, &work_automaton_decl);
2167  return (decl_t) entry;
2168}
2169
2170/* The function creates empty automaton declaration table and node
2171   representing automaton declaration and used for searching automaton
2172   declaration with given name.  The function must be called only once
2173   before any work with the automaton declaration table.  */
2174static void
2175initiate_automaton_decl_table ()
2176{
2177  work_automaton_decl.mode = dm_automaton;
2178  automaton_decl_table = htab_create (10, automaton_decl_hash,
2179				      automaton_decl_eq_p, (htab_del) 0);
2180}
2181
2182/* The function deletes the automaton declaration table.  Only call of
2183   function `initiate_automaton_decl_table' is possible immediately
2184   after this function call.  */
2185static void
2186finish_automaton_decl_table ()
2187{
2188  htab_delete (automaton_decl_table);
2189}
2190
2191
2192
2193/* This page contains abstract data `table of insn declarations'.
2194   Elements of the table is nodes representing insn declarations.  Key
2195   of the table elements is name of given insn (in corresponding
2196   define_insn_reservation).  Rememeber that insn names have own
2197   space.  */
2198
2199/* The function evaluates hash value of an insn declaration.  The
2200   function is used by abstract data `hashtab'.  The function returns
2201   hash value (0..UINT_MAX) of given insn declaration.  */
2202static hashval_t
2203insn_decl_hash (insn_decl)
2204     const void *insn_decl;
2205{
2206  const decl_t decl = (decl_t) insn_decl;
2207
2208  if (decl->mode != dm_insn_reserv || DECL_INSN_RESERV (decl)->name == NULL)
2209    abort ();
2210  return string_hash (DECL_INSN_RESERV (decl)->name);
2211}
2212
2213/* The function tests insn declarations on equality of their keys.
2214   The function is used by abstract data `hashtab'.  The function
2215   returns 1 if declarations have the same key, 0 otherwise.  */
2216static int
2217insn_decl_eq_p (insn_decl_1, insn_decl_2)
2218     const void *insn_decl_1;
2219     const void *insn_decl_2;
2220{
2221  const decl_t decl1 = (decl_t) insn_decl_1;
2222  const decl_t decl2 = (decl_t) insn_decl_2;
2223
2224  if (decl1->mode != dm_insn_reserv || DECL_INSN_RESERV (decl1)->name == NULL
2225      || decl2->mode != dm_insn_reserv
2226      || DECL_INSN_RESERV (decl2)->name == NULL)
2227    abort ();
2228  return strcmp (DECL_INSN_RESERV (decl1)->name,
2229                 DECL_INSN_RESERV (decl2)->name) == 0;
2230}
2231
2232/* The insn declaration table itself is represented by the following
2233   variable.  The table does not contain insn reservation
2234   declarations.  */
2235static htab_t insn_decl_table;
2236
2237/* The function inserts insn declaration into the table.  The function
2238   does nothing if an insn declaration with the same key exists
2239   already in the table.  The function returns insn declaration node
2240   in the table with the same key as given insn declaration node.  */
2241static decl_t
2242insert_insn_decl (insn_decl)
2243     decl_t insn_decl;
2244{
2245  void **entry_ptr;
2246
2247  entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2248  if (*entry_ptr == NULL)
2249    *entry_ptr = (void *) insn_decl;
2250  return (decl_t) *entry_ptr;
2251}
2252
2253/* The following variable value is node representing insn reservation
2254   declaration.  The node used for searching insn reservation
2255   declaration with given name.  */
2256static struct decl work_insn_decl;
2257
2258/* The function searches for insn reservation declaration in the table
2259   with the same key as node representing name of the insn reservation
2260   declaration.  The function returns node found in the table, NULL if
2261   such node does not exist in the table.  */
2262static decl_t
2263find_insn_decl (name)
2264     char *name;
2265{
2266  void *entry;
2267
2268  work_insn_decl.mode = dm_insn_reserv;
2269  DECL_INSN_RESERV (&work_insn_decl)->name = name;
2270  entry = htab_find (insn_decl_table, &work_insn_decl);
2271  return (decl_t) entry;
2272}
2273
2274/* The function creates empty insn declaration table and node
2275   representing insn declaration and used for searching insn
2276   declaration with given name.  The function must be called only once
2277   before any work with the insn declaration table.  */
2278static void
2279initiate_insn_decl_table ()
2280{
2281  work_insn_decl.mode = dm_insn_reserv;
2282  insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2283				 (htab_del) 0);
2284}
2285
2286/* The function deletes the insn declaration table.  Only call of
2287   function `initiate_insn_decl_table' is possible immediately after
2288   this function call.  */
2289static void
2290finish_insn_decl_table ()
2291{
2292  htab_delete (insn_decl_table);
2293}
2294
2295
2296
2297/* This page contains abstract data `table of declarations'.  Elements
2298   of the table is nodes representing declarations (of units and
2299   reservations).  Key of the table elements is names of given
2300   declarations.  */
2301
2302/* The function evaluates hash value of a declaration.  The function
2303   is used by abstract data `hashtab'.  The function returns hash
2304   value (0..UINT_MAX) of given declaration.  */
2305static hashval_t
2306decl_hash (decl)
2307     const void *decl;
2308{
2309  const decl_t d = (const decl_t) decl;
2310
2311  if ((d->mode != dm_unit || DECL_UNIT (d)->name == NULL)
2312      && (d->mode != dm_reserv || DECL_RESERV (d)->name == NULL))
2313    abort ();
2314  return string_hash (d->mode == dm_unit
2315		      ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
2316}
2317
2318/* The function tests declarations on equality of their keys.  The
2319   function is used by abstract data `hashtab'.  The function
2320   returns 1 if the declarations have the same key, 0 otherwise.  */
2321static int
2322decl_eq_p (decl_1, decl_2)
2323     const void *decl_1;
2324     const void *decl_2;
2325{
2326  const decl_t d1 = (const decl_t) decl_1;
2327  const decl_t d2 = (const decl_t) decl_2;
2328
2329  if (((d1->mode != dm_unit || DECL_UNIT (d1)->name == NULL)
2330       && (d1->mode != dm_reserv || DECL_RESERV (d1)->name == NULL))
2331      || ((d2->mode != dm_unit || DECL_UNIT (d2)->name == NULL)
2332	  && (d2->mode != dm_reserv || DECL_RESERV (d2)->name == NULL)))
2333    abort ();
2334  return strcmp ((d1->mode == dm_unit
2335                  ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
2336                 (d2->mode == dm_unit
2337                  ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2338}
2339
2340/* The declaration table itself is represented by the following
2341   variable.  */
2342static htab_t decl_table;
2343
2344/* The function inserts declaration into the table.  The function does
2345   nothing if a declaration with the same key exists already in the
2346   table.  The function returns declaration node in the table with the
2347   same key as given declaration node.  */
2348
2349static decl_t
2350insert_decl (decl)
2351     decl_t decl;
2352{
2353  void **entry_ptr;
2354
2355  entry_ptr = htab_find_slot (decl_table, decl, 1);
2356  if (*entry_ptr == NULL)
2357    *entry_ptr = (void *) decl;
2358  return (decl_t) *entry_ptr;
2359}
2360
2361/* The following variable value is node representing declaration.  The
2362   node used for searching declaration with given name.  */
2363static struct decl work_decl;
2364
2365/* The function searches for declaration in the table with the same
2366   key as node representing name of the declaration.  The function
2367   returns node found in the table, NULL if such node does not exist
2368   in the table.  */
2369static decl_t
2370find_decl (name)
2371     char *name;
2372{
2373  void *entry;
2374
2375  work_decl.mode = dm_unit;
2376  DECL_UNIT (&work_decl)->name = name;
2377  entry = htab_find (decl_table, &work_decl);
2378  return (decl_t) entry;
2379}
2380
2381/* The function creates empty declaration table and node representing
2382   declaration and used for searching declaration with given name.
2383   The function must be called only once before any work with the
2384   declaration table.  */
2385static void
2386initiate_decl_table ()
2387{
2388  work_decl.mode = dm_unit;
2389  decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2390}
2391
2392/* The function deletes the declaration table.  Only call of function
2393   `initiate_declaration_table' is possible immediately after this
2394   function call.  */
2395static void
2396finish_decl_table ()
2397{
2398  htab_delete (decl_table);
2399}
2400
2401
2402
2403/* This page contains checker of pipeline hazard description.  */
2404
2405/* Checking NAMES in an exclusion clause vector and returning formed
2406   unit_set_el_list.  */
2407static unit_set_el_t
2408process_excls (names, num, excl_pos)
2409     char **names;
2410     int num;
2411     pos_t excl_pos ATTRIBUTE_UNUSED;
2412{
2413  unit_set_el_t el_list;
2414  unit_set_el_t last_el;
2415  unit_set_el_t new_el;
2416  decl_t decl_in_table;
2417  int i;
2418
2419  el_list = NULL;
2420  last_el = NULL;
2421  for (i = 0; i < num; i++)
2422    {
2423      decl_in_table = find_decl (names [i]);
2424      if (decl_in_table == NULL)
2425	error ("unit `%s' in exclusion is not declared", names [i]);
2426      else if (decl_in_table->mode != dm_unit)
2427	error ("`%s' in exclusion is not unit", names [i]);
2428      else
2429	{
2430	  new_el = create_node (sizeof (struct unit_set_el));
2431	  new_el->unit_decl = DECL_UNIT (decl_in_table);
2432	  new_el->next_unit_set_el = NULL;
2433	  if (last_el == NULL)
2434	    el_list = last_el = new_el;
2435	  else
2436	    {
2437	      last_el->next_unit_set_el = new_el;
2438	      last_el = last_el->next_unit_set_el;
2439	    }
2440	}
2441    }
2442  return el_list;
2443}
2444
2445/* The function adds each element from SOURCE_LIST to the exclusion
2446   list of the each element from DEST_LIST.  Checking situation "unit
2447   excludes itself".  */
2448static void
2449add_excls (dest_list, source_list, excl_pos)
2450     unit_set_el_t dest_list;
2451     unit_set_el_t source_list;
2452     pos_t excl_pos ATTRIBUTE_UNUSED;
2453{
2454  unit_set_el_t dst;
2455  unit_set_el_t src;
2456  unit_set_el_t curr_el;
2457  unit_set_el_t prev_el;
2458  unit_set_el_t copy;
2459
2460  for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2461    for (src = source_list; src != NULL; src = src->next_unit_set_el)
2462      {
2463	if (dst->unit_decl == src->unit_decl)
2464	  {
2465	    error ("unit `%s' excludes itself", src->unit_decl->name);
2466	    continue;
2467	  }
2468	if (dst->unit_decl->automaton_name != NULL
2469	    && src->unit_decl->automaton_name != NULL
2470	    && strcmp (dst->unit_decl->automaton_name,
2471		       src->unit_decl->automaton_name) != 0)
2472	  {
2473	    error ("units `%s' and `%s' in exclusion set belong to different automata",
2474		   src->unit_decl->name, dst->unit_decl->name);
2475	    continue;
2476	  }
2477	for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2478	     curr_el != NULL;
2479	     prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2480	  if (curr_el->unit_decl == src->unit_decl)
2481	    break;
2482	if (curr_el == NULL)
2483	  {
2484	    /* Element not found - insert.  */
2485	    copy = copy_node (src, sizeof (*src));
2486	    copy->next_unit_set_el = NULL;
2487	    if (prev_el == NULL)
2488	      dst->unit_decl->excl_list = copy;
2489	    else
2490	      prev_el->next_unit_set_el = copy;
2491	}
2492    }
2493}
2494
2495/* Checking NAMES in a presence clause vector and returning formed
2496   unit_set_el_list.  The function is called only after processing all
2497   exclusion sets.  */
2498static unit_set_el_t
2499process_presence_absence (names, num, req_pos, presence_p)
2500     char **names;
2501     int num;
2502     pos_t req_pos ATTRIBUTE_UNUSED;
2503     int presence_p;
2504{
2505  unit_set_el_t el_list;
2506  unit_set_el_t last_el;
2507  unit_set_el_t new_el;
2508  decl_t decl_in_table;
2509  int i;
2510
2511  el_list = NULL;
2512  last_el = NULL;
2513  for (i = 0; i < num; i++)
2514    {
2515      decl_in_table = find_decl (names [i]);
2516      if (decl_in_table == NULL)
2517	error ((presence_p
2518		? "unit `%s' in presence set is not declared"
2519		: "unit `%s' in absence set is not declared"), names [i]);
2520      else if (decl_in_table->mode != dm_unit)
2521	error ((presence_p
2522		? "`%s' in presence set is not unit"
2523		: "`%s' in absence set is not unit"), names [i]);
2524      else
2525	{
2526	  new_el = create_node (sizeof (struct unit_set_el));
2527	  new_el->unit_decl = DECL_UNIT (decl_in_table);
2528	  new_el->next_unit_set_el = NULL;
2529	  if (last_el == NULL)
2530	    el_list = last_el = new_el;
2531	  else
2532	    {
2533	      last_el->next_unit_set_el = new_el;
2534	      last_el = last_el->next_unit_set_el;
2535	    }
2536	}
2537    }
2538  return el_list;
2539}
2540
2541/* The function adds each element from SOURCE_LIST to presence (if
2542   PRESENCE_P) or absence list of the each element from DEST_LIST.
2543   Checking situations "unit requires own presence", "unit requires
2544   own absence", and "unit excludes and requires presence of ...".
2545   Remember that we process absence sets only after all presence
2546   sets.  */
2547static void
2548add_presence_absence (dest_list, source_list, req_pos, presence_p)
2549     unit_set_el_t dest_list;
2550     unit_set_el_t source_list;
2551     pos_t req_pos ATTRIBUTE_UNUSED;
2552     int presence_p;
2553{
2554  unit_set_el_t dst;
2555  unit_set_el_t src;
2556  unit_set_el_t curr_el;
2557  unit_set_el_t prev_el;
2558  unit_set_el_t copy;
2559
2560  for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2561    for (src = source_list; src != NULL; src = src->next_unit_set_el)
2562      {
2563	if (dst->unit_decl == src->unit_decl)
2564	  {
2565	    error ((presence_p
2566		    ? "unit `%s' requires own presence"
2567		    : "unit `%s' requires own absence"), src->unit_decl->name);
2568	    continue;
2569	  }
2570	if (dst->unit_decl->automaton_name != NULL
2571	    && src->unit_decl->automaton_name != NULL
2572	    && strcmp (dst->unit_decl->automaton_name,
2573		       src->unit_decl->automaton_name) != 0)
2574	  {
2575	    error ((presence_p
2576		    ? "units `%s' and `%s' in presence set belong to different automata"
2577		    : "units `%s' and `%s' in absence set belong to different automata"),
2578		   src->unit_decl->name, dst->unit_decl->name);
2579	    continue;
2580	  }
2581	for (curr_el = (presence_p
2582			? dst->unit_decl->presence_list
2583			: dst->unit_decl->absence_list), prev_el = NULL;
2584	     curr_el != NULL;
2585	     prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2586	  if (curr_el->unit_decl == src->unit_decl)
2587	    break;
2588	if (curr_el == NULL)
2589	  {
2590	    /* Element not found - insert if there is no error.  */
2591	    int no_error_flag = 1;
2592
2593	    if (presence_p)
2594	      for (curr_el = dst->unit_decl->excl_list;
2595		   curr_el != NULL;
2596		   curr_el = curr_el->next_unit_set_el)
2597		{
2598		  if (src->unit_decl == curr_el->unit_decl)
2599		    {
2600		      if (!w_flag)
2601			{
2602			  error
2603			    ("unit `%s' excludes and requires presence of `%s'",
2604			     dst->unit_decl->name, src->unit_decl->name);
2605			  no_error_flag = 0;
2606			}
2607		      else
2608			warning
2609			  ("unit `%s' excludes and requires presence of `%s'",
2610			   dst->unit_decl->name, src->unit_decl->name);
2611		    }
2612		}
2613	    else
2614	      for (curr_el = dst->unit_decl->presence_list;
2615		   curr_el != NULL;
2616		   curr_el = curr_el->next_unit_set_el)
2617		{
2618		  if (src->unit_decl == curr_el->unit_decl)
2619		    {
2620		      if (!w_flag)
2621			{
2622			  error
2623			    ("unit `%s' requires absence and presence of `%s'",
2624			     dst->unit_decl->name, src->unit_decl->name);
2625			  no_error_flag = 0;
2626			}
2627		      else
2628			warning
2629			  ("unit `%s' requires absence and presence of `%s'",
2630			   dst->unit_decl->name, src->unit_decl->name);
2631		    }
2632		}
2633	    if (no_error_flag)
2634	      {
2635		copy = copy_node (src, sizeof (*src));
2636		copy->next_unit_set_el = NULL;
2637		if (prev_el == NULL)
2638		  {
2639		    if (presence_p)
2640		      dst->unit_decl->presence_list = copy;
2641		    else
2642		      dst->unit_decl->absence_list = copy;
2643		  }
2644		else
2645		  prev_el->next_unit_set_el = copy;
2646	      }
2647	}
2648    }
2649}
2650
2651/* The function searches for bypass with given IN_INSN_RESERV in given
2652   BYPASS_LIST.  */
2653static struct bypass_decl *
2654find_bypass (bypass_list, in_insn_reserv)
2655     struct bypass_decl *bypass_list;
2656     struct insn_reserv_decl *in_insn_reserv;
2657{
2658  struct bypass_decl *bypass;
2659
2660  for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2661    if (bypass->in_insn_reserv == in_insn_reserv)
2662      break;
2663  return bypass;
2664}
2665
2666/* The function processes pipeline description declarations, checks
2667   their correctness, and forms exclusion/presence/absence sets.  */
2668static void
2669process_decls ()
2670{
2671  decl_t decl;
2672  decl_t automaton_decl;
2673  decl_t decl_in_table;
2674  decl_t out_insn_reserv;
2675  decl_t in_insn_reserv;
2676  struct bypass_decl *bypass;
2677  int automaton_presence;
2678  int i;
2679
2680  /* Checking repeated automata declarations.  */
2681  automaton_presence = 0;
2682  for (i = 0; i < description->decls_num; i++)
2683    {
2684      decl = description->decls [i];
2685      if (decl->mode == dm_automaton)
2686	{
2687	  automaton_presence = 1;
2688	  decl_in_table = insert_automaton_decl (decl);
2689	  if (decl_in_table != decl)
2690	    {
2691	      if (!w_flag)
2692		error ("repeated declaration of automaton `%s'",
2693		       DECL_AUTOMATON (decl)->name);
2694	      else
2695		warning ("repeated declaration of automaton `%s'",
2696			 DECL_AUTOMATON (decl)->name);
2697	    }
2698	}
2699    }
2700  /* Checking undeclared automata, repeated declarations (except for
2701     automata) and correctness of their attributes (insn latency times
2702     etc.).  */
2703  for (i = 0; i < description->decls_num; i++)
2704    {
2705      decl = description->decls [i];
2706      if (decl->mode == dm_insn_reserv)
2707	{
2708          DECL_INSN_RESERV (decl)->condexp
2709	    = check_attr_test (DECL_INSN_RESERV (decl)->condexp, 0, 0);
2710	  if (DECL_INSN_RESERV (decl)->default_latency < 0)
2711	    error ("define_insn_reservation `%s' has negative latency time",
2712		   DECL_INSN_RESERV (decl)->name);
2713	  DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2714	  description->insns_num++;
2715	  decl_in_table = insert_insn_decl (decl);
2716	  if (decl_in_table != decl)
2717	    error ("`%s' is already used as insn reservation name",
2718		   DECL_INSN_RESERV (decl)->name);
2719	}
2720      else if (decl->mode == dm_bypass)
2721	{
2722	  if (DECL_BYPASS (decl)->latency < 0)
2723	    error ("define_bypass `%s - %s' has negative latency time",
2724		   DECL_BYPASS (decl)->out_insn_name,
2725		   DECL_BYPASS (decl)->in_insn_name);
2726	}
2727      else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2728	{
2729	  if (decl->mode == dm_unit)
2730	    {
2731	      DECL_UNIT (decl)->automaton_decl = NULL;
2732	      if (DECL_UNIT (decl)->automaton_name != NULL)
2733		{
2734		  automaton_decl
2735                    = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2736		  if (automaton_decl == NULL)
2737		    error ("automaton `%s' is not declared",
2738			   DECL_UNIT (decl)->automaton_name);
2739		  else
2740		    {
2741		      DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2742		      DECL_UNIT (decl)->automaton_decl
2743			= DECL_AUTOMATON (automaton_decl);
2744		    }
2745		}
2746	      else if (automaton_presence)
2747		error ("define_unit `%s' without automaton when one defined",
2748		       DECL_UNIT (decl)->name);
2749	      DECL_UNIT (decl)->unit_num = description->units_num;
2750	      description->units_num++;
2751	      if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2752		{
2753		  error ("`%s' is declared as cpu unit", NOTHING_NAME);
2754		  continue;
2755		}
2756	      decl_in_table = find_decl (DECL_UNIT (decl)->name);
2757	    }
2758	  else
2759	    {
2760	      if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2761		{
2762		  error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2763		  continue;
2764		}
2765	      decl_in_table = find_decl (DECL_RESERV (decl)->name);
2766	    }
2767	  if (decl_in_table == NULL)
2768	    decl_in_table = insert_decl (decl);
2769	  else
2770	    {
2771	      if (decl->mode == dm_unit)
2772		error ("repeated declaration of unit `%s'",
2773		       DECL_UNIT (decl)->name);
2774	      else
2775		error ("repeated declaration of reservation `%s'",
2776		       DECL_RESERV (decl)->name);
2777	    }
2778	}
2779    }
2780  /* Check bypasses and form list of bypasses for each (output)
2781     insn.  */
2782  for (i = 0; i < description->decls_num; i++)
2783    {
2784      decl = description->decls [i];
2785      if (decl->mode == dm_bypass)
2786	{
2787	  out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2788	  in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2789	  if (out_insn_reserv == NULL)
2790	    error ("there is no insn reservation `%s'",
2791		   DECL_BYPASS (decl)->out_insn_name);
2792	  else if (in_insn_reserv == NULL)
2793	    error ("there is no insn reservation `%s'",
2794		   DECL_BYPASS (decl)->in_insn_name);
2795	  else
2796	    {
2797	      DECL_BYPASS (decl)->out_insn_reserv
2798		= DECL_INSN_RESERV (out_insn_reserv);
2799	      DECL_BYPASS (decl)->in_insn_reserv
2800		= DECL_INSN_RESERV (in_insn_reserv);
2801	      bypass
2802		= find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2803			       DECL_BYPASS (decl)->in_insn_reserv);
2804	      if (bypass != NULL)
2805		{
2806		  if (DECL_BYPASS (decl)->latency == bypass->latency)
2807		    {
2808		      if (!w_flag)
2809			error
2810			  ("the same bypass `%s - %s' is already defined",
2811			   DECL_BYPASS (decl)->out_insn_name,
2812			   DECL_BYPASS (decl)->in_insn_name);
2813		      else
2814			warning
2815			  ("the same bypass `%s - %s' is already defined",
2816			   DECL_BYPASS (decl)->out_insn_name,
2817			   DECL_BYPASS (decl)->in_insn_name);
2818		    }
2819		  else
2820		    error ("bypass `%s - %s' is already defined",
2821			   DECL_BYPASS (decl)->out_insn_name,
2822			   DECL_BYPASS (decl)->in_insn_name);
2823		}
2824	      else
2825		{
2826		  DECL_BYPASS (decl)->next
2827		    = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2828		  DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2829		    = DECL_BYPASS (decl);
2830		}
2831	    }
2832	}
2833    }
2834
2835  /* Check exclusion set declarations and form exclussion sets.  */
2836  for (i = 0; i < description->decls_num; i++)
2837    {
2838      decl = description->decls [i];
2839      if (decl->mode == dm_excl)
2840	{
2841	  unit_set_el_t unit_set_el_list;
2842	  unit_set_el_t unit_set_el_list_2;
2843
2844	  unit_set_el_list
2845            = process_excls (DECL_EXCL (decl)->names,
2846			     DECL_EXCL (decl)->first_list_length, decl->pos);
2847	  unit_set_el_list_2
2848	    = process_excls (&DECL_EXCL (decl)->names
2849			     [DECL_EXCL (decl)->first_list_length],
2850                             DECL_EXCL (decl)->names_num
2851                             - DECL_EXCL (decl)->first_list_length,
2852                             decl->pos);
2853	  add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2854	  add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2855	}
2856    }
2857
2858  /* Check presence set declarations and form presence sets.  */
2859  for (i = 0; i < description->decls_num; i++)
2860    {
2861      decl = description->decls [i];
2862      if (decl->mode == dm_presence)
2863	{
2864	  unit_set_el_t unit_set_el_list;
2865	  unit_set_el_t unit_set_el_list_2;
2866
2867	  unit_set_el_list
2868            = process_presence_absence
2869	      (DECL_PRESENCE (decl)->names,
2870	       DECL_PRESENCE (decl)->first_list_length, decl->pos, 1);
2871	  unit_set_el_list_2
2872	    = process_presence_absence
2873	      (&DECL_PRESENCE (decl)->names
2874	       [DECL_PRESENCE (decl)->first_list_length],
2875	       DECL_PRESENCE (decl)->names_num
2876	       - DECL_PRESENCE (decl)->first_list_length,
2877	       decl->pos, 1);
2878	  add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2879				decl->pos, 1);
2880	}
2881    }
2882
2883  /* Check absence set declarations and form absence sets.  */
2884  for (i = 0; i < description->decls_num; i++)
2885    {
2886      decl = description->decls [i];
2887      if (decl->mode == dm_absence)
2888	{
2889	  unit_set_el_t unit_set_el_list;
2890	  unit_set_el_t unit_set_el_list_2;
2891
2892	  unit_set_el_list
2893            = process_presence_absence
2894	      (DECL_ABSENCE (decl)->names,
2895	       DECL_ABSENCE (decl)->first_list_length, decl->pos, 0);
2896	  unit_set_el_list_2
2897	    = process_presence_absence
2898	      (&DECL_ABSENCE (decl)->names
2899	       [DECL_ABSENCE (decl)->first_list_length],
2900	       DECL_ABSENCE (decl)->names_num
2901	       - DECL_ABSENCE (decl)->first_list_length,
2902	       decl->pos, 0);
2903	  add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2904				decl->pos, 0);
2905	}
2906    }
2907}
2908
2909/* The following function checks that declared automaton is used.  If
2910   the automaton is not used, the function fixes error/warning.  The
2911   following function must be called only after `process_decls'.  */
2912static void
2913check_automaton_usage ()
2914{
2915  decl_t decl;
2916  int i;
2917
2918  for (i = 0; i < description->decls_num; i++)
2919    {
2920      decl = description->decls [i];
2921      if (decl->mode == dm_automaton
2922	  && !DECL_AUTOMATON (decl)->automaton_is_used)
2923	{
2924	  if (!w_flag)
2925	    error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2926	  else
2927	    warning ("automaton `%s' is not used",
2928		     DECL_AUTOMATON (decl)->name);
2929	}
2930    }
2931}
2932
2933/* The following recursive function processes all regexp in order to
2934   fix usage of units or reservations and to fix errors of undeclared
2935   name.  The function may change unit_regexp onto reserv_regexp.
2936   Remember that reserv_regexp does not exist before the function
2937   call.  */
2938static regexp_t
2939process_regexp (regexp)
2940     regexp_t regexp;
2941{
2942  decl_t decl_in_table;
2943  regexp_t new_regexp;
2944  int i;
2945
2946  if (regexp->mode == rm_unit)
2947    {
2948      decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2949      if (decl_in_table == NULL)
2950        error ("undeclared unit or reservation `%s'",
2951	       REGEXP_UNIT (regexp)->name);
2952      else if (decl_in_table->mode == dm_unit)
2953	{
2954	  DECL_UNIT (decl_in_table)->unit_is_used = 1;
2955	  REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2956	}
2957      else if (decl_in_table->mode == dm_reserv)
2958	{
2959	  DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2960	  new_regexp = create_node (sizeof (struct regexp));
2961	  new_regexp->mode = rm_reserv;
2962	  new_regexp->pos = regexp->pos;
2963	  REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2964	  REGEXP_RESERV (new_regexp)->reserv_decl
2965	    = DECL_RESERV (decl_in_table);
2966	  regexp = new_regexp;
2967	}
2968      else
2969	abort ();
2970    }
2971  else if (regexp->mode == rm_sequence)
2972    for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2973     REGEXP_SEQUENCE (regexp)->regexps [i]
2974	= process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2975  else if (regexp->mode == rm_allof)
2976    for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2977      REGEXP_ALLOF (regexp)->regexps [i]
2978        = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2979  else if (regexp->mode == rm_oneof)
2980    for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2981      REGEXP_ONEOF (regexp)->regexps [i]
2982	= process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2983  else if (regexp->mode == rm_repeat)
2984    REGEXP_REPEAT (regexp)->regexp
2985      = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2986  else if (regexp->mode != rm_nothing)
2987    abort ();
2988  return regexp;
2989}
2990
2991/* The following function processes regexp of define_reservation and
2992   define_insn_reservation with the aid of function
2993   `process_regexp'.  */
2994static void
2995process_regexp_decls ()
2996{
2997  decl_t decl;
2998  int i;
2999
3000  for (i = 0; i < description->decls_num; i++)
3001    {
3002      decl = description->decls [i];
3003      if (decl->mode == dm_reserv)
3004	DECL_RESERV (decl)->regexp
3005	  = process_regexp (DECL_RESERV (decl)->regexp);
3006      else if (decl->mode == dm_insn_reserv)
3007	DECL_INSN_RESERV (decl)->regexp
3008	  = process_regexp (DECL_INSN_RESERV (decl)->regexp);
3009    }
3010}
3011
3012/* The following function checks that declared unit is used.  If the
3013   unit is not used, the function fixes errors/warnings.  The
3014   following function must be called only after `process_decls',
3015   `process_regexp_decls'.  */
3016static void
3017check_usage ()
3018{
3019  decl_t decl;
3020  int i;
3021
3022  for (i = 0; i < description->decls_num; i++)
3023    {
3024      decl = description->decls [i];
3025      if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
3026	{
3027	  if (!w_flag)
3028	    error ("unit `%s' is not used", DECL_UNIT (decl)->name);
3029	  else
3030	    warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
3031	}
3032      else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
3033	{
3034	  if (!w_flag)
3035	    error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3036	  else
3037	    warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
3038	}
3039    }
3040}
3041
3042/* The following variable value is number of reservation being
3043   processed on loop recognition.  */
3044static int curr_loop_pass_num;
3045
3046/* The following recursive function returns nonzero value if REGEXP
3047   contains given decl or reservations in given regexp refers for
3048   given decl.  */
3049static int
3050loop_in_regexp (regexp, start_decl)
3051     regexp_t regexp;
3052     decl_t start_decl;
3053{
3054  int i;
3055
3056  if (regexp == NULL)
3057    return 0;
3058  if (regexp->mode == rm_unit)
3059    return 0;
3060  else if (regexp->mode == rm_reserv)
3061    {
3062      if (start_decl->mode == dm_reserv
3063          && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
3064        return 1;
3065      else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3066	       == curr_loop_pass_num)
3067        /* declaration has been processed.  */
3068        return 0;
3069      else
3070        {
3071	  REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
3072            = curr_loop_pass_num;
3073          return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3074                                 start_decl);
3075        }
3076    }
3077  else if (regexp->mode == rm_sequence)
3078    {
3079      for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3080	if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
3081	  return 1;
3082      return 0;
3083    }
3084  else if (regexp->mode == rm_allof)
3085    {
3086      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3087	if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
3088	  return 1;
3089      return 0;
3090    }
3091  else if (regexp->mode == rm_oneof)
3092    {
3093      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3094	if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
3095	  return 1;
3096      return 0;
3097    }
3098  else if (regexp->mode == rm_repeat)
3099    return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
3100  else
3101    {
3102      if (regexp->mode != rm_nothing)
3103	abort ();
3104      return 0;
3105    }
3106}
3107
3108/* The following function fixes errors "cycle in definition ...".  The
3109   function uses function `loop_in_regexp' for that.  */
3110static void
3111check_loops_in_regexps ()
3112{
3113  decl_t decl;
3114  int i;
3115
3116  for (i = 0; i < description->decls_num; i++)
3117    {
3118      decl = description->decls [i];
3119      if (decl->mode == dm_reserv)
3120	DECL_RESERV (decl)->loop_pass_num = 0;
3121    }
3122  for (i = 0; i < description->decls_num; i++)
3123    {
3124      decl = description->decls [i];
3125      curr_loop_pass_num = i;
3126
3127      if (decl->mode == dm_reserv)
3128	  {
3129	    DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
3130	    if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
3131	      {
3132		if (DECL_RESERV (decl)->regexp == NULL)
3133		  abort ();
3134		error ("cycle in definition of reservation `%s'",
3135		       DECL_RESERV (decl)->name);
3136	      }
3137	  }
3138    }
3139}
3140
3141/* The function recursively processes IR of reservation and defines
3142   max and min cycle for reservation of unit and for result in the
3143   reservation.  */
3144static int
3145process_regexp_cycles (regexp, start_cycle)
3146     regexp_t regexp;
3147     int start_cycle;
3148{
3149  int i;
3150
3151  if (regexp->mode == rm_unit)
3152    {
3153      if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < start_cycle)
3154	REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = start_cycle;
3155      return start_cycle;
3156    }
3157  else if (regexp->mode == rm_reserv)
3158    return process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
3159                                  start_cycle);
3160  else if (regexp->mode == rm_repeat)
3161    {
3162      for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3163        start_cycle = process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3164					     start_cycle) + 1;
3165      return start_cycle;
3166    }
3167  else if (regexp->mode == rm_sequence)
3168    {
3169      for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3170	start_cycle
3171          = process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3172				   start_cycle) + 1;
3173      return start_cycle;
3174    }
3175  else if (regexp->mode == rm_allof)
3176    {
3177      int finish_cycle = 0;
3178      int cycle;
3179
3180      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3181	{
3182	  cycle = process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3183					 start_cycle);
3184	  if (finish_cycle < cycle)
3185	    finish_cycle = cycle;
3186	}
3187      return finish_cycle;
3188    }
3189  else if (regexp->mode == rm_oneof)
3190    {
3191      int finish_cycle = 0;
3192      int cycle;
3193
3194      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3195	{
3196	  cycle = process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3197					 start_cycle);
3198	  if (finish_cycle < cycle)
3199	    finish_cycle = cycle;
3200	}
3201      return finish_cycle;
3202    }
3203  else
3204    {
3205      if (regexp->mode != rm_nothing)
3206	abort ();
3207      return start_cycle;
3208    }
3209}
3210
3211/* The following function is called only for correct program.  The
3212   function defines max reservation of insns in cycles.  */
3213static void
3214evaluate_max_reserv_cycles ()
3215{
3216  int max_insn_cycles_num;
3217  decl_t decl;
3218  int i;
3219
3220  description->max_insn_reserv_cycles = 0;
3221  for (i = 0; i < description->decls_num; i++)
3222    {
3223      decl = description->decls [i];
3224      if (decl->mode == dm_insn_reserv)
3225      {
3226        max_insn_cycles_num
3227          = process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0);
3228        if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3229	  description->max_insn_reserv_cycles = max_insn_cycles_num;
3230      }
3231    }
3232  description->max_insn_reserv_cycles++;
3233}
3234
3235/* The following function calls functions for checking all
3236   description.  */
3237static void
3238check_all_description ()
3239{
3240  process_decls ();
3241  check_automaton_usage ();
3242  process_regexp_decls ();
3243  check_usage ();
3244  check_loops_in_regexps ();
3245  if (!have_error)
3246    evaluate_max_reserv_cycles ();
3247}
3248
3249
3250
3251/* The page contains abstract data `ticker'.  This data is used to
3252   report time of different phases of building automata.  It is
3253   possibly to write a description for which automata will be built
3254   during several minutes even on fast machine.  */
3255
3256/* The following function creates ticker and makes it active.  */
3257static ticker_t
3258create_ticker ()
3259{
3260  ticker_t ticker;
3261
3262  ticker.modified_creation_time = get_run_time ();
3263  ticker.incremented_off_time = 0;
3264  return ticker;
3265}
3266
3267/* The following function switches off given ticker.  */
3268static void
3269ticker_off (ticker)
3270     ticker_t *ticker;
3271{
3272  if (ticker->incremented_off_time == 0)
3273    ticker->incremented_off_time = get_run_time () + 1;
3274}
3275
3276/* The following function switches on given ticker.  */
3277static void
3278ticker_on (ticker)
3279     ticker_t *ticker;
3280{
3281  if (ticker->incremented_off_time != 0)
3282    {
3283      ticker->modified_creation_time
3284        += get_run_time () - ticker->incremented_off_time + 1;
3285      ticker->incremented_off_time = 0;
3286    }
3287}
3288
3289/* The following function returns current time in milliseconds since
3290   the moment when given ticker was created.  */
3291static int
3292active_time (ticker)
3293     ticker_t ticker;
3294{
3295  if (ticker.incremented_off_time != 0)
3296    return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3297  else
3298    return get_run_time () - ticker.modified_creation_time;
3299}
3300
3301/* The following function returns string representation of active time
3302   of given ticker.  The result is string representation of seconds
3303   with accuracy of 1/100 second.  Only result of the last call of the
3304   function exists.  Therefore the following code is not correct
3305
3306      printf ("parser time: %s\ngeneration time: %s\n",
3307              active_time_string (parser_ticker),
3308              active_time_string (generation_ticker));
3309
3310   Correct code has to be the following
3311
3312      printf ("parser time: %s\n", active_time_string (parser_ticker));
3313      printf ("generation time: %s\n",
3314              active_time_string (generation_ticker));
3315
3316*/
3317static void
3318print_active_time (f, ticker)
3319     FILE *f;
3320     ticker_t ticker;
3321{
3322  int msecs;
3323
3324  msecs = active_time (ticker);
3325  fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3326}
3327
3328
3329
3330/* The following variable value is number of automaton which are
3331   really being created.  This value is defined on the base of
3332   argument of option `-split'.  If the variable has zero value the
3333   number of automata is defined by the constructions `%automaton'.
3334   This case occures when option `-split' is absent or has zero
3335   argument.  If constructions `define_automaton' is absent only one
3336   automaton is created.  */
3337static int automata_num;
3338
3339/* The following variable values are times of
3340       o transformation of regular expressions
3341       o building NDFA (DFA if !ndfa_flag)
3342       o NDFA -> DFA   (simply the same automaton if !ndfa_flag)
3343       o DFA minimization
3344       o building insn equivalence classes
3345       o all previous ones
3346       o code output */
3347static ticker_t transform_time;
3348static ticker_t NDFA_time;
3349static ticker_t NDFA_to_DFA_time;
3350static ticker_t minimize_time;
3351static ticker_t equiv_time;
3352static ticker_t automaton_generation_time;
3353static ticker_t output_time;
3354
3355/* The following variable values are times of
3356       all checking
3357       all generation
3358       all pipeline hazard translator work */
3359static ticker_t check_time;
3360static ticker_t generation_time;
3361static ticker_t all_time;
3362
3363
3364
3365/* Pseudo insn decl which denotes advancing cycle.  */
3366static decl_t advance_cycle_insn_decl;
3367static void
3368add_advance_cycle_insn_decl ()
3369{
3370  advance_cycle_insn_decl = create_node (sizeof (struct decl));
3371  advance_cycle_insn_decl->mode = dm_insn_reserv;
3372  advance_cycle_insn_decl->pos = no_pos;
3373  DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3374  DECL_INSN_RESERV (advance_cycle_insn_decl)->name = (char *) "$advance_cycle";
3375  DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3376    = description->insns_num;
3377  description->decls [description->decls_num] = advance_cycle_insn_decl;
3378  description->decls_num++;
3379  description->insns_num++;
3380  num_dfa_decls++;
3381}
3382
3383
3384/* Abstract data `alternative states' which reperesents
3385   nondeterministic nature of the description (see comments for
3386   structures alt_state and state).  */
3387
3388/* List of free states.  */
3389static alt_state_t first_free_alt_state;
3390
3391#ifndef NDEBUG
3392/* The following variables is maximal number of allocated nodes
3393   alt_state.  */
3394static int allocated_alt_states_num = 0;
3395#endif
3396
3397/* The following function returns free node alt_state.  It may be new
3398   allocated node or node freed eralier.  */
3399static alt_state_t
3400get_free_alt_state ()
3401{
3402  alt_state_t result;
3403
3404  if (first_free_alt_state != NULL)
3405    {
3406      result = first_free_alt_state;
3407      first_free_alt_state = first_free_alt_state->next_alt_state;
3408    }
3409  else
3410    {
3411#ifndef NDEBUG
3412      allocated_alt_states_num++;
3413#endif
3414      result = create_node (sizeof (struct alt_state));
3415    }
3416  result->state = NULL;
3417  result->next_alt_state = NULL;
3418  result->next_sorted_alt_state = NULL;
3419  return result;
3420}
3421
3422/* The function frees node ALT_STATE.  */
3423static void
3424free_alt_state (alt_state)
3425     alt_state_t alt_state;
3426{
3427  if (alt_state == NULL)
3428    return;
3429  alt_state->next_alt_state = first_free_alt_state;
3430  first_free_alt_state = alt_state;
3431}
3432
3433/* The function frees list started with node ALT_STATE_LIST.  */
3434static void
3435free_alt_states (alt_states_list)
3436     alt_state_t alt_states_list;
3437{
3438  alt_state_t curr_alt_state;
3439  alt_state_t next_alt_state;
3440
3441  for (curr_alt_state = alt_states_list;
3442       curr_alt_state != NULL;
3443       curr_alt_state = next_alt_state)
3444    {
3445      next_alt_state = curr_alt_state->next_alt_state;
3446      free_alt_state (curr_alt_state);
3447    }
3448}
3449
3450/* The function compares unique numbers of alt states.  */
3451static int
3452alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
3453     const void *alt_state_ptr_1;
3454     const void *alt_state_ptr_2;
3455{
3456  if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3457      == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3458    return 0;
3459  else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3460	   < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3461    return -1;
3462  else
3463    return 1;
3464}
3465
3466/* The function sorts ALT_STATES_LIST and removes duplicated alt
3467   states from the list.  The comparison key is alt state unique
3468   number.  */
3469static alt_state_t
3470uniq_sort_alt_states (alt_states_list)
3471     alt_state_t alt_states_list;
3472{
3473  alt_state_t curr_alt_state;
3474  vla_ptr_t alt_states;
3475  size_t i;
3476  size_t prev_unique_state_ind;
3477  alt_state_t result;
3478  alt_state_t *result_ptr;
3479
3480  VLA_PTR_CREATE (alt_states, 150, "alt_states");
3481  for (curr_alt_state = alt_states_list;
3482       curr_alt_state != NULL;
3483       curr_alt_state = curr_alt_state->next_alt_state)
3484    VLA_PTR_ADD (alt_states, curr_alt_state);
3485  qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3486	 sizeof (alt_state_t), alt_state_cmp);
3487  if (VLA_PTR_LENGTH (alt_states) == 0)
3488    result = NULL;
3489  else
3490    {
3491      result_ptr = VLA_PTR_BEGIN (alt_states);
3492      prev_unique_state_ind = 0;
3493      for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3494        if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3495          {
3496            prev_unique_state_ind++;
3497            result_ptr [prev_unique_state_ind] = result_ptr [i];
3498          }
3499#if 0
3500      for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3501        free_alt_state (result_ptr [i]);
3502#endif
3503      VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3504      result_ptr = VLA_PTR_BEGIN (alt_states);
3505      for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3506        result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3507      result_ptr [i - 1]->next_sorted_alt_state = NULL;
3508      result = *result_ptr;
3509    }
3510  VLA_PTR_DELETE (alt_states);
3511  return result;
3512}
3513
3514/* The function checks equality of alt state lists.  Remember that the
3515   lists must be already sorted by the previous function.  */
3516static int
3517alt_states_eq (alt_states_1, alt_states_2)
3518     alt_state_t alt_states_1;
3519     alt_state_t alt_states_2;
3520{
3521  while (alt_states_1 != NULL && alt_states_2 != NULL
3522         && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3523    {
3524      alt_states_1 = alt_states_1->next_sorted_alt_state;
3525      alt_states_2 = alt_states_2->next_sorted_alt_state;
3526    }
3527  return alt_states_1 == alt_states_2;
3528}
3529
3530/* Initialization of the abstract data.  */
3531static void
3532initiate_alt_states ()
3533{
3534  first_free_alt_state = NULL;
3535}
3536
3537/* Finishing work with the abstract data.  */
3538static void
3539finish_alt_states ()
3540{
3541}
3542
3543
3544
3545/* The page contains macros for work with bits strings.  We could use
3546   standard gcc bitmap or sbitmap but it would result in difficulties
3547   of building canadian cross.  */
3548
3549/* Set bit number bitno in the bit string.  The macro is not side
3550   effect proof.  */
3551#define SET_BIT(bitstring, bitno)					  \
3552  (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3553
3554/* Test if bit number bitno in the bitstring is set.  The macro is not
3555   side effect proof.  */
3556#define TEST_BIT(bitstring, bitno)                                        \
3557  (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3558
3559
3560
3561/* This page contains abstract data `state'.  */
3562
3563/* Maximal length of reservations in cycles (>= 1).  */
3564static int max_cycles_num;
3565
3566/* Number of set elements (see type set_el_t) needed for
3567   representation of one cycle reservation.  It is depended on units
3568   number.  */
3569static int els_in_cycle_reserv;
3570
3571/* Number of set elements (see type set_el_t) needed for
3572   representation of maximal length reservation.  Deterministic
3573   reservation is stored as set (bit string) of length equal to the
3574   variable value * number of bits in set_el_t.  */
3575static int els_in_reservs;
3576
3577/* VLA for representation of array of pointers to unit
3578   declarations.  */
3579static vla_ptr_t units_container;
3580
3581/* The start address of the array.  */
3582static unit_decl_t *units_array;
3583
3584/* Empty reservation of maximal length.  */
3585static reserv_sets_t empty_reserv;
3586
3587/* The state table itself is represented by the following variable.  */
3588static htab_t state_table;
3589
3590/* VLA for representation of array of pointers to free nodes
3591   `state'.  */
3592static vla_ptr_t free_states;
3593
3594static int curr_unique_state_num;
3595
3596#ifndef NDEBUG
3597/* The following variables is maximal number of allocated nodes
3598   `state'.  */
3599static int allocated_states_num = 0;
3600#endif
3601
3602/* Allocate new reservation set.  */
3603static reserv_sets_t
3604alloc_empty_reserv_sets ()
3605{
3606  reserv_sets_t result;
3607
3608  obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3609  result = (reserv_sets_t) obstack_base (&irp);
3610  obstack_finish (&irp);
3611  memset (result, 0, els_in_reservs * sizeof (set_el_t));
3612  return result;
3613}
3614
3615/* Hash value of reservation set.  */
3616static unsigned
3617reserv_sets_hash_value (reservs)
3618     reserv_sets_t reservs;
3619{
3620  set_el_t hash_value;
3621  unsigned result;
3622  int reservs_num, i;
3623  set_el_t *reserv_ptr;
3624
3625  hash_value = 0;
3626  reservs_num = els_in_reservs;
3627  reserv_ptr = reservs;
3628  i = 0;
3629  while (reservs_num != 0)
3630    {
3631      reservs_num--;
3632      hash_value += ((*reserv_ptr >> i)
3633		     | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3634      i++;
3635      if (i == sizeof (set_el_t) * CHAR_BIT)
3636	i = 0;
3637      reserv_ptr++;
3638    }
3639  if (sizeof (set_el_t) <= sizeof (unsigned))
3640    return hash_value;
3641  result = 0;
3642  for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3643    {
3644      result += (unsigned) hash_value;
3645      hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3646    }
3647  return result;
3648}
3649
3650/* Comparison of given reservation sets.  */
3651static int
3652reserv_sets_cmp (reservs_1, reservs_2)
3653     reserv_sets_t reservs_1;
3654     reserv_sets_t reservs_2;
3655{
3656  int reservs_num;
3657  set_el_t *reserv_ptr_1;
3658  set_el_t *reserv_ptr_2;
3659
3660  if (reservs_1 == NULL || reservs_2 == NULL)
3661    abort ();
3662  reservs_num = els_in_reservs;
3663  reserv_ptr_1 = reservs_1;
3664  reserv_ptr_2 = reservs_2;
3665  while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3666    {
3667      reservs_num--;
3668      reserv_ptr_1++;
3669      reserv_ptr_2++;
3670    }
3671  if (reservs_num == 0)
3672    return 0;
3673  else if (*reserv_ptr_1 < *reserv_ptr_2)
3674    return -1;
3675  else
3676    return 1;
3677}
3678
3679/* The function checks equality of the reservation sets.  */
3680static int
3681reserv_sets_eq (reservs_1, reservs_2)
3682     reserv_sets_t reservs_1;
3683     reserv_sets_t reservs_2;
3684{
3685  return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3686}
3687
3688/* Set up in the reservation set that unit with UNIT_NUM is used on
3689   CYCLE_NUM.  */
3690static void
3691set_unit_reserv (reservs, cycle_num, unit_num)
3692     reserv_sets_t reservs;
3693     int cycle_num;
3694     int unit_num;
3695{
3696  if (cycle_num >= max_cycles_num)
3697    abort ();
3698  SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3699           * sizeof (set_el_t) * CHAR_BIT + unit_num);
3700}
3701
3702/* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3703   used on CYCLE_NUM.  */
3704static int
3705test_unit_reserv (reservs, cycle_num, unit_num)
3706     reserv_sets_t reservs;
3707     int cycle_num;
3708     int unit_num;
3709{
3710  if (cycle_num >= max_cycles_num)
3711    abort ();
3712  return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3713		   * sizeof (set_el_t) * CHAR_BIT + unit_num);
3714}
3715
3716/* The function checks that the reservation set represents no one unit
3717   reservation.  */
3718static int
3719it_is_empty_reserv_sets (operand)
3720     reserv_sets_t operand;
3721{
3722  set_el_t *reserv_ptr;
3723  int reservs_num;
3724
3725  if (operand == NULL)
3726    abort ();
3727  for (reservs_num = els_in_reservs, reserv_ptr = operand;
3728       reservs_num != 0;
3729       reserv_ptr++, reservs_num--)
3730    if (*reserv_ptr != 0)
3731      return 0;
3732  return 1;
3733}
3734
3735/* The function checks that the reservation sets are intersected,
3736   i.e. there is a unit reservation on a cycle in both reservation
3737   sets.  */
3738static int
3739reserv_sets_are_intersected (operand_1, operand_2)
3740     reserv_sets_t operand_1;
3741     reserv_sets_t operand_2;
3742{
3743  set_el_t *el_ptr_1;
3744  set_el_t *el_ptr_2;
3745  set_el_t *cycle_ptr_1;
3746  set_el_t *cycle_ptr_2;
3747  int nonzero_p;
3748
3749  if (operand_1 == NULL || operand_2 == NULL)
3750    abort ();
3751  for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3752       el_ptr_1 < operand_1 + els_in_reservs;
3753       el_ptr_1++, el_ptr_2++)
3754    if (*el_ptr_1 & *el_ptr_2)
3755      return 1;
3756  for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3757       cycle_ptr_1 < operand_1 + els_in_reservs;
3758       cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3759    {
3760      for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3761	   el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3762	   el_ptr_1++, el_ptr_2++)
3763	if (*el_ptr_1 & *el_ptr_2)
3764	  return 1;
3765      nonzero_p = 0;
3766      for (el_ptr_1 = cycle_ptr_1,
3767	     el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 1);
3768	   el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3769	   el_ptr_1++, el_ptr_2++)
3770	if (*el_ptr_1 & *el_ptr_2)
3771	  break;
3772	else if (*el_ptr_2 != 0)
3773	  nonzero_p = 1;
3774      if (nonzero_p && el_ptr_1 >= cycle_ptr_1 + els_in_cycle_reserv)
3775	return 1;
3776      for (el_ptr_1 = cycle_ptr_1,
3777	     el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 0);
3778	   el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3779	   el_ptr_1++, el_ptr_2++)
3780	/* It looks like code for exclusion but exclusion set is
3781           made as symmetric relation preliminary.  */
3782	if (*el_ptr_1 & *el_ptr_2)
3783	  return 1;
3784    }
3785  return 0;
3786}
3787
3788/* The function sets up RESULT bits by bits of OPERAND shifted on one
3789   cpu cycle.  The remaining bits of OPERAND (representing the last
3790   cycle unit reservations) are not chenged.  */
3791static void
3792reserv_sets_shift (result, operand)
3793     reserv_sets_t result;
3794     reserv_sets_t operand;
3795{
3796  int i;
3797
3798  if (result == NULL || operand == NULL || result == operand)
3799    abort ();
3800  for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3801    result [i - els_in_cycle_reserv] = operand [i];
3802}
3803
3804/* OR of the reservation sets.  */
3805static void
3806reserv_sets_or (result, operand_1, operand_2)
3807     reserv_sets_t result;
3808     reserv_sets_t operand_1;
3809     reserv_sets_t operand_2;
3810{
3811  set_el_t *el_ptr_1;
3812  set_el_t *el_ptr_2;
3813  set_el_t *result_set_el_ptr;
3814
3815  if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3816    abort ();
3817  for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3818       el_ptr_1 < operand_1 + els_in_reservs;
3819       el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3820    *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3821}
3822
3823/* AND of the reservation sets.  */
3824static void
3825reserv_sets_and (result, operand_1, operand_2)
3826     reserv_sets_t result;
3827     reserv_sets_t operand_1;
3828     reserv_sets_t operand_2;
3829{
3830  set_el_t *el_ptr_1;
3831  set_el_t *el_ptr_2;
3832  set_el_t *result_set_el_ptr;
3833
3834  if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3835    abort ();
3836  for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3837       el_ptr_1 < operand_1 + els_in_reservs;
3838       el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3839    *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3840}
3841
3842/* The function outputs string representation of units reservation on
3843   cycle START_CYCLE in the reservation set.  The function uses repeat
3844   construction if REPETITION_NUM > 1.  */
3845static void
3846output_cycle_reservs (f, reservs, start_cycle, repetition_num)
3847     FILE *f;
3848     reserv_sets_t reservs;
3849     int start_cycle;
3850     int repetition_num;
3851{
3852  int unit_num;
3853  int reserved_units_num;
3854
3855  reserved_units_num = 0;
3856  for (unit_num = 0; unit_num < description->units_num; unit_num++)
3857    if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3858                  * sizeof (set_el_t) * CHAR_BIT + unit_num))
3859      reserved_units_num++;
3860  if (repetition_num <= 0)
3861    abort ();
3862  if (repetition_num != 1 && reserved_units_num > 1)
3863    fprintf (f, "(");
3864  reserved_units_num = 0;
3865  for (unit_num = 0;
3866       unit_num < description->units_num;
3867       unit_num++)
3868    if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3869		  * sizeof (set_el_t) * CHAR_BIT + unit_num))
3870      {
3871        if (reserved_units_num != 0)
3872          fprintf (f, "+");
3873        reserved_units_num++;
3874        fprintf (f, "%s", units_array [unit_num]->name);
3875      }
3876  if (reserved_units_num == 0)
3877    fprintf (f, NOTHING_NAME);
3878  if (repetition_num <= 0)
3879    abort ();
3880  if (reserved_units_num > 1)
3881    fprintf (f, ")");
3882  if (repetition_num != 1)
3883    fprintf (f, "*%d", repetition_num);
3884}
3885
3886/* The function outputs string representation of units reservation in
3887   the reservation set.  */
3888static void
3889output_reserv_sets (f, reservs)
3890     FILE *f;
3891     reserv_sets_t reservs;
3892{
3893  int start_cycle = 0;
3894  int cycle;
3895  int repetition_num;
3896
3897  repetition_num = 0;
3898  for (cycle = 0; cycle < max_cycles_num; cycle++)
3899    if (repetition_num == 0)
3900      {
3901        repetition_num++;
3902        start_cycle = cycle;
3903      }
3904    else if (memcmp
3905             ((char *) reservs + start_cycle * els_in_cycle_reserv
3906	      * sizeof (set_el_t),
3907              (char *) reservs + cycle * els_in_cycle_reserv
3908	      * sizeof (set_el_t),
3909	      els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3910      repetition_num++;
3911    else
3912      {
3913        if (start_cycle != 0)
3914          fprintf (f, ", ");
3915        output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3916        repetition_num = 1;
3917        start_cycle = cycle;
3918      }
3919  if (start_cycle < max_cycles_num)
3920    {
3921      if (start_cycle != 0)
3922        fprintf (f, ", ");
3923      output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3924    }
3925}
3926
3927/* The following function returns free node state for AUTOMATON.  It
3928   may be new allocated node or node freed eralier.  The function also
3929   allocates reservation set if WITH_RESERVS has nonzero value.  */
3930static state_t
3931get_free_state (with_reservs, automaton)
3932     int with_reservs;
3933     automaton_t automaton;
3934{
3935  state_t result;
3936
3937  if (max_cycles_num <= 0 || automaton == NULL)
3938    abort ();
3939  if (VLA_PTR_LENGTH (free_states) != 0)
3940    {
3941      result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
3942      VLA_PTR_SHORTEN (free_states, 1);
3943      result->automaton = automaton;
3944      result->first_out_arc = NULL;
3945      result->it_was_placed_in_stack_for_NDFA_forming = 0;
3946      result->it_was_placed_in_stack_for_DFA_forming = 0;
3947      result->component_states = NULL;
3948      result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3949    }
3950  else
3951    {
3952#ifndef NDEBUG
3953      allocated_states_num++;
3954#endif
3955      result = create_node (sizeof (struct state));
3956      result->automaton = automaton;
3957      result->first_out_arc = NULL;
3958      result->unique_num = curr_unique_state_num;
3959      result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3960      curr_unique_state_num++;
3961    }
3962  if (with_reservs)
3963    {
3964      if (result->reservs == NULL)
3965        result->reservs = alloc_empty_reserv_sets ();
3966      else
3967        memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3968    }
3969  return result;
3970}
3971
3972/* The function frees node STATE.  */
3973static void
3974free_state (state)
3975     state_t state;
3976{
3977  free_alt_states (state->component_states);
3978  VLA_PTR_ADD (free_states, state);
3979}
3980
3981/* Hash value of STATE.  If STATE represents deterministic state it is
3982   simply hash value of the corresponding reservation set.  Otherwise
3983   it is formed from hash values of the component deterministic
3984   states.  One more key is order number of state automaton.  */
3985static hashval_t
3986state_hash (state)
3987     const void *state;
3988{
3989  unsigned int hash_value;
3990  alt_state_t alt_state;
3991
3992  if (((state_t) state)->component_states == NULL)
3993    hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3994  else
3995    {
3996      hash_value = 0;
3997      for (alt_state = ((state_t) state)->component_states;
3998           alt_state != NULL;
3999           alt_state = alt_state->next_sorted_alt_state)
4000        hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4001                       | (hash_value << CHAR_BIT))
4002                      + alt_state->state->unique_num);
4003    }
4004  hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4005                 | (hash_value << CHAR_BIT))
4006                + ((state_t) state)->automaton->automaton_order_num);
4007  return hash_value;
4008}
4009
4010/* Return nonzero value if the states are the same.  */
4011static int
4012state_eq_p (state_1, state_2)
4013     const void *state_1;
4014     const void *state_2;
4015{
4016  alt_state_t alt_state_1;
4017  alt_state_t alt_state_2;
4018
4019  if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
4020    return 0;
4021  else if (((state_t) state_1)->component_states == NULL
4022           && ((state_t) state_2)->component_states == NULL)
4023    return reserv_sets_eq (((state_t) state_1)->reservs,
4024			   ((state_t) state_2)->reservs);
4025  else if (((state_t) state_1)->component_states != NULL
4026           && ((state_t) state_2)->component_states != NULL)
4027    {
4028      for (alt_state_1 = ((state_t) state_1)->component_states,
4029           alt_state_2 = ((state_t) state_2)->component_states;
4030           alt_state_1 != NULL && alt_state_2 != NULL;
4031           alt_state_1 = alt_state_1->next_sorted_alt_state,
4032	   alt_state_2 = alt_state_2->next_sorted_alt_state)
4033        /* All state in the list must be already in the hash table.
4034           Also the lists must be sorted.  */
4035        if (alt_state_1->state != alt_state_2->state)
4036          return 0;
4037      return alt_state_1 == alt_state_2;
4038    }
4039  else
4040    return 0;
4041}
4042
4043/* Insert STATE into the state table.  */
4044static state_t
4045insert_state (state)
4046     state_t state;
4047{
4048  void **entry_ptr;
4049
4050  entry_ptr = htab_find_slot (state_table, (void *) state, 1);
4051  if (*entry_ptr == NULL)
4052    *entry_ptr = (void *) state;
4053  return (state_t) *entry_ptr;
4054}
4055
4056/* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
4057   deterministic STATE.  */
4058static void
4059set_state_reserv (state, cycle_num, unit_num)
4060     state_t state;
4061     int cycle_num;
4062     int unit_num;
4063{
4064  set_unit_reserv (state->reservs, cycle_num, unit_num);
4065}
4066
4067/* Return nonzero value if the deterministic states contains a
4068   reservation of the same cpu unit on the same cpu cycle.  */
4069static int
4070intersected_state_reservs_p (state1, state2)
4071     state_t state1;
4072     state_t state2;
4073{
4074  if (state1->automaton != state2->automaton)
4075    abort ();
4076  return reserv_sets_are_intersected (state1->reservs, state2->reservs);
4077}
4078
4079/* Return deterministic state (inserted into the table) which
4080   representing the automaton state whic is union of reservations of
4081   deterministic states.  */
4082static state_t
4083states_union (state1, state2)
4084     state_t state1;
4085     state_t state2;
4086{
4087  state_t result;
4088  state_t state_in_table;
4089
4090  if (state1->automaton != state2->automaton)
4091    abort ();
4092  result = get_free_state (1, state1->automaton);
4093  reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
4094  state_in_table = insert_state (result);
4095  if (result != state_in_table)
4096    {
4097      free_state (result);
4098      result = state_in_table;
4099    }
4100  return result;
4101}
4102
4103/* Return deterministic state (inserted into the table) which
4104   represent the automaton state is obtained from deterministic STATE
4105   by advancing cpu cycle.  */
4106static state_t
4107state_shift (state)
4108     state_t state;
4109{
4110  state_t result;
4111  state_t state_in_table;
4112
4113  result = get_free_state (1, state->automaton);
4114  reserv_sets_shift (result->reservs, state->reservs);
4115  state_in_table = insert_state (result);
4116  if (result != state_in_table)
4117    {
4118      free_state (result);
4119      result = state_in_table;
4120    }
4121  return result;
4122}
4123
4124/* Initialization of the abstract data.  */
4125static void
4126initiate_states ()
4127{
4128  decl_t decl;
4129  int i;
4130
4131  VLA_PTR_CREATE (units_container, description->units_num, "units_container");
4132  units_array
4133    = (description->decls_num && description->units_num
4134       ? VLA_PTR_BEGIN (units_container) : NULL);
4135  for (i = 0; i < description->decls_num; i++)
4136    {
4137      decl = description->decls [i];
4138      if (decl->mode == dm_unit)
4139	units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
4140    }
4141  max_cycles_num = description->max_insn_reserv_cycles;
4142  els_in_cycle_reserv
4143    = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
4144       / (sizeof (set_el_t) * CHAR_BIT));
4145  els_in_reservs = els_in_cycle_reserv * max_cycles_num;
4146  curr_unique_state_num = 0;
4147  initiate_alt_states ();
4148  VLA_PTR_CREATE (free_states, 1500, "free states");
4149  state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
4150  empty_reserv = alloc_empty_reserv_sets ();
4151}
4152
4153/* Finisging work with the abstract data.  */
4154static void
4155finish_states ()
4156{
4157  VLA_PTR_DELETE (units_container);
4158  htab_delete (state_table);
4159  VLA_PTR_DELETE (free_states);
4160  finish_alt_states ();
4161}
4162
4163
4164
4165/* Abstract data `arcs'.  */
4166
4167/* List of free arcs.  */
4168static arc_t first_free_arc;
4169
4170#ifndef NDEBUG
4171/* The following variables is maximal number of allocated nodes
4172   `arc'.  */
4173static int allocated_arcs_num = 0;
4174#endif
4175
4176/* The function frees node ARC.  */
4177static void
4178free_arc (arc)
4179     arc_t arc;
4180{
4181  arc->next_out_arc = first_free_arc;
4182  first_free_arc = arc;
4183}
4184
4185/* The function removes and frees ARC staring from FROM_STATE.  */
4186static void
4187remove_arc (from_state, arc)
4188     state_t from_state;
4189     arc_t arc;
4190{
4191  arc_t prev_arc;
4192  arc_t curr_arc;
4193
4194  if (arc == NULL)
4195    abort ();
4196  for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
4197       curr_arc != NULL;
4198       prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4199    if (curr_arc == arc)
4200      break;
4201  if (curr_arc == NULL)
4202    abort ();
4203  if (prev_arc == NULL)
4204    from_state->first_out_arc = arc->next_out_arc;
4205  else
4206    prev_arc->next_out_arc = arc->next_out_arc;
4207  free_arc (arc);
4208}
4209
4210/* The functions returns arc with given characteristics (or NULL if
4211   the arc does not exist).  */
4212static arc_t
4213find_arc (from_state, to_state, insn)
4214     state_t from_state;
4215     state_t to_state;
4216     ainsn_t insn;
4217{
4218  arc_t arc;
4219
4220  for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4221    if (arc->to_state == to_state && arc->insn == insn)
4222      return arc;
4223  return NULL;
4224}
4225
4226/* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4227   and with given STATE_ALTS.  The function returns added arc (or
4228   already existing arc).  */
4229static arc_t
4230add_arc (from_state, to_state, ainsn, state_alts)
4231     state_t from_state;
4232     state_t to_state;
4233     ainsn_t ainsn;
4234     int state_alts;
4235{
4236  arc_t new_arc;
4237
4238  new_arc = find_arc (from_state, to_state, ainsn);
4239  if (new_arc != NULL)
4240    return new_arc;
4241  if (first_free_arc == NULL)
4242    {
4243#ifndef NDEBUG
4244      allocated_arcs_num++;
4245#endif
4246      new_arc = create_node (sizeof (struct arc));
4247      new_arc->to_state = NULL;
4248      new_arc->insn = NULL;
4249      new_arc->next_out_arc = NULL;
4250    }
4251  else
4252    {
4253      new_arc = first_free_arc;
4254      first_free_arc =  first_free_arc->next_out_arc;
4255    }
4256  new_arc->to_state = to_state;
4257  new_arc->insn = ainsn;
4258  ainsn->arc_exists_p = 1;
4259  new_arc->next_out_arc = from_state->first_out_arc;
4260  from_state->first_out_arc = new_arc;
4261  new_arc->next_arc_marked_by_insn = NULL;
4262  new_arc->state_alts = state_alts;
4263  return new_arc;
4264}
4265
4266/* The function returns the first arc starting from STATE.  */
4267static arc_t
4268first_out_arc (state)
4269     state_t state;
4270{
4271  return state->first_out_arc;
4272}
4273
4274/* The function returns next out arc after ARC.  */
4275static arc_t
4276next_out_arc (arc)
4277     arc_t arc;
4278{
4279  return arc->next_out_arc;
4280}
4281
4282/* Initialization of the abstract data.  */
4283static void
4284initiate_arcs ()
4285{
4286  first_free_arc = NULL;
4287}
4288
4289/* Finishing work with the abstract data.  */
4290static void
4291finish_arcs ()
4292{
4293}
4294
4295
4296
4297/* Abstract data `automata lists'.  */
4298
4299/* List of free states.  */
4300static automata_list_el_t first_free_automata_list_el;
4301
4302/* The list being formed.  */
4303static automata_list_el_t current_automata_list;
4304
4305/* Hash table of automata lists.  */
4306static htab_t automata_list_table;
4307
4308/* The following function returns free automata list el.  It may be
4309   new allocated node or node freed earlier.  */
4310static automata_list_el_t
4311get_free_automata_list_el ()
4312{
4313  automata_list_el_t result;
4314
4315  if (first_free_automata_list_el != NULL)
4316    {
4317      result = first_free_automata_list_el;
4318      first_free_automata_list_el
4319	= first_free_automata_list_el->next_automata_list_el;
4320    }
4321  else
4322    result = create_node (sizeof (struct automata_list_el));
4323  result->automaton = NULL;
4324  result->next_automata_list_el = NULL;
4325  return result;
4326}
4327
4328/* The function frees node AUTOMATA_LIST_EL.  */
4329static void
4330free_automata_list_el (automata_list_el)
4331     automata_list_el_t automata_list_el;
4332{
4333  if (automata_list_el == NULL)
4334    return;
4335  automata_list_el->next_automata_list_el = first_free_automata_list_el;
4336  first_free_automata_list_el = automata_list_el;
4337}
4338
4339/* The function frees list AUTOMATA_LIST.  */
4340static void
4341free_automata_list (automata_list)
4342     automata_list_el_t automata_list;
4343{
4344  automata_list_el_t curr_automata_list_el;
4345  automata_list_el_t next_automata_list_el;
4346
4347  for (curr_automata_list_el = automata_list;
4348       curr_automata_list_el != NULL;
4349       curr_automata_list_el = next_automata_list_el)
4350    {
4351      next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4352      free_automata_list_el (curr_automata_list_el);
4353    }
4354}
4355
4356/* Hash value of AUTOMATA_LIST.  */
4357static hashval_t
4358automata_list_hash (automata_list)
4359     const void *automata_list;
4360{
4361  unsigned int hash_value;
4362  automata_list_el_t curr_automata_list_el;
4363
4364  hash_value = 0;
4365  for (curr_automata_list_el = (automata_list_el_t) automata_list;
4366       curr_automata_list_el != NULL;
4367       curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4368    hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4369		   | (hash_value << CHAR_BIT))
4370		  + curr_automata_list_el->automaton->automaton_order_num);
4371  return hash_value;
4372}
4373
4374/* Return nonzero value if the automata_lists are the same.  */
4375static int
4376automata_list_eq_p (automata_list_1, automata_list_2)
4377     const void *automata_list_1;
4378     const void *automata_list_2;
4379{
4380  automata_list_el_t automata_list_el_1;
4381  automata_list_el_t automata_list_el_2;
4382
4383  for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4384	 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4385       automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4386       automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4387	 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4388    if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4389      return 0;
4390  return automata_list_el_1 == automata_list_el_2;
4391}
4392
4393/* Initialization of the abstract data.  */
4394static void
4395initiate_automata_lists ()
4396{
4397  first_free_automata_list_el = NULL;
4398  automata_list_table = htab_create (1500, automata_list_hash,
4399				     automata_list_eq_p, (htab_del) 0);
4400}
4401
4402/* The following function starts new automata list and makes it the
4403   current one.  */
4404static void
4405automata_list_start ()
4406{
4407  current_automata_list = NULL;
4408}
4409
4410/* The following function adds AUTOMATON to the current list.  */
4411static void
4412automata_list_add (automaton)
4413     automaton_t automaton;
4414{
4415  automata_list_el_t el;
4416
4417  el = get_free_automata_list_el ();
4418  el->automaton = automaton;
4419  el->next_automata_list_el = current_automata_list;
4420  current_automata_list = el;
4421}
4422
4423/* The following function finishes forming the current list, inserts
4424   it into the table and returns it.  */
4425static automata_list_el_t
4426automata_list_finish ()
4427{
4428  void **entry_ptr;
4429
4430  if (current_automata_list == NULL)
4431    return NULL;
4432  entry_ptr = htab_find_slot (automata_list_table,
4433			      (void *) current_automata_list, 1);
4434  if (*entry_ptr == NULL)
4435    *entry_ptr = (void *) current_automata_list;
4436  else
4437    free_automata_list (current_automata_list);
4438  current_automata_list = NULL;
4439  return (automata_list_el_t) *entry_ptr;
4440}
4441
4442/* Finishing work with the abstract data.  */
4443static void
4444finish_automata_lists ()
4445{
4446  htab_delete (automata_list_table);
4447}
4448
4449
4450
4451/* The page contains abstract data for work with exclusion sets (see
4452   exclusion_set in file rtl.def).  */
4453
4454/* The following variable refers to an exclusion set returned by
4455   get_excl_set.  This is bit string of length equal to cpu units
4456   number.  If exclusion set for given unit contains 1 for a unit,
4457   then simultaneous reservation of the units is prohibited.  */
4458static reserv_sets_t excl_set;
4459
4460/* The array contains exclusion sets for each unit.  */
4461static reserv_sets_t *unit_excl_set_table;
4462
4463/* The following function forms the array containing exclusion sets
4464   for each unit.  */
4465static void
4466initiate_excl_sets ()
4467{
4468  decl_t decl;
4469  reserv_sets_t unit_excl_set;
4470  unit_set_el_t el;
4471  int i;
4472
4473  obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4474  excl_set = (reserv_sets_t) obstack_base (&irp);
4475  obstack_finish (&irp);
4476  obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4477  unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4478  obstack_finish (&irp);
4479  /* Evaluate unit exclusion sets.  */
4480  for (i = 0; i < description->decls_num; i++)
4481    {
4482      decl = description->decls [i];
4483      if (decl->mode == dm_unit)
4484	{
4485	  obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4486	  unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4487	  obstack_finish (&irp);
4488	  memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4489	  for (el = DECL_UNIT (decl)->excl_list;
4490	       el != NULL;
4491	       el = el->next_unit_set_el)
4492            SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4493          unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4494        }
4495    }
4496}
4497
4498/* The function sets up and return EXCL_SET which is union of
4499   exclusion sets for each unit in IN_SET.  */
4500static reserv_sets_t
4501get_excl_set (in_set)
4502     reserv_sets_t in_set;
4503{
4504  int excl_char_num;
4505  int chars_num;
4506  int i;
4507  int start_unit_num;
4508  int unit_num;
4509
4510  chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4511  memset (excl_set, 0, chars_num);
4512  for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4513    if (((unsigned char *) in_set) [excl_char_num])
4514      for (i = CHAR_BIT - 1; i >= 0; i--)
4515	if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4516	  {
4517	    start_unit_num = excl_char_num * CHAR_BIT + i;
4518	    if (start_unit_num >= description->units_num)
4519	      return excl_set;
4520	    for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4521	      {
4522		excl_set [unit_num]
4523		  |= unit_excl_set_table [start_unit_num] [unit_num];
4524	      }
4525	  }
4526  return excl_set;
4527}
4528
4529
4530
4531/* The page contains abstract data for work with presence/absence sets
4532   (see presence_set/absence_set in file rtl.def).  */
4533
4534/* The following variables refer to correspondingly a presence and an
4535   absence set returned by get_presence_absence_set.  This is bit
4536   string of length equal to cpu units number.  */
4537static reserv_sets_t presence_set, absence_set;
4538
4539/* The following arrays contain correspondingly presence and absence
4540   sets for each unit.  */
4541static reserv_sets_t *unit_presence_set_table, *unit_absence_set_table;
4542
4543/* The following function forms the array containing presence and
4544   absence sets for each unit */
4545static void
4546initiate_presence_absence_sets ()
4547{
4548  decl_t decl;
4549  reserv_sets_t unit_set;
4550  unit_set_el_t el;
4551  int i;
4552
4553  obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4554  presence_set = (reserv_sets_t) obstack_base (&irp);
4555  obstack_finish (&irp);
4556  obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4557  unit_presence_set_table = (reserv_sets_t *) obstack_base (&irp);
4558  obstack_finish (&irp);
4559  obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4560  absence_set = (reserv_sets_t) obstack_base (&irp);
4561  obstack_finish (&irp);
4562  obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4563  unit_absence_set_table = (reserv_sets_t *) obstack_base (&irp);
4564  obstack_finish (&irp);
4565  /* Evaluate unit presence/absence sets.  */
4566  for (i = 0; i < description->decls_num; i++)
4567    {
4568      decl = description->decls [i];
4569      if (decl->mode == dm_unit)
4570	{
4571	  obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4572	  unit_set = (reserv_sets_t) obstack_base (&irp);
4573	  obstack_finish (&irp);
4574	  memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4575	  for (el = DECL_UNIT (decl)->presence_list;
4576	       el != NULL;
4577	       el = el->next_unit_set_el)
4578            SET_BIT (unit_set, el->unit_decl->unit_num);
4579          unit_presence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4580
4581	  obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4582	  unit_set = (reserv_sets_t) obstack_base (&irp);
4583	  obstack_finish (&irp);
4584	  memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4585	  for (el = DECL_UNIT (decl)->absence_list;
4586	       el != NULL;
4587	       el = el->next_unit_set_el)
4588            SET_BIT (unit_set, el->unit_decl->unit_num);
4589          unit_absence_set_table [DECL_UNIT (decl)->unit_num] = unit_set;
4590        }
4591    }
4592}
4593
4594/* The function sets up and return PRESENCE_SET (if PRESENCE_P) or
4595   ABSENCE_SET which is union of corresponding sets for each unit in
4596   IN_SET.  */
4597static reserv_sets_t
4598get_presence_absence_set (in_set, presence_p)
4599     reserv_sets_t in_set;
4600     int presence_p;
4601{
4602  int char_num;
4603  int chars_num;
4604  int i;
4605  int start_unit_num;
4606  int unit_num;
4607
4608  chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4609  if (presence_p)
4610    memset (presence_set, 0, chars_num);
4611  else
4612    memset (absence_set, 0, chars_num);
4613  for (char_num = 0; char_num < chars_num; char_num++)
4614    if (((unsigned char *) in_set) [char_num])
4615      for (i = CHAR_BIT - 1; i >= 0; i--)
4616	if ((((unsigned char *) in_set) [char_num] >> i) & 1)
4617	  {
4618	    start_unit_num = char_num * CHAR_BIT + i;
4619	    if (start_unit_num >= description->units_num)
4620	      return (presence_p ? presence_set : absence_set);
4621	    for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4622	      if (presence_p)
4623		presence_set [unit_num]
4624		  |= unit_presence_set_table [start_unit_num] [unit_num];
4625	      else
4626		absence_set [unit_num]
4627		  |= unit_absence_set_table [start_unit_num] [unit_num];
4628	  }
4629  return (presence_p ? presence_set : absence_set);
4630}
4631
4632
4633
4634/* This page contains code for transformation of original reservations
4635   described in .md file.  The main goal of transformations is
4636   simplifying reservation and lifting up all `|' on the top of IR
4637   reservation representation.  */
4638
4639
4640/* The following function makes copy of IR representation of
4641   reservation.  The function also substitutes all reservations
4642   defined by define_reservation by corresponding value during making
4643   the copy.  */
4644static regexp_t
4645copy_insn_regexp (regexp)
4646     regexp_t regexp;
4647{
4648  regexp_t  result;
4649  int i;
4650
4651  if (regexp->mode == rm_reserv)
4652    result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4653  else if (regexp->mode == rm_unit)
4654    result = copy_node (regexp, sizeof (struct regexp));
4655  else if (regexp->mode == rm_repeat)
4656    {
4657      result = copy_node (regexp, sizeof (struct regexp));
4658      REGEXP_REPEAT (result)->regexp
4659        = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4660    }
4661  else if (regexp->mode == rm_sequence)
4662    {
4663      result = copy_node (regexp,
4664                          sizeof (struct regexp) + sizeof (regexp_t)
4665			  * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4666      for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4667	REGEXP_SEQUENCE (result)->regexps [i]
4668	  = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4669    }
4670  else if (regexp->mode == rm_allof)
4671    {
4672      result = copy_node (regexp,
4673                          sizeof (struct regexp) + sizeof (regexp_t)
4674			  * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4675      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4676	REGEXP_ALLOF (result)->regexps [i]
4677	  = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4678    }
4679  else if (regexp->mode == rm_oneof)
4680    {
4681      result = copy_node (regexp,
4682                          sizeof (struct regexp) + sizeof (regexp_t)
4683			  * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4684      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4685	REGEXP_ONEOF (result)->regexps [i]
4686	  = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4687    }
4688  else
4689    {
4690      if (regexp->mode != rm_nothing)
4691	abort ();
4692      result = copy_node (regexp, sizeof (struct regexp));
4693    }
4694  return result;
4695}
4696
4697/* The following variable is set up 1 if a transformation has been
4698   applied.  */
4699static int regexp_transformed_p;
4700
4701/* The function makes transformation
4702   A*N -> A, A, ...  */
4703static regexp_t
4704transform_1 (regexp)
4705     regexp_t regexp;
4706{
4707  int i;
4708  int repeat_num;
4709  regexp_t operand;
4710  pos_t pos;
4711
4712  if (regexp->mode == rm_repeat)
4713    {
4714      repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4715      if (repeat_num <= 1)
4716	abort ();
4717      operand = REGEXP_REPEAT (regexp)->regexp;
4718      pos = regexp->mode;
4719      regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4720			    * (repeat_num - 1));
4721      regexp->mode = rm_sequence;
4722      regexp->pos = pos;
4723      REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4724      for (i = 0; i < repeat_num; i++)
4725	REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4726      regexp_transformed_p = 1;
4727    }
4728  return regexp;
4729}
4730
4731/* The function makes transformations
4732   ...,(A,B,...),C,... -> ...,A,B,...,C,...
4733   ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4734   ...|(A|B|...)|C|... -> ...|A|B|...|C|...  */
4735static regexp_t
4736transform_2 (regexp)
4737     regexp_t regexp;
4738{
4739  if (regexp->mode == rm_sequence)
4740    {
4741      regexp_t sequence = NULL;
4742      regexp_t result;
4743      int sequence_index = 0;
4744      int i, j;
4745
4746      for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4747	if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4748	  {
4749	    sequence_index = i;
4750	    sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4751	    break;
4752	  }
4753      if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4754	{
4755	  if ( REGEXP_SEQUENCE (sequence)->regexps_num <= 1
4756	      || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4757	    abort ();
4758	  result = create_node (sizeof (struct regexp)
4759                                + sizeof (regexp_t)
4760				* (REGEXP_SEQUENCE (regexp)->regexps_num
4761                                   + REGEXP_SEQUENCE (sequence)->regexps_num
4762                                   - 2));
4763	  result->mode = rm_sequence;
4764	  result->pos = regexp->pos;
4765	  REGEXP_SEQUENCE (result)->regexps_num
4766            = (REGEXP_SEQUENCE (regexp)->regexps_num
4767               + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4768	  for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4769            if (i < sequence_index)
4770              REGEXP_SEQUENCE (result)->regexps [i]
4771                = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4772            else if (i > sequence_index)
4773              REGEXP_SEQUENCE (result)->regexps
4774                [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4775                = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4776            else
4777              for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4778                REGEXP_SEQUENCE (result)->regexps [i + j]
4779                  = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4780	  regexp_transformed_p = 1;
4781	  regexp = result;
4782	}
4783    }
4784  else if (regexp->mode == rm_allof)
4785    {
4786      regexp_t allof = NULL;
4787      regexp_t result;
4788      int allof_index = 0;
4789      int i, j;
4790
4791      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4792	if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4793	  {
4794	    allof_index = i;
4795	    allof = REGEXP_ALLOF (regexp)->regexps [i];
4796	    break;
4797	  }
4798      if (i < REGEXP_ALLOF (regexp)->regexps_num)
4799	{
4800	  if (REGEXP_ALLOF (allof)->regexps_num <= 1
4801	      || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4802	    abort ();
4803	  result = create_node (sizeof (struct regexp)
4804                                + sizeof (regexp_t)
4805				* (REGEXP_ALLOF (regexp)->regexps_num
4806                                   + REGEXP_ALLOF (allof)->regexps_num - 2));
4807	  result->mode = rm_allof;
4808	  result->pos = regexp->pos;
4809	  REGEXP_ALLOF (result)->regexps_num
4810            = (REGEXP_ALLOF (regexp)->regexps_num
4811               + REGEXP_ALLOF (allof)->regexps_num - 1);
4812	  for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4813            if (i < allof_index)
4814              REGEXP_ALLOF (result)->regexps [i]
4815                = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4816            else if (i > allof_index)
4817              REGEXP_ALLOF (result)->regexps
4818                [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4819                = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4820            else
4821              for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4822                REGEXP_ALLOF (result)->regexps [i + j]
4823                  = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4824	  regexp_transformed_p = 1;
4825	  regexp = result;
4826	}
4827    }
4828  else if (regexp->mode == rm_oneof)
4829    {
4830      regexp_t oneof = NULL;
4831      regexp_t result;
4832      int oneof_index = 0;
4833      int i, j;
4834
4835      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4836	if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4837	  {
4838	    oneof_index = i;
4839	    oneof = REGEXP_ONEOF (regexp)->regexps [i];
4840	    break;
4841	  }
4842      if (i < REGEXP_ONEOF (regexp)->regexps_num)
4843	{
4844	  if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4845	      || REGEXP_ONEOF (regexp)->regexps_num <= 1)
4846	    abort ();
4847	  result = create_node (sizeof (struct regexp)
4848				+ sizeof (regexp_t)
4849				* (REGEXP_ONEOF (regexp)->regexps_num
4850                                   + REGEXP_ONEOF (oneof)->regexps_num - 2));
4851	  result->mode = rm_oneof;
4852	  result->pos = regexp->pos;
4853	  REGEXP_ONEOF (result)->regexps_num
4854	    = (REGEXP_ONEOF (regexp)->regexps_num
4855               + REGEXP_ONEOF (oneof)->regexps_num - 1);
4856	  for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4857            if (i < oneof_index)
4858              REGEXP_ONEOF (result)->regexps [i]
4859                = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4860            else if (i > oneof_index)
4861              REGEXP_ONEOF (result)->regexps
4862                [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4863                = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4864            else
4865              for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4866                REGEXP_ONEOF (result)->regexps [i + j]
4867                  = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4868	  regexp_transformed_p = 1;
4869	  regexp = result;
4870	}
4871    }
4872  return regexp;
4873}
4874
4875/* The function makes transformations
4876   ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4877   ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4878   ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4879   ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),...  */
4880static regexp_t
4881transform_3 (regexp)
4882     regexp_t regexp;
4883{
4884  if (regexp->mode == rm_sequence)
4885    {
4886      regexp_t oneof = NULL;
4887      int oneof_index = 0;
4888      regexp_t result;
4889      regexp_t sequence;
4890      int i, j;
4891
4892      for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4893	if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4894	  {
4895	    oneof_index = i;
4896	    oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4897	    break;
4898	  }
4899      if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4900	{
4901	  if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4902	      || REGEXP_SEQUENCE (regexp)->regexps_num <= 1)
4903	    abort ();
4904	  result = create_node (sizeof (struct regexp)
4905				+ sizeof (regexp_t)
4906				* (REGEXP_ONEOF (oneof)->regexps_num - 1));
4907	  result->mode = rm_oneof;
4908	  result->pos = regexp->pos;
4909	  REGEXP_ONEOF (result)->regexps_num
4910	    = REGEXP_ONEOF (oneof)->regexps_num;
4911	  for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4912	    {
4913	      sequence
4914                = create_node (sizeof (struct regexp)
4915                               + sizeof (regexp_t)
4916                               * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4917	      sequence->mode = rm_sequence;
4918	      sequence->pos = regexp->pos;
4919	      REGEXP_SEQUENCE (sequence)->regexps_num
4920                = REGEXP_SEQUENCE (regexp)->regexps_num;
4921              REGEXP_ONEOF (result)->regexps [i] = sequence;
4922	      for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4923		if (j != oneof_index)
4924		  REGEXP_SEQUENCE (sequence)->regexps [j]
4925		    = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4926		else
4927		  REGEXP_SEQUENCE (sequence)->regexps [j]
4928		    = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4929	    }
4930	  regexp_transformed_p = 1;
4931	  regexp = result;
4932	}
4933    }
4934  else if (regexp->mode == rm_allof)
4935    {
4936      regexp_t oneof = NULL, seq;
4937      int oneof_index = 0, max_seq_length, allof_length;
4938      regexp_t result;
4939      regexp_t allof = NULL, allof_op = NULL;
4940      int i, j;
4941
4942      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4943	if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4944	  {
4945	    oneof_index = i;
4946	    oneof = REGEXP_ALLOF (regexp)->regexps [i];
4947	    break;
4948	  }
4949      if (i < REGEXP_ALLOF (regexp)->regexps_num)
4950	{
4951	  if (REGEXP_ONEOF (oneof)->regexps_num <= 1
4952	      || REGEXP_ALLOF (regexp)->regexps_num <= 1)
4953	    abort ();
4954	  result = create_node (sizeof (struct regexp)
4955				+ sizeof (regexp_t)
4956				* (REGEXP_ONEOF (oneof)->regexps_num - 1));
4957	  result->mode = rm_oneof;
4958	  result->pos = regexp->pos;
4959	  REGEXP_ONEOF (result)->regexps_num
4960	    = REGEXP_ONEOF (oneof)->regexps_num;
4961	  for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4962	    {
4963	      allof
4964		= create_node (sizeof (struct regexp)
4965                               + sizeof (regexp_t)
4966			       * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4967	      allof->mode = rm_allof;
4968	      allof->pos = regexp->pos;
4969	      REGEXP_ALLOF (allof)->regexps_num
4970                = REGEXP_ALLOF (regexp)->regexps_num;
4971              REGEXP_ONEOF (result)->regexps [i] = allof;
4972	      for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4973		if (j != oneof_index)
4974		  REGEXP_ALLOF (allof)->regexps [j]
4975		    = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4976		else
4977		  REGEXP_ALLOF (allof)->regexps [j]
4978		    = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4979	    }
4980	  regexp_transformed_p = 1;
4981	  regexp = result;
4982	}
4983      max_seq_length = 0;
4984      if (regexp->mode == rm_allof)
4985	for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4986	  {
4987	    if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_sequence)
4988	      {
4989		seq = REGEXP_ALLOF (regexp)->regexps [i];
4990		if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4991		  max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4992	      }
4993	    else if (REGEXP_ALLOF (regexp)->regexps [i]->mode != rm_unit)
4994	      {
4995		max_seq_length = 0;
4996		break;
4997	      }
4998	  }
4999      if (max_seq_length != 0)
5000	{
5001	  if (max_seq_length == 1 || REGEXP_ALLOF (regexp)->regexps_num <= 1)
5002	    abort ();
5003	  result = create_node (sizeof (struct regexp)
5004				+ sizeof (regexp_t) * (max_seq_length - 1));
5005	  result->mode = rm_sequence;
5006	  result->pos = regexp->pos;
5007	  REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
5008	  for (i = 0; i < max_seq_length; i++)
5009	    {
5010	      allof_length = 0;
5011	      for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5012		if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5013		    && (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5014					      ->regexps [j])->regexps_num)))
5015		  {
5016		    allof_op
5017		      = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)->regexps [j])
5018			 ->regexps [i]);
5019		    allof_length++;
5020		  }
5021		else if (i == 0
5022			 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5023			     == rm_unit))
5024		  {
5025		    allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5026		    allof_length++;
5027		  }
5028	      if (allof_length == 1)
5029		REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
5030	      else
5031		{
5032		  allof = create_node (sizeof (struct regexp)
5033				       + sizeof (regexp_t)
5034				       * (allof_length - 1));
5035		  allof->mode = rm_allof;
5036		  allof->pos = regexp->pos;
5037		  REGEXP_ALLOF (allof)->regexps_num = allof_length;
5038		  REGEXP_SEQUENCE (result)->regexps [i] = allof;
5039		  allof_length = 0;
5040		  for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
5041		    if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
5042			&& (i <
5043			    (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5044					      ->regexps [j])->regexps_num)))
5045		      {
5046			allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
5047						     ->regexps [j])
5048				    ->regexps [i]);
5049			REGEXP_ALLOF (allof)->regexps [allof_length]
5050			  = allof_op;
5051			allof_length++;
5052		      }
5053		    else if (i == 0
5054			     && (REGEXP_ALLOF (regexp)->regexps [j]->mode
5055				 == rm_unit))
5056		      {
5057			allof_op = REGEXP_ALLOF (regexp)->regexps [j];
5058			REGEXP_ALLOF (allof)->regexps [allof_length]
5059			  = allof_op;
5060			allof_length++;
5061		      }
5062		}
5063	    }
5064	  regexp_transformed_p = 1;
5065	  regexp = result;
5066	}
5067    }
5068  return regexp;
5069}
5070
5071/* The function traverses IR of reservation and applies transformations
5072   implemented by FUNC.  */
5073static regexp_t
5074regexp_transform_func (regexp, func)
5075     regexp_t regexp;
5076     regexp_t (*func) PARAMS ((regexp_t regexp));
5077{
5078  int i;
5079
5080  if (regexp->mode == rm_sequence)
5081    for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5082      REGEXP_SEQUENCE (regexp)->regexps [i]
5083	= regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i], func);
5084  else if (regexp->mode == rm_allof)
5085    for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5086      REGEXP_ALLOF (regexp)->regexps [i]
5087	= regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
5088  else if (regexp->mode == rm_oneof)
5089    for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
5090      REGEXP_ONEOF (regexp)->regexps [i]
5091	= regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
5092  else if (regexp->mode == rm_repeat)
5093    REGEXP_REPEAT (regexp)->regexp
5094      = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
5095  else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
5096    abort ();
5097  return (*func) (regexp);
5098}
5099
5100/* The function applies all transformations for IR representation of
5101   reservation REGEXP.  */
5102static regexp_t
5103transform_regexp (regexp)
5104     regexp_t regexp;
5105{
5106  regexp = regexp_transform_func (regexp, transform_1);
5107  do
5108    {
5109      regexp_transformed_p = 0;
5110      regexp = regexp_transform_func (regexp, transform_2);
5111      regexp = regexp_transform_func (regexp, transform_3);
5112    }
5113  while (regexp_transformed_p);
5114  return regexp;
5115}
5116
5117/* The function applys all transformations for reservations of all
5118   insn declarations.  */
5119static void
5120transform_insn_regexps ()
5121{
5122  decl_t decl;
5123  int i;
5124
5125  transform_time = create_ticker ();
5126  add_advance_cycle_insn_decl ();
5127  fprintf (stderr, "Reservation transformation...");
5128  fflush (stderr);
5129  for (i = 0; i < description->decls_num; i++)
5130    {
5131      decl = description->decls [i];
5132      if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
5133	DECL_INSN_RESERV (decl)->transformed_regexp
5134	  = transform_regexp (copy_insn_regexp
5135			      (DECL_INSN_RESERV (decl)->regexp));
5136    }
5137  fprintf (stderr, "done\n");
5138  ticker_off (&transform_time);
5139  fflush (stderr);
5140}
5141
5142
5143
5144/* The following variable is an array indexed by cycle.  Each element
5145   contains cyclic list of units which should be in the same cycle.  */
5146static unit_decl_t *the_same_automaton_lists;
5147
5148/* The function processes all alternative reservations on CYCLE in
5149   given REGEXP to check the UNIT is not reserved on the all
5150   alternatives.  If it is true, the unit should be in the same
5151   automaton with other analogous units reserved on CYCLE in given
5152   REGEXP.  */
5153static void
5154process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
5155     regexp_t unit;
5156     regexp_t regexp;
5157     int cycle;
5158{
5159  int i, k;
5160  regexp_t seq, allof;
5161  unit_decl_t unit_decl, last;
5162
5163  if (regexp == NULL || regexp->mode != rm_oneof)
5164    abort ();
5165  unit_decl = REGEXP_UNIT (unit)->unit_decl;
5166  for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5167    {
5168      seq = REGEXP_ONEOF (regexp)->regexps [i];
5169      if (seq->mode == rm_sequence)
5170	{
5171	  if (cycle >= REGEXP_SEQUENCE (seq)->regexps_num)
5172	    break;
5173	  allof = REGEXP_SEQUENCE (seq)->regexps [cycle];
5174	  if (allof->mode == rm_allof)
5175	    {
5176	      for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5177		if (REGEXP_ALLOF (allof)->regexps [k]->mode == rm_unit
5178		    && (REGEXP_UNIT (REGEXP_ALLOF (allof)->regexps [k])
5179			->unit_decl == unit_decl))
5180		  break;
5181	      if (k >= REGEXP_ALLOF (allof)->regexps_num)
5182		break;
5183	    }
5184	  else if (allof->mode == rm_unit
5185		   && REGEXP_UNIT (allof)->unit_decl != unit_decl)
5186	    break;
5187	}
5188      else if (cycle != 0)
5189	break;
5190      else if (seq->mode == rm_allof)
5191	{
5192	  for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5193	    if (REGEXP_ALLOF (seq)->regexps [k]->mode == rm_unit
5194		&& (REGEXP_UNIT (REGEXP_ALLOF (seq)->regexps [k])->unit_decl
5195		    == unit_decl))
5196	      break;
5197	  if (k >= REGEXP_ALLOF (seq)->regexps_num)
5198	    break;
5199	}
5200      else if (seq->mode == rm_unit
5201	       && REGEXP_UNIT (seq)->unit_decl != unit_decl)
5202	break;
5203    }
5204  if (i >= 0)
5205    {
5206      if (the_same_automaton_lists [cycle] == NULL)
5207	the_same_automaton_lists [cycle] = unit_decl;
5208      else
5209	{
5210	  for (last = the_same_automaton_lists [cycle];;)
5211	    {
5212	      if (last == unit_decl)
5213		return;
5214	      if (last->the_same_automaton_unit
5215		  == the_same_automaton_lists [cycle])
5216		break;
5217	      last = last->the_same_automaton_unit;
5218	    }
5219	  last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
5220	  unit_decl->the_same_automaton_unit
5221	    = the_same_automaton_lists [cycle];
5222	}
5223    }
5224}
5225
5226/* The function processes given REGEXP to find units which should be
5227   in the same automaton.  */
5228static void
5229form_the_same_automaton_unit_lists_from_regexp (regexp)
5230     regexp_t regexp;
5231{
5232  int i, j, k;
5233  regexp_t seq, allof, unit;
5234
5235  if (regexp == NULL || regexp->mode != rm_oneof)
5236    return;
5237  for (i = 0; i < description->max_insn_reserv_cycles; i++)
5238    the_same_automaton_lists [i] = NULL;
5239  for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5240    {
5241      seq = REGEXP_ONEOF (regexp)->regexps [i];
5242      if (seq->mode == rm_sequence)
5243	for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5244	  {
5245	    allof = REGEXP_SEQUENCE (seq)->regexps [j];
5246	    if (allof->mode == rm_allof)
5247	      for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5248		{
5249		  unit = REGEXP_ALLOF (allof)->regexps [k];
5250		  if (unit->mode == rm_unit)
5251		    process_unit_to_form_the_same_automaton_unit_lists
5252		      (unit, regexp, j);
5253		  else if (unit->mode != rm_nothing)
5254		    abort ();
5255		}
5256	    else if (allof->mode == rm_unit)
5257	      process_unit_to_form_the_same_automaton_unit_lists
5258		(allof, regexp, j);
5259	    else if (allof->mode != rm_nothing)
5260	      abort ();
5261	  }
5262      else if (seq->mode == rm_allof)
5263	for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5264	  {
5265	    unit = REGEXP_ALLOF (seq)->regexps [k];
5266	    if (unit->mode == rm_unit)
5267	      process_unit_to_form_the_same_automaton_unit_lists
5268		(unit, regexp, 0);
5269	    else if (unit->mode != rm_nothing)
5270	      abort ();
5271	  }
5272      else if (seq->mode == rm_unit)
5273	process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
5274      else if (seq->mode != rm_nothing)
5275	abort ();
5276    }
5277}
5278
5279/* The function initializes data to search for units which should be
5280   in the same automaton and call function
5281   `form_the_same_automaton_unit_lists_from_regexp' for each insn
5282   reservation regexp.  */
5283static void
5284form_the_same_automaton_unit_lists ()
5285{
5286  decl_t decl;
5287  int i;
5288
5289  the_same_automaton_lists
5290    = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
5291			       * sizeof (unit_decl_t));
5292  for (i = 0; i < description->decls_num; i++)
5293    {
5294      decl = description->decls [i];
5295      if (decl->mode == dm_unit)
5296	{
5297	  DECL_UNIT (decl)->the_same_automaton_message_reported_p = FALSE;
5298	  DECL_UNIT (decl)->the_same_automaton_unit = DECL_UNIT (decl);
5299	}
5300    }
5301  for (i = 0; i < description->decls_num; i++)
5302    {
5303      decl = description->decls [i];
5304      if (decl->mode == dm_insn_reserv)
5305	form_the_same_automaton_unit_lists_from_regexp
5306	  (DECL_INSN_RESERV (decl)->transformed_regexp);
5307    }
5308  free (the_same_automaton_lists);
5309}
5310
5311/* The function finds units which should be in the same automaton and,
5312   if they are not, reports about it.  */
5313static void
5314check_unit_distributions_to_automata ()
5315{
5316  decl_t decl;
5317  unit_decl_t start_unit_decl, unit_decl;
5318  int i;
5319
5320  form_the_same_automaton_unit_lists ();
5321  for (i = 0; i < description->decls_num; i++)
5322    {
5323      decl = description->decls [i];
5324      if (decl->mode == dm_unit)
5325	{
5326	  start_unit_decl = DECL_UNIT (decl);
5327	  if (!start_unit_decl->the_same_automaton_message_reported_p)
5328	    for (unit_decl = start_unit_decl->the_same_automaton_unit;
5329		 unit_decl != start_unit_decl;
5330		 unit_decl = unit_decl->the_same_automaton_unit)
5331	      if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
5332		{
5333		  error ("Units `%s' and `%s' should be in the same automaton",
5334			 start_unit_decl->name, unit_decl->name);
5335		  unit_decl->the_same_automaton_message_reported_p = TRUE;
5336		}
5337	}
5338    }
5339}
5340
5341
5342
5343/* The page contains code for building alt_states (see comments for
5344   IR) describing all possible insns reservations of an automaton.  */
5345
5346/* Current state being formed for which the current alt_state
5347   refers.  */
5348static state_t state_being_formed;
5349
5350/* Current alt_state being formed.  */
5351static alt_state_t alt_state_being_formed;
5352
5353/* This recursive function processes `,' and units in reservation
5354   REGEXP for forming alt_states of AUTOMATON.  It is believed that
5355   CURR_CYCLE is start cycle of all reservation REGEXP.  */
5356static int
5357process_seq_for_forming_states (regexp, automaton, curr_cycle)
5358     regexp_t regexp;
5359     automaton_t automaton;
5360     int curr_cycle;
5361{
5362  int i;
5363
5364  if (regexp == NULL)
5365    return curr_cycle;
5366  else if (regexp->mode == rm_unit)
5367    {
5368      if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5369          == automaton->automaton_order_num)
5370        set_state_reserv (state_being_formed, curr_cycle,
5371                          REGEXP_UNIT (regexp)->unit_decl->unit_num);
5372      return curr_cycle;
5373    }
5374  else if (regexp->mode == rm_sequence)
5375    {
5376      for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5377	curr_cycle
5378	  = process_seq_for_forming_states
5379	    (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5380      return curr_cycle;
5381    }
5382  else if (regexp->mode == rm_allof)
5383    {
5384      int finish_cycle = 0;
5385      int cycle;
5386
5387      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5388	{
5389	  cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5390						  ->regexps [i],
5391						  automaton, curr_cycle);
5392	  if (finish_cycle < cycle)
5393	    finish_cycle = cycle;
5394	}
5395      return finish_cycle;
5396    }
5397  else
5398    {
5399      if (regexp->mode != rm_nothing)
5400	abort ();
5401      return curr_cycle;
5402    }
5403}
5404
5405/* This recursive function finishes forming ALT_STATE of AUTOMATON and
5406   inserts alt_state into the table.  */
5407static void
5408finish_forming_alt_state (alt_state, automaton)
5409     alt_state_t alt_state;
5410     automaton_t automaton ATTRIBUTE_UNUSED;
5411{
5412  state_t state_in_table;
5413  state_t corresponding_state;
5414
5415  corresponding_state = alt_state->state;
5416  state_in_table = insert_state (corresponding_state);
5417  if (state_in_table != corresponding_state)
5418    {
5419      free_state (corresponding_state);
5420      alt_state->state = state_in_table;
5421    }
5422}
5423
5424/* The following variable value is current automaton insn for whose
5425   reservation the alt states are created.  */
5426static ainsn_t curr_ainsn;
5427
5428/* This recursive function processes `|' in reservation REGEXP for
5429   forming alt_states of AUTOMATON.  List of the alt states should
5430   have the same order as in the description.  */
5431static void
5432process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5433     regexp_t regexp;
5434     automaton_t automaton;
5435     int inside_oneof_p;
5436{
5437  int i;
5438
5439  if (regexp->mode != rm_oneof)
5440    {
5441      alt_state_being_formed = get_free_alt_state ();
5442      state_being_formed = get_free_state (1, automaton);
5443      alt_state_being_formed->state = state_being_formed;
5444      /* We inserts in reverse order but we process alternatives also
5445         in reverse order.  So we have the same order of alternative
5446         as in the description.  */
5447      alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5448      curr_ainsn->alt_states = alt_state_being_formed;
5449      (void) process_seq_for_forming_states (regexp, automaton, 0);
5450      finish_forming_alt_state (alt_state_being_formed, automaton);
5451    }
5452  else
5453    {
5454      if (inside_oneof_p)
5455	abort ();
5456      /* We processes it in reverse order to get list with the same
5457	 order as in the description.  See also the previous
5458	 commentary.  */
5459      for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5460	process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5461					 automaton, 1);
5462    }
5463}
5464
5465/* Create nodes alt_state for all AUTOMATON insns.  */
5466static void
5467create_alt_states (automaton)
5468     automaton_t automaton;
5469{
5470  struct insn_reserv_decl *reserv_decl;
5471
5472  for (curr_ainsn = automaton->ainsn_list;
5473       curr_ainsn != NULL;
5474       curr_ainsn = curr_ainsn->next_ainsn)
5475    {
5476      reserv_decl = curr_ainsn->insn_reserv_decl;
5477      if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5478        {
5479          curr_ainsn->alt_states = NULL;
5480          process_alts_for_forming_states (reserv_decl->transformed_regexp,
5481					   automaton, 0);
5482          curr_ainsn->sorted_alt_states
5483	    = uniq_sort_alt_states (curr_ainsn->alt_states);
5484        }
5485    }
5486}
5487
5488
5489
5490/* The page contains major code for building DFA(s) for fast pipeline
5491   hazards recognition.  */
5492
5493/* The function forms list of ainsns of AUTOMATON with the same
5494   reservation.  */
5495static void
5496form_ainsn_with_same_reservs (automaton)
5497     automaton_t automaton;
5498{
5499  ainsn_t curr_ainsn;
5500  size_t i;
5501  vla_ptr_t first_insns;
5502  vla_ptr_t last_insns;
5503
5504  VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5505  VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5506  for (curr_ainsn = automaton->ainsn_list;
5507       curr_ainsn != NULL;
5508       curr_ainsn = curr_ainsn->next_ainsn)
5509    if (curr_ainsn->insn_reserv_decl
5510	== DECL_INSN_RESERV (advance_cycle_insn_decl))
5511      {
5512        curr_ainsn->next_same_reservs_insn = NULL;
5513        curr_ainsn->first_insn_with_same_reservs = 1;
5514      }
5515    else
5516      {
5517        for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5518          if (alt_states_eq
5519              (curr_ainsn->sorted_alt_states,
5520               ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5521            break;
5522        curr_ainsn->next_same_reservs_insn = NULL;
5523        if (i < VLA_PTR_LENGTH (first_insns))
5524          {
5525            curr_ainsn->first_insn_with_same_reservs = 0;
5526	    ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5527	      = curr_ainsn;
5528            VLA_PTR (last_insns, i) = curr_ainsn;
5529          }
5530        else
5531          {
5532            VLA_PTR_ADD (first_insns, curr_ainsn);
5533            VLA_PTR_ADD (last_insns, curr_ainsn);
5534            curr_ainsn->first_insn_with_same_reservs = 1;
5535          }
5536      }
5537  VLA_PTR_DELETE (first_insns);
5538  VLA_PTR_DELETE (last_insns);
5539}
5540
5541/* The following function creates all states of nondeterministic (if
5542   NDFA_FLAG has nonzero value) or deterministic AUTOMATON.  */
5543static void
5544make_automaton (automaton)
5545     automaton_t automaton;
5546{
5547  ainsn_t ainsn;
5548  struct insn_reserv_decl *insn_reserv_decl;
5549  alt_state_t alt_state;
5550  state_t state;
5551  state_t start_state;
5552  state_t state2;
5553  ainsn_t advance_cycle_ainsn;
5554  arc_t added_arc;
5555  vla_ptr_t state_stack;
5556
5557  VLA_PTR_CREATE (state_stack, 150, "state stack");
5558  /* Create the start state (empty state).  */
5559  start_state = insert_state (get_free_state (1, automaton));
5560  automaton->start_state = start_state;
5561  start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5562  VLA_PTR_ADD (state_stack, start_state);
5563  while (VLA_PTR_LENGTH (state_stack) != 0)
5564    {
5565      state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5566      VLA_PTR_SHORTEN (state_stack, 1);
5567      advance_cycle_ainsn = NULL;
5568      for (ainsn = automaton->ainsn_list;
5569	   ainsn != NULL;
5570	   ainsn = ainsn->next_ainsn)
5571        if (ainsn->first_insn_with_same_reservs)
5572          {
5573            insn_reserv_decl = ainsn->insn_reserv_decl;
5574            if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5575              {
5576		/* We process alt_states in the same order as they are
5577                   present in the description.  */
5578		added_arc = NULL;
5579                for (alt_state = ainsn->alt_states;
5580                     alt_state != NULL;
5581                     alt_state = alt_state->next_alt_state)
5582                  {
5583                    state2 = alt_state->state;
5584                    if (!intersected_state_reservs_p (state, state2))
5585                      {
5586                        state2 = states_union (state, state2);
5587                        if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5588                          {
5589                            state2->it_was_placed_in_stack_for_NDFA_forming
5590			      = 1;
5591                            VLA_PTR_ADD (state_stack, state2);
5592                          }
5593			added_arc = add_arc (state, state2, ainsn, 1);
5594			if (!ndfa_flag)
5595			  break;
5596                      }
5597                  }
5598		if (!ndfa_flag && added_arc != NULL)
5599		  {
5600		    added_arc->state_alts = 0;
5601		    for (alt_state = ainsn->alt_states;
5602			 alt_state != NULL;
5603			 alt_state = alt_state->next_alt_state)
5604		      {
5605			state2 = alt_state->state;
5606			if (!intersected_state_reservs_p (state, state2))
5607			  added_arc->state_alts++;
5608		      }
5609		  }
5610              }
5611            else
5612              advance_cycle_ainsn = ainsn;
5613          }
5614      /* Add transition to advance cycle.  */
5615      state2 = state_shift (state);
5616      if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5617        {
5618          state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5619          VLA_PTR_ADD (state_stack, state2);
5620        }
5621      if (advance_cycle_ainsn == NULL)
5622	abort ();
5623      add_arc (state, state2, advance_cycle_ainsn, 1);
5624    }
5625  VLA_PTR_DELETE (state_stack);
5626}
5627
5628/* Foms lists of all arcs of STATE marked by the same ainsn.  */
5629static void
5630form_arcs_marked_by_insn (state)
5631     state_t state;
5632{
5633  decl_t decl;
5634  arc_t arc;
5635  int i;
5636
5637  for (i = 0; i < description->decls_num; i++)
5638    {
5639      decl = description->decls [i];
5640      if (decl->mode == dm_insn_reserv)
5641	DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5642    }
5643  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5644    {
5645      if (arc->insn == NULL)
5646	abort ();
5647      arc->next_arc_marked_by_insn
5648	= arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5649      arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5650    }
5651}
5652
5653/* The function creates composed state (see comments for IR) from
5654   ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5655   same insn.  If the composed state is not in STATE_STACK yet, it is
5656   popped to STATE_STACK.  */
5657static void
5658create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5659     state_t original_state;
5660     arc_t arcs_marked_by_insn;
5661     vla_ptr_t *state_stack;
5662{
5663  state_t state;
5664  alt_state_t curr_alt_state;
5665  alt_state_t new_alt_state;
5666  arc_t curr_arc;
5667  arc_t next_arc;
5668  state_t state_in_table;
5669  state_t temp_state;
5670  alt_state_t canonical_alt_states_list;
5671  int alts_number;
5672
5673  if (arcs_marked_by_insn == NULL)
5674    return;
5675  if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5676    state = arcs_marked_by_insn->to_state;
5677  else
5678    {
5679      if (!ndfa_flag)
5680	abort ();
5681      /* Create composed state.  */
5682      state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5683      curr_alt_state = NULL;
5684      for (curr_arc = arcs_marked_by_insn;
5685           curr_arc != NULL;
5686           curr_arc = curr_arc->next_arc_marked_by_insn)
5687        {
5688          new_alt_state = get_free_alt_state ();
5689          new_alt_state->next_alt_state = curr_alt_state;
5690          new_alt_state->state = curr_arc->to_state;
5691	  if (curr_arc->to_state->component_states != NULL)
5692	    abort ();
5693          curr_alt_state = new_alt_state;
5694        }
5695      /* There are not identical sets in the alt state list.  */
5696      canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5697      if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5698        {
5699          temp_state = state;
5700          state = canonical_alt_states_list->state;
5701          free_state (temp_state);
5702        }
5703      else
5704        {
5705          state->component_states = canonical_alt_states_list;
5706          state_in_table = insert_state (state);
5707          if (state_in_table != state)
5708            {
5709              if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5710		abort ();
5711              free_state (state);
5712              state = state_in_table;
5713            }
5714          else
5715            {
5716              if (state->it_was_placed_in_stack_for_DFA_forming)
5717		abort ();
5718              for (curr_alt_state = state->component_states;
5719                   curr_alt_state != NULL;
5720                   curr_alt_state = curr_alt_state->next_sorted_alt_state)
5721                for (curr_arc = first_out_arc (curr_alt_state->state);
5722                     curr_arc != NULL;
5723                     curr_arc = next_out_arc (curr_arc))
5724		  add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5725            }
5726          arcs_marked_by_insn->to_state = state;
5727          for (alts_number = 0,
5728	       curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5729               curr_arc != NULL;
5730               curr_arc = next_arc)
5731            {
5732              next_arc = curr_arc->next_arc_marked_by_insn;
5733              remove_arc (original_state, curr_arc);
5734	      alts_number++;
5735            }
5736	  arcs_marked_by_insn->state_alts = alts_number;
5737        }
5738    }
5739  if (!state->it_was_placed_in_stack_for_DFA_forming)
5740    {
5741      state->it_was_placed_in_stack_for_DFA_forming = 1;
5742      VLA_PTR_ADD (*state_stack, state);
5743    }
5744}
5745
5746/* The function transformes nondeterminstic AUTOMATON into
5747   deterministic.  */
5748static void
5749NDFA_to_DFA (automaton)
5750     automaton_t automaton;
5751{
5752  state_t start_state;
5753  state_t state;
5754  decl_t decl;
5755  vla_ptr_t state_stack;
5756  int i;
5757
5758  VLA_PTR_CREATE (state_stack, 150, "state stack");
5759  /* Create the start state (empty state).  */
5760  start_state = automaton->start_state;
5761  start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5762  VLA_PTR_ADD (state_stack, start_state);
5763  while (VLA_PTR_LENGTH (state_stack) != 0)
5764    {
5765      state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5766      VLA_PTR_SHORTEN (state_stack, 1);
5767      form_arcs_marked_by_insn (state);
5768      for (i = 0; i < description->decls_num; i++)
5769	{
5770	  decl = description->decls [i];
5771	  if (decl->mode == dm_insn_reserv)
5772	    create_composed_state
5773              (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5774	       &state_stack);
5775	}
5776    }
5777  VLA_PTR_DELETE (state_stack);
5778}
5779
5780/* The following variable value is current number (1, 2, ...) of passing
5781   graph of states.  */
5782static int curr_state_graph_pass_num;
5783
5784/* This recursive function passes all states achieved from START_STATE
5785   and applies APPLIED_FUNC to them.  */
5786static void
5787pass_state_graph (start_state, applied_func)
5788     state_t start_state;
5789     void (*applied_func) PARAMS ((state_t state));
5790{
5791  arc_t arc;
5792
5793  if (start_state->pass_num == curr_state_graph_pass_num)
5794    return;
5795  start_state->pass_num = curr_state_graph_pass_num;
5796  (*applied_func) (start_state);
5797  for (arc = first_out_arc (start_state);
5798       arc != NULL;
5799       arc = next_out_arc (arc))
5800    pass_state_graph (arc->to_state, applied_func);
5801}
5802
5803/* This recursive function passes all states of AUTOMATON and applies
5804   APPLIED_FUNC to them.  */
5805static void
5806pass_states (automaton, applied_func)
5807     automaton_t automaton;
5808     void (*applied_func) PARAMS ((state_t state));
5809{
5810  curr_state_graph_pass_num++;
5811  pass_state_graph (automaton->start_state, applied_func);
5812}
5813
5814/* The function initializes code for passing of all states.  */
5815static void
5816initiate_pass_states ()
5817{
5818  curr_state_graph_pass_num = 0;
5819}
5820
5821/* The following vla is used for storing pointers to all achieved
5822   states.  */
5823static vla_ptr_t all_achieved_states;
5824
5825/* This function is called by function pass_states to add an achieved
5826   STATE.  */
5827static void
5828add_achieved_state (state)
5829     state_t state;
5830{
5831  VLA_PTR_ADD (all_achieved_states, state);
5832}
5833
5834/* The function sets up equivalence numbers of insns which mark all
5835   out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5836   nonzero value) or by equiv_class_num_2 of the destination state.
5837   The function returns number of out arcs of STATE.  */
5838static int
5839set_out_arc_insns_equiv_num (state, odd_iteration_flag)
5840     state_t state;
5841     int odd_iteration_flag;
5842{
5843  int state_out_arcs_num;
5844  arc_t arc;
5845
5846  state_out_arcs_num = 0;
5847  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5848    {
5849      if (arc->insn->insn_reserv_decl->equiv_class_num != 0
5850	  || arc->insn->insn_reserv_decl->state_alts != 0)
5851	abort ();
5852      state_out_arcs_num++;
5853      arc->insn->insn_reserv_decl->equiv_class_num
5854	= (odd_iteration_flag
5855           ? arc->to_state->equiv_class_num_1
5856	   : arc->to_state->equiv_class_num_2);
5857      arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
5858      if (arc->insn->insn_reserv_decl->equiv_class_num == 0
5859	  || arc->insn->insn_reserv_decl->state_alts <= 0)
5860	abort ();
5861    }
5862  return state_out_arcs_num;
5863}
5864
5865/* The function clears equivalence numbers and alt_states in all insns
5866   which mark all out arcs of STATE.  */
5867static void
5868clear_arc_insns_equiv_num (state)
5869     state_t state;
5870{
5871  arc_t arc;
5872
5873  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5874    {
5875      arc->insn->insn_reserv_decl->equiv_class_num = 0;
5876      arc->insn->insn_reserv_decl->state_alts = 0;
5877    }
5878}
5879
5880/* The function copies pointers to equivalent states from vla FROM
5881   into vla TO.  */
5882static void
5883copy_equiv_class (to, from)
5884     vla_ptr_t *to;
5885     const vla_ptr_t *from;
5886{
5887  state_t *class_ptr;
5888
5889  VLA_PTR_NULLIFY (*to);
5890  for (class_ptr = VLA_PTR_BEGIN (*from);
5891       class_ptr <= (state_t *) VLA_PTR_LAST (*from);
5892       class_ptr++)
5893    VLA_PTR_ADD (*to, *class_ptr);
5894}
5895
5896/* The function returns nonzero value if STATE is not equivalent to
5897   another state from the same current partition on equivalence
5898   classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of
5899   output arcs.  Iteration of making equivalence partition is defined
5900   by ODD_ITERATION_FLAG.  */
5901static int
5902state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag)
5903     state_t state;
5904     int original_state_out_arcs_num;
5905     int odd_iteration_flag;
5906{
5907  arc_t arc;
5908  int state_out_arcs_num;
5909
5910  state_out_arcs_num = 0;
5911  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5912    {
5913      state_out_arcs_num++;
5914      if ((odd_iteration_flag
5915           ? arc->to_state->equiv_class_num_1
5916	   : arc->to_state->equiv_class_num_2)
5917          != arc->insn->insn_reserv_decl->equiv_class_num
5918	  || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
5919        return 1;
5920    }
5921  return state_out_arcs_num != original_state_out_arcs_num;
5922}
5923
5924/* The function makes initial partition of STATES on equivalent
5925   classes.  */
5926static state_t
5927init_equiv_class (states, states_num)
5928     state_t *states;
5929     int states_num;
5930{
5931  state_t *state_ptr;
5932  state_t result_equiv_class;
5933
5934  result_equiv_class = NULL;
5935  for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
5936    {
5937      (*state_ptr)->equiv_class_num_1 = 1;
5938      (*state_ptr)->next_equiv_class_state = result_equiv_class;
5939      result_equiv_class = *state_ptr;
5940    }
5941  return result_equiv_class;
5942}
5943
5944/* The function processes equivalence class given by its pointer
5945   EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG.  If there
5946   are not equvalent states, the function partitions the class
5947   removing nonequivalent states and placing them in
5948   *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5949   assigns it to the state equivalence number.  If the class has been
5950   partitioned, the function returns nonzero value.  */
5951static int
5952partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5953		       next_iteration_classes, new_equiv_class_num_ptr)
5954     state_t *equiv_class_ptr;
5955     int odd_iteration_flag;
5956     vla_ptr_t *next_iteration_classes;
5957     int *new_equiv_class_num_ptr;
5958{
5959  state_t new_equiv_class;
5960  int partition_p;
5961  state_t first_state;
5962  state_t curr_state;
5963  state_t prev_state;
5964  state_t next_state;
5965  int out_arcs_num;
5966
5967  partition_p = 0;
5968  if (*equiv_class_ptr == NULL)
5969    abort ();
5970  for (first_state = *equiv_class_ptr;
5971       first_state != NULL;
5972       first_state = new_equiv_class)
5973    {
5974      new_equiv_class = NULL;
5975      if (first_state->next_equiv_class_state != NULL)
5976	{
5977	  /* There are more one states in the class equivalence.  */
5978	  out_arcs_num = set_out_arc_insns_equiv_num (first_state,
5979						      odd_iteration_flag);
5980	  for (prev_state = first_state,
5981		 curr_state = first_state->next_equiv_class_state;
5982	       curr_state != NULL;
5983	       curr_state = next_state)
5984	    {
5985	      next_state = curr_state->next_equiv_class_state;
5986	      if (state_is_differed (curr_state, out_arcs_num,
5987				     odd_iteration_flag))
5988		{
5989		  /* Remove curr state from the class equivalence.  */
5990		  prev_state->next_equiv_class_state = next_state;
5991		  /* Add curr state to the new class equivalence.  */
5992		  curr_state->next_equiv_class_state = new_equiv_class;
5993		  if (new_equiv_class == NULL)
5994		    (*new_equiv_class_num_ptr)++;
5995		  if (odd_iteration_flag)
5996		    curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5997		  else
5998		    curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5999		  new_equiv_class = curr_state;
6000		  partition_p = 1;
6001		}
6002	      else
6003		prev_state = curr_state;
6004	    }
6005	  clear_arc_insns_equiv_num (first_state);
6006	}
6007      if (new_equiv_class != NULL)
6008	VLA_PTR_ADD  (*next_iteration_classes, new_equiv_class);
6009    }
6010  return partition_p;
6011}
6012
6013/* The function finds equivalent states of AUTOMATON.  */
6014static void
6015evaluate_equiv_classes (automaton, equiv_classes)
6016     automaton_t automaton;
6017     vla_ptr_t *equiv_classes;
6018{
6019  state_t new_equiv_class;
6020  int new_equiv_class_num;
6021  int odd_iteration_flag;
6022  int finish_flag;
6023  vla_ptr_t next_iteration_classes;
6024  state_t *equiv_class_ptr;
6025  state_t *state_ptr;
6026
6027  VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
6028  pass_states (automaton, add_achieved_state);
6029  new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
6030                                      VLA_PTR_LENGTH (all_achieved_states));
6031  odd_iteration_flag = 0;
6032  new_equiv_class_num = 1;
6033  VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
6034  VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
6035  do
6036    {
6037      odd_iteration_flag = !odd_iteration_flag;
6038      finish_flag = 1;
6039      copy_equiv_class (equiv_classes, &next_iteration_classes);
6040      /* Transfer equiv numbers for the next iteration.  */
6041      for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
6042	   state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
6043           state_ptr++)
6044	if (odd_iteration_flag)
6045	  (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
6046	else
6047	  (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
6048      for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6049           equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6050           equiv_class_ptr++)
6051	if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
6052				   &next_iteration_classes,
6053				   &new_equiv_class_num))
6054	  finish_flag = 0;
6055    }
6056  while (!finish_flag);
6057  VLA_PTR_DELETE (next_iteration_classes);
6058  VLA_PTR_DELETE (all_achieved_states);
6059}
6060
6061/* The function merges equivalent states of AUTOMATON.  */
6062static void
6063merge_states (automaton, equiv_classes)
6064     automaton_t automaton;
6065     vla_ptr_t *equiv_classes;
6066{
6067  state_t *equiv_class_ptr;
6068  state_t curr_state;
6069  state_t new_state;
6070  state_t first_class_state;
6071  alt_state_t alt_states;
6072  alt_state_t new_alt_state;
6073  arc_t curr_arc;
6074  arc_t next_arc;
6075
6076  /* Create states corresponding to equivalence classes containing two
6077     or more states.  */
6078  for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6079       equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6080       equiv_class_ptr++)
6081    if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6082      {
6083        /* There are more one states in the class equivalence.  */
6084        /* Create new compound state.  */
6085        new_state = get_free_state (0, automaton);
6086        alt_states = NULL;
6087        first_class_state = *equiv_class_ptr;
6088        for (curr_state = first_class_state;
6089             curr_state != NULL;
6090             curr_state = curr_state->next_equiv_class_state)
6091          {
6092            curr_state->equiv_class_state = new_state;
6093            new_alt_state = get_free_alt_state ();
6094            new_alt_state->state = curr_state;
6095            new_alt_state->next_sorted_alt_state = alt_states;
6096            alt_states = new_alt_state;
6097          }
6098        new_state->component_states = alt_states;
6099      }
6100    else
6101      (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
6102  for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
6103       equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
6104       equiv_class_ptr++)
6105    if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
6106      {
6107        first_class_state = *equiv_class_ptr;
6108        /* Create new arcs output from the state corresponding to
6109           equiv class.  */
6110        for (curr_arc = first_out_arc (first_class_state);
6111             curr_arc != NULL;
6112             curr_arc = next_out_arc (curr_arc))
6113          add_arc (first_class_state->equiv_class_state,
6114                   curr_arc->to_state->equiv_class_state,
6115		   curr_arc->insn, curr_arc->state_alts);
6116        /* Delete output arcs from states of given class equivalence.  */
6117        for (curr_state = first_class_state;
6118             curr_state != NULL;
6119             curr_state = curr_state->next_equiv_class_state)
6120          {
6121            if (automaton->start_state == curr_state)
6122              automaton->start_state = curr_state->equiv_class_state;
6123            /* Delete the state and its output arcs.  */
6124            for (curr_arc = first_out_arc (curr_state);
6125                 curr_arc != NULL;
6126                 curr_arc = next_arc)
6127              {
6128                next_arc = next_out_arc (curr_arc);
6129                free_arc (curr_arc);
6130              }
6131          }
6132      }
6133    else
6134      {
6135        /* Change `to_state' of arcs output from the state of given
6136           equivalence class.  */
6137        for (curr_arc = first_out_arc (*equiv_class_ptr);
6138             curr_arc != NULL;
6139             curr_arc = next_out_arc (curr_arc))
6140          curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6141      }
6142}
6143
6144/* The function sets up new_cycle_p for states if there is arc to the
6145   state marked by advance_cycle_insn_decl.  */
6146static void
6147set_new_cycle_flags (state)
6148     state_t state;
6149{
6150  arc_t arc;
6151
6152  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6153    if (arc->insn->insn_reserv_decl
6154	== DECL_INSN_RESERV (advance_cycle_insn_decl))
6155      arc->to_state->new_cycle_p = 1;
6156}
6157
6158/* The top level function for minimization of deterministic
6159   AUTOMATON.  */
6160static void
6161minimize_DFA (automaton)
6162     automaton_t automaton;
6163{
6164  vla_ptr_t equiv_classes;
6165
6166  VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
6167  evaluate_equiv_classes (automaton, &equiv_classes);
6168  merge_states (automaton, &equiv_classes);
6169  pass_states (automaton, set_new_cycle_flags);
6170  VLA_PTR_DELETE (equiv_classes);
6171}
6172
6173/* Values of two variables are counted number of states and arcs in an
6174   automaton.  */
6175static int curr_counted_states_num;
6176static int curr_counted_arcs_num;
6177
6178/* The function is called by function `pass_states' to count states
6179   and arcs of an automaton.  */
6180static void
6181incr_states_and_arcs_nums (state)
6182     state_t state;
6183{
6184  arc_t arc;
6185
6186  curr_counted_states_num++;
6187  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6188    curr_counted_arcs_num++;
6189}
6190
6191/* The function counts states and arcs of AUTOMATON.  */
6192static void
6193count_states_and_arcs (automaton, states_num, arcs_num)
6194     automaton_t automaton;
6195     int *states_num;
6196     int *arcs_num;
6197{
6198  curr_counted_states_num = 0;
6199  curr_counted_arcs_num = 0;
6200  pass_states (automaton, incr_states_and_arcs_nums);
6201  *states_num = curr_counted_states_num;
6202  *arcs_num = curr_counted_arcs_num;
6203}
6204
6205/* The function builds one DFA AUTOMATON for fast pipeline hazards
6206   recognition after checking and simplifying IR of the
6207   description.  */
6208static void
6209build_automaton (automaton)
6210     automaton_t automaton;
6211{
6212  int states_num;
6213  int arcs_num;
6214
6215  ticker_on (&NDFA_time);
6216  make_automaton (automaton);
6217  ticker_off (&NDFA_time);
6218  count_states_and_arcs (automaton, &states_num, &arcs_num);
6219  automaton->NDFA_states_num = states_num;
6220  automaton->NDFA_arcs_num = arcs_num;
6221  ticker_on (&NDFA_to_DFA_time);
6222  NDFA_to_DFA (automaton);
6223  ticker_off (&NDFA_to_DFA_time);
6224  count_states_and_arcs (automaton, &states_num, &arcs_num);
6225  automaton->DFA_states_num = states_num;
6226  automaton->DFA_arcs_num = arcs_num;
6227  if (!no_minimization_flag)
6228    {
6229      ticker_on (&minimize_time);
6230      minimize_DFA (automaton);
6231      ticker_off (&minimize_time);
6232      count_states_and_arcs (automaton, &states_num, &arcs_num);
6233      automaton->minimal_DFA_states_num = states_num;
6234      automaton->minimal_DFA_arcs_num = arcs_num;
6235    }
6236}
6237
6238
6239
6240/* The page contains code for enumeration  of all states of an automaton.  */
6241
6242/* Variable used for enumeration of all states of an automaton.  Its
6243   value is current number of automaton states.  */
6244static int curr_state_order_num;
6245
6246/* The function is called by function `pass_states' for enumerating
6247   states.  */
6248static void
6249set_order_state_num (state)
6250     state_t state;
6251{
6252  state->order_state_num = curr_state_order_num;
6253  curr_state_order_num++;
6254}
6255
6256/* The function enumerates all states of AUTOMATON.  */
6257static void
6258enumerate_states (automaton)
6259     automaton_t automaton;
6260{
6261  curr_state_order_num = 0;
6262  pass_states (automaton, set_order_state_num);
6263  automaton->achieved_states_num = curr_state_order_num;
6264}
6265
6266
6267
6268/* The page contains code for finding equivalent automaton insns
6269   (ainsns).  */
6270
6271/* The function inserts AINSN into cyclic list
6272   CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns.  */
6273static ainsn_t
6274insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6275     ainsn_t ainsn;
6276     ainsn_t cyclic_equiv_class_insn_list;
6277{
6278  if (cyclic_equiv_class_insn_list == NULL)
6279    ainsn->next_equiv_class_insn = ainsn;
6280  else
6281    {
6282      ainsn->next_equiv_class_insn
6283        = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6284      cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6285    }
6286  return ainsn;
6287}
6288
6289/* The function deletes equiv_class_insn into cyclic list of
6290   equivalent ainsns.  */
6291static void
6292delete_ainsn_from_equiv_class (equiv_class_insn)
6293     ainsn_t equiv_class_insn;
6294{
6295  ainsn_t curr_equiv_class_insn;
6296  ainsn_t prev_equiv_class_insn;
6297
6298  prev_equiv_class_insn = equiv_class_insn;
6299  for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6300       curr_equiv_class_insn != equiv_class_insn;
6301       curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6302    prev_equiv_class_insn = curr_equiv_class_insn;
6303  if (prev_equiv_class_insn != equiv_class_insn)
6304    prev_equiv_class_insn->next_equiv_class_insn
6305      = equiv_class_insn->next_equiv_class_insn;
6306}
6307
6308/* The function processes AINSN of a state in order to find equivalent
6309   ainsns.  INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6310   state.  */
6311static void
6312process_insn_equiv_class (ainsn, insn_arcs_array)
6313     ainsn_t ainsn;
6314     arc_t *insn_arcs_array;
6315{
6316  ainsn_t next_insn;
6317  ainsn_t curr_insn;
6318  ainsn_t cyclic_insn_list;
6319  arc_t arc;
6320
6321  if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6322    abort ();
6323  curr_insn = ainsn;
6324  /* New class of ainsns which are not equivalent to given ainsn.  */
6325  cyclic_insn_list = NULL;
6326  do
6327    {
6328      next_insn = curr_insn->next_equiv_class_insn;
6329      arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6330      if (arc == NULL
6331          || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6332              != arc->to_state))
6333        {
6334          delete_ainsn_from_equiv_class (curr_insn);
6335          cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6336							    cyclic_insn_list);
6337        }
6338      curr_insn = next_insn;
6339    }
6340  while (curr_insn != ainsn);
6341}
6342
6343/* The function processes STATE in order to find equivalent ainsns.  */
6344static void
6345process_state_for_insn_equiv_partition (state)
6346     state_t state;
6347{
6348  arc_t arc;
6349  arc_t *insn_arcs_array;
6350  int i;
6351  vla_ptr_t insn_arcs_vect;
6352
6353  VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6354  VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6355  insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6356  /* Process insns of the arcs.  */
6357  for (i = 0; i < description->insns_num; i++)
6358    insn_arcs_array [i] = NULL;
6359  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6360    insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6361  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6362    process_insn_equiv_class (arc->insn, insn_arcs_array);
6363  VLA_PTR_DELETE (insn_arcs_vect);
6364}
6365
6366/* The function searches for equivalent ainsns of AUTOMATON.  */
6367static void
6368set_insn_equiv_classes (automaton)
6369     automaton_t automaton;
6370{
6371  ainsn_t ainsn;
6372  ainsn_t first_insn;
6373  ainsn_t curr_insn;
6374  ainsn_t cyclic_insn_list;
6375  ainsn_t insn_with_same_reservs;
6376  int equiv_classes_num;
6377
6378  /* All insns are included in one equivalence class.  */
6379  cyclic_insn_list = NULL;
6380  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6381    if (ainsn->first_insn_with_same_reservs)
6382      cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6383							cyclic_insn_list);
6384  /* Process insns in order to make equivalence partition.  */
6385  pass_states (automaton, process_state_for_insn_equiv_partition);
6386  /* Enumerate equiv classes.  */
6387  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6388    /* Set undefined value.  */
6389    ainsn->insn_equiv_class_num = -1;
6390  equiv_classes_num = 0;
6391  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6392    if (ainsn->insn_equiv_class_num < 0)
6393      {
6394        first_insn = ainsn;
6395        if (!first_insn->first_insn_with_same_reservs)
6396	  abort ();
6397        first_insn->first_ainsn_with_given_equialence_num = 1;
6398        curr_insn = first_insn;
6399        do
6400          {
6401            for (insn_with_same_reservs = curr_insn;
6402                 insn_with_same_reservs != NULL;
6403                 insn_with_same_reservs
6404		   = insn_with_same_reservs->next_same_reservs_insn)
6405              insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6406            curr_insn = curr_insn->next_equiv_class_insn;
6407          }
6408        while (curr_insn != first_insn);
6409        equiv_classes_num++;
6410      }
6411  automaton->insn_equiv_classes_num = equiv_classes_num;
6412}
6413
6414
6415
6416/* This page contains code for creating DFA(s) and calls functions
6417   building them.  */
6418
6419
6420/* The following value is used to prevent floating point overflow for
6421   estimating an automaton bound.  The value should be less DBL_MAX on
6422   the host machine.  We use here approximate minimum of maximal
6423   double floating point value required by ANSI C standard.  It
6424   will work for non ANSI sun compiler too.  */
6425
6426#define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND  1.0E37
6427
6428/* The function estimate size of the single DFA used by PHR (pipeline
6429   hazards recognizer).  */
6430static double
6431estimate_one_automaton_bound ()
6432{
6433  decl_t decl;
6434  double one_automaton_estimation_bound;
6435  double root_value;
6436  int i;
6437
6438  one_automaton_estimation_bound = 1.0;
6439  for (i = 0; i < description->decls_num; i++)
6440    {
6441      decl = description->decls [i];
6442      if (decl->mode == dm_unit)
6443	{
6444	  root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num + 1.0)
6445                            / automata_num);
6446	  if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6447	      > one_automaton_estimation_bound)
6448	    one_automaton_estimation_bound *= root_value;
6449	}
6450    }
6451  return one_automaton_estimation_bound;
6452}
6453
6454/* The function compares unit declarations acoording to their maximal
6455   cycle in reservations.  */
6456static int
6457compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6458     const void *unit_decl_1;
6459     const void *unit_decl_2;
6460{
6461  if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6462      < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6463    return 1;
6464  else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6465	   == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6466    return 0;
6467  else
6468    return -1;
6469}
6470
6471/* The function makes heuristic assigning automata to units.  Actually
6472   efficacy of the algorithm has been checked yet??? */
6473static void
6474units_to_automata_heuristic_distr ()
6475{
6476  double estimation_bound;
6477  decl_t decl;
6478  decl_t *unit_decl_ptr;
6479  int automaton_num;
6480  int rest_units_num;
6481  double bound_value;
6482  vla_ptr_t unit_decls;
6483  int i;
6484
6485  if (description->units_num == 0)
6486    return;
6487  estimation_bound = estimate_one_automaton_bound ();
6488  VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6489  for (i = 0; i < description->decls_num; i++)
6490    {
6491      decl = description->decls [i];
6492      if (decl->mode == dm_unit)
6493	VLA_PTR_ADD (unit_decls, decl);
6494    }
6495  qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6496         sizeof (decl_t), compare_max_occ_cycle_nums);
6497  automaton_num = 0;
6498  unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6499  bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6500  DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6501  for (unit_decl_ptr++;
6502       unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6503       unit_decl_ptr++)
6504    {
6505      rest_units_num
6506	= ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6507      if (automata_num - automaton_num - 1 > rest_units_num)
6508	abort ();
6509      if (automaton_num < automata_num - 1
6510          && ((automata_num - automaton_num - 1 == rest_units_num)
6511              || (bound_value
6512                  > (estimation_bound
6513		     / (DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num)))))
6514        {
6515          bound_value = DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6516          automaton_num++;
6517        }
6518      else
6519        bound_value *= DECL_UNIT (*unit_decl_ptr)->max_occ_cycle_num;
6520      DECL_UNIT (*unit_decl_ptr)->corresponding_automaton_num = automaton_num;
6521    }
6522  if (automaton_num != automata_num - 1)
6523    abort ();
6524  VLA_PTR_DELETE (unit_decls);
6525}
6526
6527/* The functions creates automaton insns for each automata.  Automaton
6528   insn is simply insn for given automaton which makes reservation
6529   only of units of the automaton.  */
6530static ainsn_t
6531create_ainsns ()
6532{
6533  decl_t decl;
6534  ainsn_t first_ainsn;
6535  ainsn_t curr_ainsn;
6536  ainsn_t prev_ainsn;
6537  int i;
6538
6539  first_ainsn = NULL;
6540  prev_ainsn = NULL;
6541  for (i = 0; i < description->decls_num; i++)
6542    {
6543      decl = description->decls [i];
6544      if (decl->mode == dm_insn_reserv)
6545	{
6546	  curr_ainsn = create_node (sizeof (struct ainsn));
6547	  curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6548	  curr_ainsn->important_p = FALSE;
6549	  curr_ainsn->next_ainsn = NULL;
6550	  if (prev_ainsn == NULL)
6551	    first_ainsn = curr_ainsn;
6552	  else
6553	    prev_ainsn->next_ainsn = curr_ainsn;
6554	  prev_ainsn = curr_ainsn;
6555	}
6556    }
6557  return first_ainsn;
6558}
6559
6560/* The function assigns automata to units according to constructions
6561   `define_automaton' in the description.  */
6562static void
6563units_to_automata_distr ()
6564{
6565  decl_t decl;
6566  int i;
6567
6568  for (i = 0; i < description->decls_num; i++)
6569    {
6570      decl = description->decls [i];
6571      if (decl->mode == dm_unit)
6572	{
6573	  if (DECL_UNIT (decl)->automaton_decl == NULL
6574	      || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6575		  == NULL))
6576	    /* Distribute to the first automaton.  */
6577	    DECL_UNIT (decl)->corresponding_automaton_num = 0;
6578	  else
6579	    DECL_UNIT (decl)->corresponding_automaton_num
6580	      = (DECL_UNIT (decl)->automaton_decl
6581                 ->corresponding_automaton->automaton_order_num);
6582	}
6583    }
6584}
6585
6586/* The function creates DFA(s) for fast pipeline hazards recognition
6587   after checking and simplifying IR of the description.  */
6588static void
6589create_automata ()
6590{
6591  automaton_t curr_automaton;
6592  automaton_t prev_automaton;
6593  decl_t decl;
6594  int curr_automaton_num;
6595  int i;
6596
6597  if (automata_num != 0)
6598    {
6599      units_to_automata_heuristic_distr ();
6600      for (prev_automaton = NULL, curr_automaton_num = 0;
6601           curr_automaton_num < automata_num;
6602           curr_automaton_num++, prev_automaton = curr_automaton)
6603        {
6604	  curr_automaton = create_node (sizeof (struct automaton));
6605	  curr_automaton->ainsn_list = create_ainsns ();
6606	  curr_automaton->corresponding_automaton_decl = NULL;
6607	  curr_automaton->next_automaton = NULL;
6608          curr_automaton->automaton_order_num = curr_automaton_num;
6609          if (prev_automaton == NULL)
6610            description->first_automaton = curr_automaton;
6611          else
6612            prev_automaton->next_automaton = curr_automaton;
6613        }
6614    }
6615  else
6616    {
6617      curr_automaton_num = 0;
6618      prev_automaton = NULL;
6619      for (i = 0; i < description->decls_num; i++)
6620	{
6621	  decl = description->decls [i];
6622	  if (decl->mode == dm_automaton
6623	      && DECL_AUTOMATON (decl)->automaton_is_used)
6624	    {
6625	      curr_automaton = create_node (sizeof (struct automaton));
6626	      curr_automaton->ainsn_list = create_ainsns ();
6627	      curr_automaton->corresponding_automaton_decl
6628		= DECL_AUTOMATON (decl);
6629	      curr_automaton->next_automaton = NULL;
6630	      DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6631	      curr_automaton->automaton_order_num = curr_automaton_num;
6632	      if (prev_automaton == NULL)
6633		description->first_automaton = curr_automaton;
6634	      else
6635		prev_automaton->next_automaton = curr_automaton;
6636	      curr_automaton_num++;
6637	      prev_automaton = curr_automaton;
6638	    }
6639	}
6640      if (curr_automaton_num == 0)
6641	{
6642	  curr_automaton = create_node (sizeof (struct automaton));
6643	  curr_automaton->ainsn_list = create_ainsns ();
6644	  curr_automaton->corresponding_automaton_decl = NULL;
6645	  curr_automaton->next_automaton = NULL;
6646	  description->first_automaton = curr_automaton;
6647	}
6648      units_to_automata_distr ();
6649    }
6650  NDFA_time = create_ticker ();
6651  ticker_off (&NDFA_time);
6652  NDFA_to_DFA_time = create_ticker ();
6653  ticker_off (&NDFA_to_DFA_time);
6654  minimize_time = create_ticker ();
6655  ticker_off (&minimize_time);
6656  equiv_time = create_ticker ();
6657  ticker_off (&equiv_time);
6658  for (curr_automaton = description->first_automaton;
6659       curr_automaton != NULL;
6660       curr_automaton = curr_automaton->next_automaton)
6661    {
6662      if (curr_automaton->corresponding_automaton_decl == NULL)
6663	fprintf (stderr, "Create anonymous automaton ...");
6664      else
6665	fprintf (stderr, "Create automaton `%s'...",
6666		 curr_automaton->corresponding_automaton_decl->name);
6667      create_alt_states (curr_automaton);
6668      form_ainsn_with_same_reservs (curr_automaton);
6669      build_automaton (curr_automaton);
6670      enumerate_states (curr_automaton);
6671      ticker_on (&equiv_time);
6672      set_insn_equiv_classes (curr_automaton);
6673      ticker_off (&equiv_time);
6674      fprintf (stderr, "done\n");
6675    }
6676}
6677
6678
6679
6680/* This page contains code for forming string representation of
6681   regexp.  The representation is formed on IR obstack.  So you should
6682   not work with IR obstack between regexp_representation and
6683   finish_regexp_representation calls.  */
6684
6685/* This recursive function forms string representation of regexp
6686   (without tailing '\0').  */
6687static void
6688form_regexp (regexp)
6689     regexp_t regexp;
6690{
6691  int i;
6692
6693  if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6694    {
6695      const char *name = (regexp->mode == rm_unit
6696                          ? REGEXP_UNIT (regexp)->name
6697			  : REGEXP_RESERV (regexp)->name);
6698
6699      obstack_grow (&irp, name, strlen (name));
6700    }
6701  else if (regexp->mode == rm_sequence)
6702    for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6703      {
6704	if (i != 0)
6705          obstack_1grow (&irp, ',');
6706	form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6707      }
6708  else if (regexp->mode == rm_allof)
6709    {
6710      obstack_1grow (&irp, '(');
6711      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6712	{
6713	  if (i != 0)
6714            obstack_1grow (&irp, '+');
6715	  if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6716              || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6717            obstack_1grow (&irp, '(');
6718	  form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6719	  if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6720              || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6721            obstack_1grow (&irp, ')');
6722        }
6723      obstack_1grow (&irp, ')');
6724    }
6725  else if (regexp->mode == rm_oneof)
6726    for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6727      {
6728	if (i != 0)
6729          obstack_1grow (&irp, '|');
6730	if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6731          obstack_1grow (&irp, '(');
6732        form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6733	if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6734          obstack_1grow (&irp, ')');
6735      }
6736  else if (regexp->mode == rm_repeat)
6737    {
6738      char digits [30];
6739
6740      if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6741	  || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6742	  || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6743        obstack_1grow (&irp, '(');
6744      form_regexp (REGEXP_REPEAT (regexp)->regexp);
6745      if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6746	  || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6747	  || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6748        obstack_1grow (&irp, ')');
6749      sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6750      obstack_grow (&irp, digits, strlen (digits));
6751    }
6752  else if (regexp->mode == rm_nothing)
6753    obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6754  else
6755    abort ();
6756}
6757
6758/* The function returns string representation of REGEXP on IR
6759   obstack.  */
6760static const char *
6761regexp_representation (regexp)
6762     regexp_t regexp;
6763{
6764  form_regexp (regexp);
6765  obstack_1grow (&irp, '\0');
6766  return obstack_base (&irp);
6767}
6768
6769/* The function frees memory allocated for last formed string
6770   representation of regexp.  */
6771static void
6772finish_regexp_representation ()
6773{
6774  int length = obstack_object_size (&irp);
6775
6776  obstack_blank_fast (&irp, -length);
6777}
6778
6779
6780
6781/* This page contains code for output PHR (pipeline hazards recognizer).  */
6782
6783/* The function outputs minimal C type which is sufficient for
6784   representation numbers in range min_range_value and
6785   max_range_value.  Because host machine and build machine may be
6786   different, we use here minimal values required by ANSI C standard
6787   instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc.  This is a good
6788   approximation.  */
6789
6790static void
6791output_range_type (f, min_range_value, max_range_value)
6792     FILE *f;
6793     long int min_range_value;
6794     long int max_range_value;
6795{
6796  if (min_range_value >= 0 && max_range_value <= 255)
6797    fprintf (f, "unsigned char");
6798  else if (min_range_value >= -127 && max_range_value <= 127)
6799    fprintf (f, "signed char");
6800  else if (min_range_value >= 0 && max_range_value <= 65535)
6801    fprintf (f, "unsigned short");
6802  else if (min_range_value >= -32767 && max_range_value <= 32767)
6803    fprintf (f, "short");
6804  else
6805    fprintf (f, "int");
6806}
6807
6808/* The following macro value is used as value of member
6809   `longest_path_length' of state when we are processing path and the
6810   state on the path.  */
6811
6812#define ON_THE_PATH -2
6813
6814/* The following recursive function searches for the length of the
6815   longest path starting from STATE which does not contain cycles and
6816   `cycle advance' arcs.  */
6817
6818static int
6819longest_path_length (state)
6820     state_t state;
6821{
6822  arc_t arc;
6823  int length, result;
6824
6825  if (state->longest_path_length == ON_THE_PATH)
6826    /* We don't expect the path cycle here.  Our graph may contain
6827       only cycles with one state on the path not containing `cycle
6828       advance' arcs -- see comment below.  */
6829    abort ();
6830  else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6831    /* We alreday visited the state.  */
6832    return state->longest_path_length;
6833
6834  result = 0;
6835  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6836    /* Ignore cycles containing one state and `cycle advance' arcs.  */
6837    if (arc->to_state != state
6838	&& (arc->insn->insn_reserv_decl
6839	    != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6840    {
6841      length = longest_path_length (arc->to_state);
6842      if (length > result)
6843	result = length;
6844    }
6845  state->longest_path_length = result + 1;
6846  return result;
6847}
6848
6849/* The following variable value is value of the corresponding global
6850   variable in the automaton based pipeline interface.  */
6851
6852static int max_dfa_issue_rate;
6853
6854/* The following function processes the longest path length staring
6855   from STATE to find MAX_DFA_ISSUE_RATE.  */
6856
6857static void
6858process_state_longest_path_length (state)
6859     state_t state;
6860{
6861  int value;
6862
6863  value = longest_path_length (state);
6864  if (value > max_dfa_issue_rate)
6865    max_dfa_issue_rate = value;
6866}
6867
6868/* The following macro value is name of the corresponding global
6869   variable in the automaton based pipeline interface.  */
6870
6871#define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
6872
6873/* The following function calculates value of the corresponding
6874   global variable and outputs its declaration.  */
6875
6876static void
6877output_dfa_max_issue_rate ()
6878{
6879  automaton_t automaton;
6880
6881  if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
6882    abort ();
6883  max_dfa_issue_rate = 0;
6884  for (automaton = description->first_automaton;
6885       automaton != NULL;
6886       automaton = automaton->next_automaton)
6887    pass_states (automaton, process_state_longest_path_length);
6888  fprintf (output_file, "\nint %s = %d;\n",
6889	   MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
6890}
6891
6892/* The function outputs all initialization values of VECT with length
6893   vect_length.  */
6894static void
6895output_vect (vect, vect_length)
6896     vect_el_t *vect;
6897     int vect_length;
6898{
6899  int els_on_line;
6900
6901  els_on_line = 1;
6902  if (vect_length == 0)
6903    fprintf (output_file,
6904             "0 /* This is dummy el because the vect is empty */");
6905  else
6906    {
6907      do
6908        {
6909          fprintf (output_file, "%5ld", (long) *vect);
6910          vect_length--;
6911          if (els_on_line == 10)
6912	    {
6913	      els_on_line = 0;
6914	      fprintf (output_file, ",\n");
6915	    }
6916          else if (vect_length != 0)
6917            fprintf (output_file, ", ");
6918          els_on_line++;
6919          vect++;
6920        }
6921      while (vect_length != 0);
6922    }
6923}
6924
6925/* The following is name of the structure which represents DFA(s) for
6926   PHR.  */
6927#define CHIP_NAME "DFA_chip"
6928
6929/* The following is name of member which represents state of a DFA for
6930   PHR.  */
6931static void
6932output_chip_member_name (f, automaton)
6933     FILE *f;
6934     automaton_t automaton;
6935{
6936  if (automaton->corresponding_automaton_decl == NULL)
6937    fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6938  else
6939    fprintf (f, "%s_automaton_state",
6940             automaton->corresponding_automaton_decl->name);
6941}
6942
6943/* The following is name of temporary variable which stores state of a
6944   DFA for PHR.  */
6945static void
6946output_temp_chip_member_name (f, automaton)
6947     FILE *f;
6948     automaton_t automaton;
6949{
6950  fprintf (f, "_");
6951  output_chip_member_name (f, automaton);
6952}
6953
6954/* This is name of macro value which is code of pseudo_insn
6955   representing advancing cpu cycle.  Its value is used as internal
6956   code unknown insn.  */
6957#define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6958
6959/* Output name of translate vector for given automaton.  */
6960static void
6961output_translate_vect_name (f, automaton)
6962     FILE *f;
6963     automaton_t automaton;
6964{
6965  if (automaton->corresponding_automaton_decl == NULL)
6966    fprintf (f, "translate_%d", automaton->automaton_order_num);
6967  else
6968    fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6969}
6970
6971/* Output name for simple transition table representation.  */
6972static void
6973output_trans_full_vect_name (f, automaton)
6974     FILE *f;
6975     automaton_t automaton;
6976{
6977  if (automaton->corresponding_automaton_decl == NULL)
6978    fprintf (f, "transitions_%d", automaton->automaton_order_num);
6979  else
6980    fprintf (f, "%s_transitions",
6981	     automaton->corresponding_automaton_decl->name);
6982}
6983
6984/* Output name of comb vector of the transition table for given
6985   automaton.  */
6986static void
6987output_trans_comb_vect_name (f, automaton)
6988     FILE *f;
6989     automaton_t automaton;
6990{
6991  if (automaton->corresponding_automaton_decl == NULL)
6992    fprintf (f, "transitions_%d", automaton->automaton_order_num);
6993  else
6994    fprintf (f, "%s_transitions",
6995             automaton->corresponding_automaton_decl->name);
6996}
6997
6998/* Output name of check vector of the transition table for given
6999   automaton.  */
7000static void
7001output_trans_check_vect_name (f, automaton)
7002     FILE *f;
7003     automaton_t automaton;
7004{
7005  if (automaton->corresponding_automaton_decl == NULL)
7006    fprintf (f, "check_%d", automaton->automaton_order_num);
7007  else
7008    fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7009}
7010
7011/* Output name of base vector of the transition table for given
7012   automaton.  */
7013static void
7014output_trans_base_vect_name (f, automaton)
7015     FILE *f;
7016     automaton_t automaton;
7017{
7018  if (automaton->corresponding_automaton_decl == NULL)
7019    fprintf (f, "base_%d", automaton->automaton_order_num);
7020  else
7021    fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7022}
7023
7024/* Output name for simple alternatives number representation.  */
7025static void
7026output_state_alts_full_vect_name (f, automaton)
7027     FILE *f;
7028     automaton_t automaton;
7029{
7030  if (automaton->corresponding_automaton_decl == NULL)
7031    fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7032  else
7033    fprintf (f, "%s_state_alts",
7034             automaton->corresponding_automaton_decl->name);
7035}
7036
7037/* Output name of comb vector of the alternatives number table for given
7038   automaton.  */
7039static void
7040output_state_alts_comb_vect_name (f, automaton)
7041     FILE *f;
7042     automaton_t automaton;
7043{
7044  if (automaton->corresponding_automaton_decl == NULL)
7045    fprintf (f, "state_alts_%d", automaton->automaton_order_num);
7046  else
7047    fprintf (f, "%s_state_alts",
7048             automaton->corresponding_automaton_decl->name);
7049}
7050
7051/* Output name of check vector of the alternatives number table for given
7052   automaton.  */
7053static void
7054output_state_alts_check_vect_name (f, automaton)
7055     FILE *f;
7056     automaton_t automaton;
7057{
7058  if (automaton->corresponding_automaton_decl == NULL)
7059    fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
7060  else
7061    fprintf (f, "%s_check_state_alts",
7062	     automaton->corresponding_automaton_decl->name);
7063}
7064
7065/* Output name of base vector of the alternatives number table for given
7066   automaton.  */
7067static void
7068output_state_alts_base_vect_name (f, automaton)
7069     FILE *f;
7070     automaton_t automaton;
7071{
7072  if (automaton->corresponding_automaton_decl == NULL)
7073    fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
7074  else
7075    fprintf (f, "%s_base_state_alts",
7076	     automaton->corresponding_automaton_decl->name);
7077}
7078
7079/* Output name of simple min issue delay table representation.  */
7080static void
7081output_min_issue_delay_vect_name (f, automaton)
7082     FILE *f;
7083     automaton_t automaton;
7084{
7085  if (automaton->corresponding_automaton_decl == NULL)
7086    fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7087  else
7088    fprintf (f, "%s_min_issue_delay",
7089             automaton->corresponding_automaton_decl->name);
7090}
7091
7092/* Output name of deadlock vector for given automaton.  */
7093static void
7094output_dead_lock_vect_name (f, automaton)
7095     FILE *f;
7096     automaton_t automaton;
7097{
7098  if (automaton->corresponding_automaton_decl == NULL)
7099    fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7100  else
7101    fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7102}
7103
7104/* Output name of reserved units table for AUTOMATON into file F.  */
7105static void
7106output_reserved_units_table_name (f, automaton)
7107     FILE *f;
7108     automaton_t automaton;
7109{
7110  if (automaton->corresponding_automaton_decl == NULL)
7111    fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7112  else
7113    fprintf (f, "%s_reserved_units",
7114	     automaton->corresponding_automaton_decl->name);
7115}
7116
7117/* Name of the PHR interface macro.  */
7118#define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
7119
7120/* Name of the PHR interface macro.  */
7121#define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7122
7123/* Names of an internal functions: */
7124#define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7125
7126/* This is external type of DFA(s) state.  */
7127#define STATE_TYPE_NAME "state_t"
7128
7129#define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7130
7131#define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
7132
7133#define INTERNAL_RESET_FUNC_NAME "internal_reset"
7134
7135#define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7136
7137#define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7138
7139/* Name of cache of insn dfa codes.  */
7140#define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7141
7142/* Name of length of cache of insn dfa codes.  */
7143#define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7144
7145/* Names of the PHR interface functions: */
7146#define SIZE_FUNC_NAME "state_size"
7147
7148#define TRANSITION_FUNC_NAME "state_transition"
7149
7150#define STATE_ALTS_FUNC_NAME "state_alts"
7151
7152#define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7153
7154#define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7155
7156#define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7157
7158#define RESET_FUNC_NAME "state_reset"
7159
7160#define INSN_LATENCY_FUNC_NAME "insn_latency"
7161
7162#define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7163
7164#define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7165
7166#define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7167
7168#define DFA_START_FUNC_NAME  "dfa_start"
7169
7170#define DFA_FINISH_FUNC_NAME "dfa_finish"
7171
7172/* Names of parameters of the PHR interface functions.  */
7173#define STATE_NAME "state"
7174
7175#define INSN_PARAMETER_NAME "insn"
7176
7177#define INSN2_PARAMETER_NAME "insn2"
7178
7179#define CHIP_PARAMETER_NAME "chip"
7180
7181#define FILE_PARAMETER_NAME "f"
7182
7183#define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7184
7185#define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7186
7187/* Names of the variables whose values are internal insn code of rtx
7188   insn.  */
7189#define INTERNAL_INSN_CODE_NAME "insn_code"
7190
7191#define INTERNAL_INSN2_CODE_NAME "insn2_code"
7192
7193/* Names of temporary variables in some functions.  */
7194#define TEMPORARY_VARIABLE_NAME "temp"
7195
7196#define I_VARIABLE_NAME "i"
7197
7198/* Name of result variable in some functions.  */
7199#define RESULT_VARIABLE_NAME "res"
7200
7201/* Name of function (attribute) to translate insn into number of insn
7202   alternatives reservation.  */
7203#define INSN_ALTS_FUNC_NAME "insn_alts"
7204
7205/* Name of function (attribute) to translate insn into internal insn
7206   code.  */
7207#define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7208
7209/* Name of function (attribute) to translate insn into internal insn
7210   code with caching.  */
7211#define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7212
7213/* Name of function (attribute) to translate insn into internal insn
7214   code.  */
7215#define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
7216
7217/* Name of function (attribute) to translate insn into internal insn
7218   code.  */
7219#define BYPASS_P_FUNC_NAME "bypass_p"
7220
7221/* Output C type which is used for representation of codes of states
7222   of AUTOMATON.  */
7223static void
7224output_state_member_type (f, automaton)
7225     FILE *f;
7226     automaton_t automaton;
7227{
7228  output_range_type (f, 0, automaton->achieved_states_num);
7229}
7230
7231/* Output definition of the structure representing current DFA(s)
7232   state(s).  */
7233static void
7234output_chip_definitions ()
7235{
7236  automaton_t automaton;
7237
7238  fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7239  for (automaton = description->first_automaton;
7240       automaton != NULL;
7241       automaton = automaton->next_automaton)
7242    {
7243      fprintf (output_file, "  ");
7244      output_state_member_type (output_file, automaton);
7245      fprintf (output_file, " ");
7246      output_chip_member_name (output_file, automaton);
7247      fprintf (output_file, ";\n");
7248    }
7249  fprintf (output_file, "};\n\n");
7250#if 0
7251  fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7252#endif
7253}
7254
7255
7256/* The function outputs translate vector of internal insn code into
7257   insn equivalence class number.  The equivalence class number is
7258   used to access to table and vectors reprewsenting DFA(s).  */
7259static void
7260output_translate_vect (automaton)
7261     automaton_t automaton;
7262{
7263  ainsn_t ainsn;
7264  int insn_value;
7265  vla_hwint_t translate_vect;
7266
7267  VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7268  VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7269  for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
7270    /* Undefined value */
7271    VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7272  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7273    VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7274      = ainsn->insn_equiv_class_num;
7275  fprintf (output_file,
7276           "/* Vector translating external insn codes to internal ones.*/\n");
7277  fprintf (output_file, "static const ");
7278  output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7279  fprintf (output_file, " ");
7280  output_translate_vect_name (output_file, automaton);
7281  fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7282  output_vect (VLA_HWINT_BEGIN (translate_vect),
7283	       VLA_HWINT_LENGTH (translate_vect));
7284  fprintf (output_file, "};\n\n");
7285  VLA_HWINT_DELETE (translate_vect);
7286}
7287
7288/* The value in a table state x ainsn -> something which represents
7289   undefined value.  */
7290static int undefined_vect_el_value;
7291
7292/* The following function returns nonzero value if the best
7293   representation of the table is comb vector.  */
7294static int
7295comb_vect_p (tab)
7296     state_ainsn_table_t tab;
7297{
7298  return  (2 * VLA_HWINT_LENGTH (tab->full_vect)
7299           > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7300}
7301
7302/* The following function creates new table for AUTOMATON.  */
7303static state_ainsn_table_t
7304create_state_ainsn_table (automaton)
7305     automaton_t automaton;
7306{
7307  state_ainsn_table_t tab;
7308  int full_vect_length;
7309  int i;
7310
7311  tab = create_node (sizeof (struct state_ainsn_table));
7312  tab->automaton = automaton;
7313  VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7314  VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7315  VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7316  VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7317  VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7318  full_vect_length = (automaton->insn_equiv_classes_num
7319                      * automaton->achieved_states_num);
7320  VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7321  for (i = 0; i < full_vect_length; i++)
7322    VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7323  tab->min_base_vect_el_value = 0;
7324  tab->max_base_vect_el_value = 0;
7325  tab->min_comb_vect_el_value = 0;
7326  tab->max_comb_vect_el_value = 0;
7327  return tab;
7328}
7329
7330/* The following function outputs the best C representation of the
7331   table TAB of given TABLE_NAME.  */
7332static void
7333output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7334                          output_comb_vect_name_func,
7335                          output_check_vect_name_func,
7336                          output_base_vect_name_func)
7337     state_ainsn_table_t tab;
7338     char *table_name;
7339     void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7340     void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7341     void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7342     void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7343{
7344  if (!comb_vect_p (tab))
7345    {
7346      fprintf (output_file, "/* Vector for %s.  */\n", table_name);
7347      fprintf (output_file, "static const ");
7348      output_range_type (output_file, tab->min_comb_vect_el_value,
7349                         tab->max_comb_vect_el_value);
7350      fprintf (output_file, " ");
7351      (*output_full_vect_name_func) (output_file, tab->automaton);
7352      fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7353      output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7354                   VLA_HWINT_LENGTH (tab->full_vect));
7355      fprintf (output_file, "};\n\n");
7356    }
7357  else
7358    {
7359      fprintf (output_file, "/* Comb vector for %s.  */\n", table_name);
7360      fprintf (output_file, "static const ");
7361      output_range_type (output_file, tab->min_comb_vect_el_value,
7362                         tab->max_comb_vect_el_value);
7363      fprintf (output_file, " ");
7364      (*output_comb_vect_name_func) (output_file, tab->automaton);
7365      fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7366      output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7367                   VLA_HWINT_LENGTH (tab->comb_vect));
7368      fprintf (output_file, "};\n\n");
7369      fprintf (output_file, "/* Check vector for %s.  */\n", table_name);
7370      fprintf (output_file, "static const ");
7371      output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7372      fprintf (output_file, " ");
7373      (*output_check_vect_name_func) (output_file, tab->automaton);
7374      fprintf (output_file, "[] = {\n");
7375      output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7376                   VLA_HWINT_LENGTH (tab->check_vect));
7377      fprintf (output_file, "};\n\n");
7378      fprintf (output_file, "/* Base vector for %s.  */\n", table_name);
7379      fprintf (output_file, "static const ");
7380      output_range_type (output_file, tab->min_base_vect_el_value,
7381                         tab->max_base_vect_el_value);
7382      fprintf (output_file, " ");
7383      (*output_base_vect_name_func) (output_file, tab->automaton);
7384      fprintf (output_file, "[] = {\n");
7385      output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7386                   VLA_HWINT_LENGTH (tab->base_vect));
7387      fprintf (output_file, "};\n\n");
7388    }
7389}
7390
7391/* The following function adds vector with length VECT_LENGTH and
7392   elements pointed by VECT to table TAB as its line with number
7393   VECT_NUM.  */
7394static void
7395add_vect (tab, vect_num, vect, vect_length)
7396     state_ainsn_table_t tab;
7397     int vect_num;
7398     vect_el_t *vect;
7399     int vect_length;
7400{
7401  int real_vect_length;
7402  vect_el_t *comb_vect_start;
7403  vect_el_t *check_vect_start;
7404  int comb_vect_index;
7405  int comb_vect_els_num;
7406  int vect_index;
7407  int first_unempty_vect_index;
7408  int additional_els_num;
7409  int no_state_value;
7410  vect_el_t vect_el;
7411  int i;
7412
7413  if (vect_length == 0)
7414    abort ();
7415  real_vect_length = tab->automaton->insn_equiv_classes_num;
7416  if (vect [vect_length - 1] == undefined_vect_el_value)
7417    abort ();
7418  /* Form full vector in the table: */
7419  for (i = 0; i < vect_length; i++)
7420    VLA_HWINT (tab->full_vect,
7421               i + tab->automaton->insn_equiv_classes_num * vect_num)
7422      = vect [i];
7423  /* Form comb vector in the table: */
7424  if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7425    abort ();
7426  comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7427  comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7428  for (first_unempty_vect_index = 0;
7429       first_unempty_vect_index < vect_length;
7430       first_unempty_vect_index++)
7431    if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7432      break;
7433  /* Search for the place in comb vect for the inserted vect.  */
7434  for (comb_vect_index = 0;
7435       comb_vect_index < comb_vect_els_num;
7436       comb_vect_index++)
7437    {
7438      for (vect_index = first_unempty_vect_index;
7439           vect_index < vect_length
7440             && vect_index + comb_vect_index < comb_vect_els_num;
7441           vect_index++)
7442        if (vect [vect_index] != undefined_vect_el_value
7443            && (comb_vect_start [vect_index + comb_vect_index]
7444		!= undefined_vect_el_value))
7445          break;
7446      if (vect_index >= vect_length
7447          || vect_index + comb_vect_index >= comb_vect_els_num)
7448        break;
7449    }
7450  /* Slot was found.  */
7451  additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7452  if (additional_els_num < 0)
7453    additional_els_num = 0;
7454  /* Expand comb and check vectors.  */
7455  vect_el = undefined_vect_el_value;
7456  no_state_value = tab->automaton->achieved_states_num;
7457  while (additional_els_num > 0)
7458    {
7459      VLA_HWINT_ADD (tab->comb_vect, vect_el);
7460      VLA_HWINT_ADD (tab->check_vect, no_state_value);
7461      additional_els_num--;
7462    }
7463  comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7464  check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7465  if (VLA_HWINT_LENGTH (tab->comb_vect)
7466      < (size_t) (comb_vect_index + real_vect_length))
7467    abort ();
7468  /* Fill comb and check vectors.  */
7469  for (vect_index = 0; vect_index < vect_length; vect_index++)
7470    if (vect [vect_index] != undefined_vect_el_value)
7471      {
7472        if (comb_vect_start [comb_vect_index + vect_index]
7473	    != undefined_vect_el_value)
7474	  abort ();
7475        comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7476        if (vect [vect_index] < 0)
7477	  abort ();
7478        if (tab->max_comb_vect_el_value < vect [vect_index])
7479          tab->max_comb_vect_el_value = vect [vect_index];
7480        if (tab->min_comb_vect_el_value > vect [vect_index])
7481          tab->min_comb_vect_el_value = vect [vect_index];
7482        check_vect_start [comb_vect_index + vect_index] = vect_num;
7483      }
7484  if (tab->max_base_vect_el_value < comb_vect_index)
7485    tab->max_base_vect_el_value = comb_vect_index;
7486  if (tab->min_base_vect_el_value > comb_vect_index)
7487    tab->min_base_vect_el_value = comb_vect_index;
7488  VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7489}
7490
7491/* Return number of out arcs of STATE.  */
7492static int
7493out_state_arcs_num (state)
7494     state_t state;
7495{
7496  int result;
7497  arc_t arc;
7498
7499  result = 0;
7500  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7501    {
7502      if (arc->insn == NULL)
7503	abort ();
7504      if (arc->insn->first_ainsn_with_given_equialence_num)
7505        result++;
7506    }
7507  return result;
7508}
7509
7510/* Compare number of possible transitions from the states.  */
7511static int
7512compare_transition_els_num (state_ptr_1, state_ptr_2)
7513     const void *state_ptr_1;
7514     const void *state_ptr_2;
7515{
7516  int transition_els_num_1;
7517  int transition_els_num_2;
7518
7519  transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7520  transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7521  if (transition_els_num_1 < transition_els_num_2)
7522    return 1;
7523  else if (transition_els_num_1 == transition_els_num_2)
7524    return 0;
7525  else
7526    return -1;
7527}
7528
7529/* The function adds element EL_VALUE to vector VECT for a table state
7530   x AINSN.  */
7531static void
7532add_vect_el (vect, ainsn, el_value)
7533     vla_hwint_t *vect;
7534     ainsn_t ainsn;
7535     int el_value;
7536{
7537  int equiv_class_num;
7538  int vect_index;
7539
7540  if (ainsn == NULL)
7541    abort ();
7542  equiv_class_num = ainsn->insn_equiv_class_num;
7543  for (vect_index = VLA_HWINT_LENGTH (*vect);
7544       vect_index <= equiv_class_num;
7545       vect_index++)
7546    VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7547  VLA_HWINT (*vect, equiv_class_num) = el_value;
7548}
7549
7550/* This is for forming vector of states of an automaton.  */
7551static vla_ptr_t output_states_vect;
7552
7553/* The function is called by function pass_states.  The function adds
7554   STATE to `output_states_vect'.  */
7555static void
7556add_states_vect_el (state)
7557     state_t state;
7558{
7559  VLA_PTR_ADD (output_states_vect, state);
7560}
7561
7562/* Form and output vectors (comb, check, base or full vector)
7563   representing transition table of AUTOMATON.  */
7564static void
7565output_trans_table (automaton)
7566     automaton_t automaton;
7567{
7568  state_t *state_ptr;
7569  arc_t arc;
7570  vla_hwint_t transition_vect;
7571
7572  undefined_vect_el_value = automaton->achieved_states_num;
7573  automaton->trans_table = create_state_ainsn_table (automaton);
7574  /* Create vect of pointers to states ordered by num of transitions
7575     from the state (state with the maximum num is the first).  */
7576  VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7577  pass_states (automaton, add_states_vect_el);
7578  qsort (VLA_PTR_BEGIN (output_states_vect),
7579         VLA_PTR_LENGTH (output_states_vect),
7580         sizeof (state_t), compare_transition_els_num);
7581  VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7582  for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7583       state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7584       state_ptr++)
7585    {
7586      VLA_HWINT_NULLIFY (transition_vect);
7587      for (arc = first_out_arc (*state_ptr);
7588	   arc != NULL;
7589	   arc = next_out_arc (arc))
7590        {
7591          if (arc->insn == NULL)
7592	    abort ();
7593          if (arc->insn->first_ainsn_with_given_equialence_num)
7594            add_vect_el (&transition_vect, arc->insn,
7595                         arc->to_state->order_state_num);
7596        }
7597      add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7598                VLA_HWINT_BEGIN (transition_vect),
7599                VLA_HWINT_LENGTH (transition_vect));
7600    }
7601  output_state_ainsn_table
7602    (automaton->trans_table, (char *) "state transitions",
7603     output_trans_full_vect_name, output_trans_comb_vect_name,
7604     output_trans_check_vect_name, output_trans_base_vect_name);
7605  VLA_PTR_DELETE (output_states_vect);
7606  VLA_HWINT_DELETE (transition_vect);
7607}
7608
7609/* Form and output vectors (comb, check, base or simple vect)
7610   representing alts number table of AUTOMATON.  The table is state x
7611   ainsn -> number of possible alternative reservations by the
7612   ainsn.  */
7613static void
7614output_state_alts_table (automaton)
7615     automaton_t automaton;
7616{
7617  state_t *state_ptr;
7618  arc_t arc;
7619  vla_hwint_t state_alts_vect;
7620
7621  undefined_vect_el_value = 0; /* no alts when transition is not possible */
7622  automaton->state_alts_table = create_state_ainsn_table (automaton);
7623  /* Create vect of pointers to states ordered by num of transitions
7624     from the state (state with the maximum num is the first).  */
7625  VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7626  pass_states (automaton, add_states_vect_el);
7627  qsort (VLA_PTR_BEGIN (output_states_vect),
7628         VLA_PTR_LENGTH (output_states_vect),
7629         sizeof (state_t), compare_transition_els_num);
7630  /* Create base, comb, and check vectors.  */
7631  VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7632  for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7633       state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7634       state_ptr++)
7635    {
7636      VLA_HWINT_NULLIFY (state_alts_vect);
7637      for (arc = first_out_arc (*state_ptr);
7638	   arc != NULL;
7639	   arc = next_out_arc (arc))
7640        {
7641          if (arc->insn == NULL)
7642	    abort ();
7643          if (arc->insn->first_ainsn_with_given_equialence_num)
7644            add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7645        }
7646      add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7647                VLA_HWINT_BEGIN (state_alts_vect),
7648                VLA_HWINT_LENGTH (state_alts_vect));
7649    }
7650  output_state_ainsn_table
7651    (automaton->state_alts_table, (char *) "state insn alternatives",
7652     output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7653     output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7654  VLA_PTR_DELETE (output_states_vect);
7655  VLA_HWINT_DELETE (state_alts_vect);
7656}
7657
7658/* The current number of passing states to find minimal issue delay
7659   value for an ainsn and state.  */
7660static int curr_state_pass_num;
7661
7662
7663/* This recursive function passes states to find minimal issue delay
7664   value for AINSN.  The state being visited is STATE.  The function
7665   returns minimal issue delay value for AINSN in STATE or -1 if we
7666   enter into a loop.  */
7667static int
7668min_issue_delay_pass_states (state, ainsn)
7669     state_t state;
7670     ainsn_t ainsn;
7671{
7672  arc_t arc;
7673  int min_insn_issue_delay, insn_issue_delay;
7674
7675  if (state->state_pass_num == curr_state_pass_num
7676      || state->min_insn_issue_delay != -1)
7677    /* We've entered into a loop or already have the correct value for
7678       given state and ainsn.  */
7679    return state->min_insn_issue_delay;
7680  state->state_pass_num = curr_state_pass_num;
7681  min_insn_issue_delay = -1;
7682  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7683    if (arc->insn == ainsn)
7684      {
7685	min_insn_issue_delay = 0;
7686	break;
7687      }
7688    else
7689      {
7690        insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7691	if (insn_issue_delay != -1)
7692	  {
7693	    if (arc->insn->insn_reserv_decl
7694		== DECL_INSN_RESERV (advance_cycle_insn_decl))
7695	      insn_issue_delay++;
7696	    if (min_insn_issue_delay == -1
7697		|| min_insn_issue_delay > insn_issue_delay)
7698	      {
7699		min_insn_issue_delay = insn_issue_delay;
7700		if (insn_issue_delay == 0)
7701		  break;
7702	      }
7703	  }
7704      }
7705  return min_insn_issue_delay;
7706}
7707
7708/* The function searches minimal issue delay value for AINSN in STATE.
7709   The function can return negative value if we can not issue AINSN.  We
7710   will report about it later.  */
7711static int
7712min_issue_delay (state, ainsn)
7713     state_t state;
7714     ainsn_t ainsn;
7715{
7716  curr_state_pass_num++;
7717  state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7718  return state->min_insn_issue_delay;
7719}
7720
7721/* The function initiates code for finding minimal issue delay values.
7722   It should be called only once.  */
7723static void
7724initiate_min_issue_delay_pass_states ()
7725{
7726  curr_state_pass_num = 0;
7727}
7728
7729/* Form and output vectors representing minimal issue delay table of
7730   AUTOMATON.  The table is state x ainsn -> minimal issue delay of
7731   the ainsn.  */
7732static void
7733output_min_issue_delay_table (automaton)
7734     automaton_t automaton;
7735{
7736  vla_hwint_t min_issue_delay_vect;
7737  vla_hwint_t compressed_min_issue_delay_vect;
7738  vect_el_t min_delay;
7739  ainsn_t ainsn;
7740  state_t *state_ptr;
7741  int i;
7742
7743  /* Create vect of pointers to states ordered by num of transitions
7744     from the state (state with the maximum num is the first).  */
7745  VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7746  pass_states (automaton, add_states_vect_el);
7747  VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7748  VLA_HWINT_EXPAND (min_issue_delay_vect,
7749		    VLA_HWINT_LENGTH (output_states_vect)
7750		    * automaton->insn_equiv_classes_num);
7751  for (i = 0;
7752       i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7753	    * automaton->insn_equiv_classes_num);
7754       i++)
7755    VLA_HWINT (min_issue_delay_vect, i) = 0;
7756  automaton->max_min_delay = 0;
7757  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7758    if (ainsn->first_ainsn_with_given_equialence_num)
7759      {
7760	for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7761	     state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7762	     state_ptr++)
7763	  (*state_ptr)->min_insn_issue_delay = -1;
7764	for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7765	     state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7766	     state_ptr++)
7767	  {
7768            min_delay = min_issue_delay (*state_ptr, ainsn);
7769	    if (automaton->max_min_delay < min_delay)
7770	      automaton->max_min_delay = min_delay;
7771	    VLA_HWINT (min_issue_delay_vect,
7772		       (*state_ptr)->order_state_num
7773		       * automaton->insn_equiv_classes_num
7774		       + ainsn->insn_equiv_class_num) = min_delay;
7775	  }
7776      }
7777  fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
7778  fprintf (output_file, "static const ");
7779  output_range_type (output_file, 0, automaton->max_min_delay);
7780  fprintf (output_file, " ");
7781  output_min_issue_delay_vect_name (output_file, automaton);
7782  fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7783  /* Compress the vector */
7784  if (automaton->max_min_delay < 2)
7785    automaton->min_issue_delay_table_compression_factor = 8;
7786  else if (automaton->max_min_delay < 4)
7787    automaton->min_issue_delay_table_compression_factor = 4;
7788  else if (automaton->max_min_delay < 16)
7789    automaton->min_issue_delay_table_compression_factor = 2;
7790  else
7791    automaton->min_issue_delay_table_compression_factor = 1;
7792  VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7793		    "compressed min issue delay vector");
7794  VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7795		    (VLA_HWINT_LENGTH (min_issue_delay_vect)
7796		     + automaton->min_issue_delay_table_compression_factor
7797		     - 1)
7798		    / automaton->min_issue_delay_table_compression_factor);
7799  for (i = 0;
7800       i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7801       i++)
7802    VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7803  for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7804    VLA_HWINT (compressed_min_issue_delay_vect,
7805	       i / automaton->min_issue_delay_table_compression_factor)
7806      |= (VLA_HWINT (min_issue_delay_vect, i)
7807	  << (8 - (i % automaton->min_issue_delay_table_compression_factor
7808		   + 1)
7809	      * (8 / automaton->min_issue_delay_table_compression_factor)));
7810  output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7811               VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7812  fprintf (output_file, "};\n\n");
7813  VLA_PTR_DELETE (output_states_vect);
7814  VLA_HWINT_DELETE (min_issue_delay_vect);
7815  VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7816}
7817
7818#ifndef NDEBUG
7819/* Number of states which contains transition only by advancing cpu
7820   cycle.  */
7821static int locked_states_num;
7822#endif
7823
7824/* Form and output vector representing the locked states of
7825   AUTOMATON.  */
7826static void
7827output_dead_lock_vect (automaton)
7828     automaton_t automaton;
7829{
7830  state_t *state_ptr;
7831  arc_t arc;
7832  vla_hwint_t dead_lock_vect;
7833
7834  /* Create vect of pointers to states ordered by num of
7835     transitions from the state (state with the maximum num is the
7836     first).  */
7837  VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7838  pass_states (automaton, add_states_vect_el);
7839  VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7840  VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7841  for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7842       state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7843       state_ptr++)
7844    {
7845      arc = first_out_arc (*state_ptr);
7846      if (arc == NULL)
7847	abort ();
7848      VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
7849        = (next_out_arc (arc) == NULL
7850           && (arc->insn->insn_reserv_decl
7851               == DECL_INSN_RESERV (advance_cycle_insn_decl)) ? 1 : 0);
7852#ifndef NDEBUG
7853      if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
7854        locked_states_num++;
7855#endif
7856    }
7857  fprintf (output_file, "/* Vector for locked state flags.  */\n");
7858  fprintf (output_file, "static const ");
7859  output_range_type (output_file, 0, 1);
7860  fprintf (output_file, " ");
7861  output_dead_lock_vect_name (output_file, automaton);
7862  fprintf (output_file, "[] = {\n");
7863  output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
7864	       VLA_HWINT_LENGTH (dead_lock_vect));
7865  fprintf (output_file, "};\n\n");
7866  VLA_HWINT_DELETE (dead_lock_vect);
7867  VLA_PTR_DELETE (output_states_vect);
7868}
7869
7870/* Form and output vector representing reserved units of the states of
7871   AUTOMATON.  */
7872static void
7873output_reserved_units_table (automaton)
7874     automaton_t automaton;
7875{
7876  state_t *curr_state_ptr;
7877  vla_hwint_t reserved_units_table;
7878  size_t state_byte_size;
7879  int i;
7880
7881  /* Create vect of pointers to states.  */
7882  VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7883  pass_states (automaton, add_states_vect_el);
7884  /* Create vector.  */
7885  VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
7886  state_byte_size = (description->query_units_num + 7) / 8;
7887  VLA_HWINT_EXPAND (reserved_units_table,
7888		    VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7889  for (i = 0;
7890       i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7891       i++)
7892    VLA_HWINT (reserved_units_table, i) = 0;
7893  for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
7894       curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7895       curr_state_ptr++)
7896    {
7897      for (i = 0; i < description->units_num; i++)
7898	if (units_array [i]->query_p)
7899	  {
7900	    if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i))
7901	      VLA_HWINT (reserved_units_table,
7902			 (*curr_state_ptr)->order_state_num * state_byte_size
7903			 + units_array [i]->query_num / 8)
7904		+= (1 << (units_array [i]->query_num % 8));
7905	  }
7906    }
7907  fprintf (output_file, "/* Vector for reserved units of states.  */\n");
7908  fprintf (output_file, "static const ");
7909  output_range_type (output_file, 0, 255);
7910  fprintf (output_file, " ");
7911  output_reserved_units_table_name (output_file, automaton);
7912  fprintf (output_file, "[] = {\n");
7913  output_vect (VLA_HWINT_BEGIN (reserved_units_table),
7914               VLA_HWINT_LENGTH (reserved_units_table));
7915  fprintf (output_file, "};\n\n");
7916  VLA_HWINT_DELETE (reserved_units_table);
7917  VLA_PTR_DELETE (output_states_vect);
7918}
7919
7920/* The function outputs all tables representing DFA(s) used for fast
7921   pipeline hazards recognition.  */
7922static void
7923output_tables ()
7924{
7925  automaton_t automaton;
7926
7927#ifndef NDEBUG
7928  locked_states_num = 0;
7929#endif
7930  initiate_min_issue_delay_pass_states ();
7931  for (automaton = description->first_automaton;
7932       automaton != NULL;
7933       automaton = automaton->next_automaton)
7934    {
7935      output_translate_vect (automaton);
7936      output_trans_table (automaton);
7937      fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
7938      output_state_alts_table (automaton);
7939      fprintf (output_file, "\n#endif /* #if %s */\n\n",
7940	       AUTOMATON_STATE_ALTS_MACRO_NAME);
7941      output_min_issue_delay_table (automaton);
7942      output_dead_lock_vect (automaton);
7943      if (no_minimization_flag)
7944	{
7945	  fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
7946	  output_reserved_units_table (automaton);
7947	  fprintf (output_file, "\n#endif /* #if %s */\n\n",
7948		   CPU_UNITS_QUERY_MACRO_NAME);
7949	}
7950    }
7951  fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7952           DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7953}
7954
7955/* The function outputs definition and value of PHR interface variable
7956   `max_insn_queue_index'.  Its value is not less than maximal queue
7957   length needed for the insn scheduler.  */
7958static void
7959output_max_insn_queue_index_def ()
7960{
7961  int i, max, latency;
7962  decl_t decl;
7963
7964  max = description->max_insn_reserv_cycles;
7965  for (i = 0; i < description->decls_num; i++)
7966    {
7967      decl = description->decls [i];
7968      if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7969	{
7970	  latency = DECL_INSN_RESERV (decl)->default_latency;
7971	  if (latency > max)
7972	    max = latency;
7973	}
7974      else if (decl->mode == dm_bypass)
7975	{
7976	  latency = DECL_BYPASS (decl)->latency;
7977	  if (latency > max)
7978	    max = latency;
7979	}
7980    }
7981  for (i = 0; (1 << i) <= max; i++)
7982    ;
7983  if (i < 0)
7984    abort ();
7985  fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
7986}
7987
7988
7989/* The function outputs switch cases for insn reseravtions using
7990   function *output_automata_list_code.  */
7991static void
7992output_insn_code_cases (output_automata_list_code)
7993     void (*output_automata_list_code) PARAMS ((automata_list_el_t));
7994{
7995  decl_t decl, decl2;
7996  int i, j;
7997
7998  for (i = 0; i < description->decls_num; i++)
7999    {
8000      decl = description->decls [i];
8001      if (decl->mode == dm_insn_reserv)
8002	DECL_INSN_RESERV (decl)->processed_p = FALSE;
8003    }
8004  for (i = 0; i < description->decls_num; i++)
8005    {
8006      decl = description->decls [i];
8007      if (decl->mode == dm_insn_reserv
8008	  && !DECL_INSN_RESERV (decl)->processed_p)
8009	{
8010	  for (j = i; j < description->decls_num; j++)
8011	    {
8012	      decl2 = description->decls [j];
8013	      if (decl2->mode == dm_insn_reserv
8014		  && (DECL_INSN_RESERV (decl2)->important_automata_list
8015		      == DECL_INSN_RESERV (decl)->important_automata_list))
8016		{
8017		  DECL_INSN_RESERV (decl2)->processed_p = TRUE;
8018		  fprintf (output_file, "    case %d: /* %s */\n",
8019			   DECL_INSN_RESERV (decl2)->insn_num,
8020			   DECL_INSN_RESERV (decl2)->name);
8021		}
8022	    }
8023	  (*output_automata_list_code)
8024	    (DECL_INSN_RESERV (decl)->important_automata_list);
8025	}
8026    }
8027}
8028
8029
8030/* The function outputs a code for evaluation of a minimal delay of
8031   issue of insns which have reservations in given AUTOMATA_LIST.  */
8032static void
8033output_automata_list_min_issue_delay_code (automata_list)
8034     automata_list_el_t automata_list;
8035{
8036  automata_list_el_t el;
8037  automaton_t automaton;
8038
8039  for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8040    {
8041      automaton = el->automaton;
8042      fprintf (output_file, "\n      %s = ", TEMPORARY_VARIABLE_NAME);
8043      output_min_issue_delay_vect_name (output_file, automaton);
8044      fprintf (output_file,
8045	       (automaton->min_issue_delay_table_compression_factor != 1
8046		? " [(" : " ["));
8047      output_translate_vect_name (output_file, automaton);
8048      fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8049      fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8050      output_chip_member_name (output_file, automaton);
8051      fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
8052      if (automaton->min_issue_delay_table_compression_factor == 1)
8053	fprintf (output_file, "];\n");
8054      else
8055	{
8056	  fprintf (output_file, ") / %d];\n",
8057		   automaton->min_issue_delay_table_compression_factor);
8058	  fprintf (output_file, "      %s = (%s >> (8 - (",
8059		   TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8060	  output_translate_vect_name (output_file, automaton);
8061	  fprintf
8062	    (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
8063	     INTERNAL_INSN_CODE_NAME,
8064	     automaton->min_issue_delay_table_compression_factor,
8065	     8 / automaton->min_issue_delay_table_compression_factor,
8066	     (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8067	     - 1);
8068	}
8069      if (el == automata_list)
8070	fprintf (output_file, "      %s = %s;\n",
8071		 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8072      else
8073	{
8074	  fprintf (output_file, "      if (%s > %s)\n",
8075		   TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8076	  fprintf (output_file, "        %s = %s;\n",
8077		   RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8078	}
8079    }
8080  fprintf (output_file, "      break;\n\n");
8081}
8082
8083/* Output function `internal_min_issue_delay'.  */
8084static void
8085output_internal_min_issue_delay_func ()
8086{
8087  fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8088	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
8089  fprintf (output_file,
8090	   "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s  ATTRIBUTE_UNUSED;\n",
8091	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8092	   CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8093	   CHIP_PARAMETER_NAME);
8094  fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n  int %s = -1;\n",
8095	   TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8096  fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8097  output_insn_code_cases (output_automata_list_min_issue_delay_code);
8098  fprintf (output_file,
8099	   "\n    default:\n      %s = -1;\n      break;\n    }\n",
8100	   RESULT_VARIABLE_NAME);
8101  fprintf (output_file, "  return %s;\n", RESULT_VARIABLE_NAME);
8102  fprintf (output_file, "}\n\n");
8103}
8104
8105/* The function outputs a code changing state after issue of insns
8106   which have reservations in given AUTOMATA_LIST.  */
8107static void
8108output_automata_list_transition_code (automata_list)
8109     automata_list_el_t automata_list;
8110{
8111  automata_list_el_t el, next_el;
8112
8113  fprintf (output_file, "      {\n");
8114  if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8115    for (el = automata_list;; el = next_el)
8116      {
8117        next_el = el->next_automata_list_el;
8118        if (next_el == NULL)
8119          break;
8120        fprintf (output_file, "        ");
8121        output_state_member_type (output_file, el->automaton);
8122	fprintf (output_file, " ");
8123        output_temp_chip_member_name (output_file, el->automaton);
8124        fprintf (output_file, ";\n");
8125      }
8126  for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8127    if (comb_vect_p (el->automaton->trans_table))
8128      {
8129	fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);
8130	output_trans_base_vect_name (output_file, el->automaton);
8131	fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8132	output_chip_member_name (output_file, el->automaton);
8133	fprintf (output_file, "] + ");
8134	output_translate_vect_name (output_file, el->automaton);
8135	fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8136	fprintf (output_file, "        if (");
8137	output_trans_check_vect_name (output_file, el->automaton);
8138	fprintf (output_file, " [%s] != %s->",
8139		 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8140	output_chip_member_name (output_file, el->automaton);
8141	fprintf (output_file, ")\n");
8142	fprintf (output_file, "          return %s (%s, %s);\n",
8143		 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8144		 CHIP_PARAMETER_NAME);
8145	fprintf (output_file, "        else\n");
8146	fprintf (output_file, "          ");
8147	if (el->next_automata_list_el != NULL)
8148	  output_temp_chip_member_name (output_file, el->automaton);
8149	else
8150	  {
8151	    fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8152	    output_chip_member_name (output_file, el->automaton);
8153	  }
8154	fprintf (output_file, " = ");
8155	output_trans_comb_vect_name (output_file, el->automaton);
8156	fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8157      }
8158    else
8159      {
8160	fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);
8161	output_trans_full_vect_name (output_file, el->automaton);
8162	fprintf (output_file, " [");
8163	output_translate_vect_name (output_file, el->automaton);
8164	fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8165	fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8166	output_chip_member_name (output_file, el->automaton);
8167	fprintf (output_file, " * %d];\n",
8168		 el->automaton->insn_equiv_classes_num);
8169	fprintf (output_file, "        if (%s >= %d)\n",
8170		 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8171	fprintf (output_file, "          return %s (%s, %s);\n",
8172		 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8173		 CHIP_PARAMETER_NAME);
8174	fprintf (output_file, "        else\n          ");
8175	if (el->next_automata_list_el != NULL)
8176	  output_temp_chip_member_name (output_file, el->automaton);
8177	else
8178	  {
8179	    fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8180	    output_chip_member_name (output_file, el->automaton);
8181	  }
8182	fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8183      }
8184  if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8185    for (el = automata_list;; el = next_el)
8186      {
8187        next_el = el->next_automata_list_el;
8188        if (next_el == NULL)
8189          break;
8190        fprintf (output_file, "        %s->", CHIP_PARAMETER_NAME);
8191        output_chip_member_name (output_file, el->automaton);
8192        fprintf (output_file, " = ");
8193        output_temp_chip_member_name (output_file, el->automaton);
8194        fprintf (output_file, ";\n");
8195      }
8196  fprintf (output_file, "        return -1;\n");
8197  fprintf (output_file, "      }\n");
8198}
8199
8200/* Output function `internal_state_transition'.  */
8201static void
8202output_internal_trans_func ()
8203{
8204  fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8205	   INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
8206  fprintf (output_file,
8207	   "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s  ATTRIBUTE_UNUSED;\n",
8208	   INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8209	   CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
8210	   CHIP_NAME, CHIP_PARAMETER_NAME);
8211  fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8212  fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8213  output_insn_code_cases (output_automata_list_transition_code);
8214  fprintf (output_file, "\n    default:\n      return -1;\n    }\n");
8215  fprintf (output_file, "}\n\n");
8216}
8217
8218/* Output code
8219
8220  if (insn != 0)
8221    {
8222      insn_code = dfa_insn_code (insn);
8223      if (insn_code > DFA__ADVANCE_CYCLE)
8224        return code;
8225    }
8226  else
8227    insn_code = DFA__ADVANCE_CYCLE;
8228
8229  where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8230  code denotes CODE.  */
8231static void
8232output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
8233     const char *insn_name;
8234     const char *insn_code_name;
8235     int code;
8236{
8237  fprintf (output_file, "\n  if (%s != 0)\n    {\n", insn_name);
8238  fprintf (output_file, "      %s = %s (%s);\n", insn_code_name,
8239	   DFA_INSN_CODE_FUNC_NAME, insn_name);
8240  fprintf (output_file, "      if (%s > %s)\n        return %d;\n",
8241	   insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8242  fprintf (output_file, "    }\n  else\n    %s = %s;\n\n",
8243	   insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8244}
8245
8246
8247/* The function outputs function `dfa_insn_code'.  */
8248static void
8249output_dfa_insn_code_func ()
8250{
8251  fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n");
8252  fprintf (output_file, "static int %s PARAMS ((rtx));\n",
8253	   DFA_INSN_CODE_FUNC_NAME);
8254  fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
8255	   DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
8256  fprintf (output_file, "{\n  int %s;\n  int %s;\n\n",
8257	   INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
8258  fprintf (output_file, "  if (INSN_UID (%s) >= %s)\n    {\n",
8259	   INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8260  fprintf (output_file, "      %s = %s;\n      %s = 2 * INSN_UID (%s);\n",
8261	   TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8262	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
8263  fprintf (output_file, "      %s = xrealloc (%s, %s * sizeof (int));\n",
8264	   DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8265	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8266  fprintf (output_file,
8267	   "      for (; %s < %s; %s++)\n        %s [%s] = -1;\n    }\n",
8268	   TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8269	   TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8270	   TEMPORARY_VARIABLE_NAME);
8271  fprintf (output_file, "  if ((%s = %s [INSN_UID (%s)]) < 0)\n    {\n",
8272	   INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8273	   INSN_PARAMETER_NAME);
8274  fprintf (output_file, "      %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8275	   INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8276  fprintf (output_file, "      %s [INSN_UID (%s)] = %s;\n",
8277	   DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME,
8278	   INTERNAL_INSN_CODE_NAME);
8279  fprintf (output_file, "    }\n  return %s;\n}\n\n",
8280	   INTERNAL_INSN_CODE_NAME);
8281}
8282
8283/* The function outputs PHR interface function `state_transition'.  */
8284static void
8285output_trans_func ()
8286{
8287  fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8288	   TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8289	   STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8290  fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
8291  output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8292					INTERNAL_INSN_CODE_NAME, -1);
8293  fprintf (output_file, "  return %s (%s, %s);\n}\n\n",
8294	   INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8295}
8296
8297/* The function outputs a code for evaluation of alternative states
8298   number for insns which have reservations in given AUTOMATA_LIST.  */
8299static void
8300output_automata_list_state_alts_code (automata_list)
8301     automata_list_el_t automata_list;
8302{
8303  automata_list_el_t el;
8304  automaton_t automaton;
8305
8306  fprintf (output_file, "      {\n");
8307  for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8308    if (comb_vect_p (el->automaton->state_alts_table))
8309      {
8310	fprintf (output_file, "        int %s;\n", TEMPORARY_VARIABLE_NAME);
8311	break;
8312      }
8313  for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8314    {
8315      automaton = el->automaton;
8316      if (comb_vect_p (automaton->state_alts_table))
8317	{
8318	  fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);
8319	  output_state_alts_base_vect_name (output_file, automaton);
8320	  fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8321	  output_chip_member_name (output_file, automaton);
8322	  fprintf (output_file, "] + ");
8323	  output_translate_vect_name (output_file, automaton);
8324	  fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8325	  fprintf (output_file, "        if (");
8326	  output_state_alts_check_vect_name (output_file, automaton);
8327	  fprintf (output_file, " [%s] != %s->",
8328		   TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8329	  output_chip_member_name (output_file, automaton);
8330	  fprintf (output_file, ")\n");
8331	  fprintf (output_file, "          return 0;\n");
8332	  fprintf (output_file, "        else\n");
8333	  fprintf (output_file,
8334		   (el == automata_list
8335		    ? "          %s = " : "          %s += "),
8336		   RESULT_VARIABLE_NAME);
8337	  output_state_alts_comb_vect_name (output_file, automaton);
8338	  fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8339	}
8340      else
8341	{
8342	  fprintf (output_file,
8343		   (el == automata_list
8344		    ? "\n        %s = " : "        %s += "),
8345		   RESULT_VARIABLE_NAME);
8346	  output_state_alts_full_vect_name (output_file, automaton);
8347	  fprintf (output_file, " [");
8348	  output_translate_vect_name (output_file, automaton);
8349	  fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8350	  fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8351	  output_chip_member_name (output_file, automaton);
8352	  fprintf (output_file, " * %d];\n",
8353		   automaton->insn_equiv_classes_num);
8354	}
8355    }
8356  fprintf (output_file, "        break;\n      }\n\n");
8357}
8358
8359/* Output function `internal_state_alts'.  */
8360static void
8361output_internal_state_alts_func ()
8362{
8363  fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8364	   INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8365  fprintf (output_file,
8366	   "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8367	   INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8368	   CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8369	   CHIP_PARAMETER_NAME);
8370  fprintf (output_file, "{\n  int %s;\n", RESULT_VARIABLE_NAME);
8371  fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8372  output_insn_code_cases (output_automata_list_state_alts_code);
8373  fprintf (output_file,
8374	   "\n    default:\n      %s = 0;\n      break;\n    }\n",
8375	   RESULT_VARIABLE_NAME);
8376  fprintf (output_file, "  return %s;\n", RESULT_VARIABLE_NAME);
8377  fprintf (output_file, "}\n\n");
8378}
8379
8380/* The function outputs PHR interface function `state_alts'.  */
8381static void
8382output_state_alts_func ()
8383{
8384  fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8385	   STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8386	   STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8387  fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
8388  output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8389					INTERNAL_INSN_CODE_NAME, 0);
8390  fprintf (output_file, "  return %s (%s, %s);\n}\n\n",
8391	   INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8392}
8393
8394/* Output function `min_issue_delay'.  */
8395static void
8396output_min_issue_delay_func ()
8397{
8398  fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8399	   MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8400	   STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8401  fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
8402  fprintf (output_file, "\n  if (%s != 0)\n    {\n", INSN_PARAMETER_NAME);
8403  fprintf (output_file, "      %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8404	   DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8405  fprintf (output_file, "      if (%s > %s)\n        return 0;\n",
8406	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8407  fprintf (output_file, "    }\n  else\n    %s = %s;\n",
8408	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8409  fprintf (output_file, "\n  return %s (%s, %s);\n",
8410 	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8411	   STATE_NAME);
8412  fprintf (output_file, "}\n\n");
8413}
8414
8415/* Output function `internal_dead_lock'.  */
8416static void
8417output_internal_dead_lock_func ()
8418{
8419  automaton_t automaton;
8420
8421  fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8422	   INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8423  fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8424	   INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8425	   CHIP_PARAMETER_NAME);
8426  fprintf (output_file, "{\n");
8427  for (automaton = description->first_automaton;
8428       automaton != NULL;
8429       automaton = automaton->next_automaton)
8430    {
8431      fprintf (output_file, "  if (");
8432      output_dead_lock_vect_name (output_file, automaton);
8433      fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8434      output_chip_member_name (output_file, automaton);
8435      fprintf (output_file, "])\n    return 1/* TRUE */;\n");
8436    }
8437  fprintf (output_file, "  return 0/* FALSE */;\n}\n\n");
8438}
8439
8440/* The function outputs PHR interface function `state_dead_lock_p'.  */
8441static void
8442output_dead_lock_func ()
8443{
8444  fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8445	   DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8446  fprintf (output_file, "{\n  return %s (%s);\n}\n\n",
8447	   INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8448}
8449
8450/* Output function `internal_reset'.  */
8451static void
8452output_internal_reset_func ()
8453{
8454  fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8455	   INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8456  fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8457	   INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8458	   CHIP_NAME, CHIP_PARAMETER_NAME);
8459  fprintf (output_file, "{\n  memset (%s, 0, sizeof (struct %s));\n}\n\n",
8460	   CHIP_PARAMETER_NAME, CHIP_NAME);
8461}
8462
8463/* The function outputs PHR interface function `state_size'.  */
8464static void
8465output_size_func ()
8466{
8467  fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8468  fprintf (output_file, "{\n  return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8469}
8470
8471/* The function outputs PHR interface function `state_reset'.  */
8472static void
8473output_reset_func ()
8474{
8475  fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8476	   RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8477  fprintf (output_file, "{\n  %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8478	   STATE_NAME);
8479}
8480
8481/* Output function `min_insn_conflict_delay'.  */
8482static void
8483output_min_insn_conflict_delay_func ()
8484{
8485  fprintf (output_file,
8486	   "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8487	   MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8488	   STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8489 	   STATE_TYPE_NAME, STATE_NAME,
8490	   INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8491  fprintf (output_file, "{\n  struct %s %s;\n  int %s, %s;\n",
8492	   CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8493	   INTERNAL_INSN2_CODE_NAME);
8494  output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8495					INTERNAL_INSN_CODE_NAME, 0);
8496  output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8497					INTERNAL_INSN2_CODE_NAME, 0);
8498  fprintf (output_file, "  memcpy (&%s, %s, sizeof (%s));\n",
8499	   CHIP_NAME, STATE_NAME, CHIP_NAME);
8500  fprintf (output_file, "  %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8501  fprintf (output_file, "  if (%s (%s, &%s) > 0)\n    abort ();\n",
8502	   INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8503  fprintf (output_file, "  return %s (%s, &%s);\n",
8504	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8505	   CHIP_NAME);
8506  fprintf (output_file, "}\n\n");
8507}
8508
8509/* Output function `internal_insn_latency'.  */
8510static void
8511output_internal_insn_latency_func ()
8512{
8513  decl_t decl;
8514  struct bypass_decl *bypass;
8515  int i;
8516
8517  fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8518	   INTERNAL_INSN_LATENCY_FUNC_NAME);
8519  fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8520	   INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8521	   INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8522	   INSN2_PARAMETER_NAME);
8523  fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
8524	   INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8525  fprintf (output_file,
8526	   "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
8527	   INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8528  fprintf (output_file, "{\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8529  for (i = 0; i < description->decls_num; i++)
8530    {
8531      decl = description->decls [i];
8532      if (decl->mode == dm_insn_reserv)
8533	{
8534	  fprintf (output_file, "    case %d:\n",
8535		   DECL_INSN_RESERV (decl)->insn_num);
8536	  if (DECL_INSN_RESERV (decl)->bypass_list == NULL)
8537	    fprintf (output_file, "      return (%s != %s ? %d : 0);\n",
8538		     INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8539		     DECL_INSN_RESERV (decl)->default_latency);
8540	  else
8541	    {
8542	      fprintf (output_file, "      switch (%s)\n        {\n",
8543		       INTERNAL_INSN2_CODE_NAME);
8544	      for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8545		   bypass != NULL;
8546		   bypass = bypass->next)
8547		{
8548		  fprintf (output_file, "        case %d:\n",
8549			   bypass->in_insn_reserv->insn_num);
8550		  if (bypass->bypass_guard_name == NULL)
8551		    fprintf (output_file, "          return %d;\n",
8552			     bypass->latency);
8553		  else
8554		    fprintf (output_file,
8555			     "          return (%s (%s, %s) ? %d : %d);\n",
8556			     bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8557			     INSN2_PARAMETER_NAME, bypass->latency,
8558			     DECL_INSN_RESERV (decl)->default_latency);
8559		}
8560	      fprintf (output_file, "        default:\n");
8561	      fprintf (output_file,
8562		       "          return (%s != %s ? %d : 0);\n        }\n",
8563		       INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8564		       DECL_INSN_RESERV (decl)->default_latency);
8565
8566	    }
8567	}
8568    }
8569  fprintf (output_file, "    default:\n      return 0;\n    }\n}\n\n");
8570}
8571
8572/* The function outputs PHR interface function `insn_latency'.  */
8573static void
8574output_insn_latency_func ()
8575{
8576  fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
8577	   INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8578	   INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8579  fprintf (output_file, "{\n  int %s, %s;\n",
8580	   INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8581  output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8582					INTERNAL_INSN_CODE_NAME, 0);
8583  output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8584					INTERNAL_INSN2_CODE_NAME, 0);
8585  fprintf (output_file, "  return %s (%s, %s, %s, %s);\n}\n\n",
8586	   INTERNAL_INSN_LATENCY_FUNC_NAME,
8587	   INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8588	   INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8589}
8590
8591/* The function outputs PHR interface function `print_reservation'.  */
8592static void
8593output_print_reservation_func ()
8594{
8595  decl_t decl;
8596  int i;
8597
8598  fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
8599           PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8600           INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
8601           INSN_PARAMETER_NAME);
8602  fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
8603  fprintf (output_file, "\n  if (%s != 0)\n    {\n", INSN_PARAMETER_NAME);
8604  fprintf (output_file, "      %s = %s (%s);\n",
8605	   INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8606	   INSN_PARAMETER_NAME);
8607  fprintf (output_file, "      if (%s > %s)\n",
8608	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8609  fprintf (output_file, "        {\n          fprintf (%s, \"%s\");\n",
8610           FILE_PARAMETER_NAME, NOTHING_NAME);
8611  fprintf (output_file, "          return;\n        }\n");
8612  fprintf (output_file, "    }\n  else\n");
8613  fprintf (output_file,
8614           "    {\n      fprintf (%s, \"%s\");\n      return;\n    }\n",
8615           FILE_PARAMETER_NAME, NOTHING_NAME);
8616  fprintf (output_file, "  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8617  for (i = 0; i < description->decls_num; i++)
8618    {
8619      decl = description->decls [i];
8620      if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8621	{
8622          fprintf (output_file,
8623                   "    case %d:\n", DECL_INSN_RESERV (decl)->insn_num);
8624          fprintf (output_file,
8625                   "      fprintf (%s, \"%s\");\n      break;\n",
8626                   FILE_PARAMETER_NAME,
8627                   regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8628          finish_regexp_representation ();
8629        }
8630    }
8631  fprintf (output_file, "    default:\n      fprintf (%s, \"%s\");\n    }\n",
8632           FILE_PARAMETER_NAME, NOTHING_NAME);
8633  fprintf (output_file, "}\n\n");
8634}
8635
8636/* The following function is used to sort unit declaration by their
8637   names.  */
8638static int
8639units_cmp (unit1, unit2)
8640     const void *unit1, *unit2;
8641{
8642  const unit_decl_t u1 = *(unit_decl_t *) unit1;
8643  const unit_decl_t u2 = *(unit_decl_t *) unit2;
8644
8645  return strcmp (u1->name, u2->name);
8646}
8647
8648/* The following macro value is name of struct containing unit name
8649   and unit code.  */
8650#define NAME_CODE_STRUCT_NAME  "name_code"
8651
8652/* The following macro value is name of table of struct name_code.  */
8653#define NAME_CODE_TABLE_NAME   "name_code_table"
8654
8655/* The following macro values are member names for struct name_code.  */
8656#define NAME_MEMBER_NAME       "name"
8657#define CODE_MEMBER_NAME       "code"
8658
8659/* The following macro values are local variable names for function
8660   `get_cpu_unit_code'.  */
8661#define CMP_VARIABLE_NAME      "cmp"
8662#define LOW_VARIABLE_NAME      "l"
8663#define MIDDLE_VARIABLE_NAME   "m"
8664#define HIGH_VARIABLE_NAME     "h"
8665
8666/* The following function outputs function to obtain internal cpu unit
8667   code by the cpu unit name.  */
8668static void
8669output_get_cpu_unit_code_func ()
8670{
8671  int i;
8672  unit_decl_t *units;
8673
8674  fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8675	   GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8676	   CPU_UNIT_NAME_PARAMETER_NAME);
8677  fprintf (output_file, "{\n  struct %s {const char *%s; int %s;};\n",
8678	   NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8679  fprintf (output_file, "  int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8680	   LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8681  fprintf (output_file, "  static struct %s %s [] =\n    {\n",
8682	   NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8683  units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
8684				   * description->units_num);
8685  memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8686  qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8687  for (i = 0; i < description->units_num; i++)
8688    if (units [i]->query_p)
8689      fprintf (output_file, "      {\"%s\", %d},\n",
8690	       units[i]->name, units[i]->query_num);
8691  fprintf (output_file, "    };\n\n");
8692  fprintf (output_file, "  /* The following is binary search: */\n");
8693  fprintf (output_file, "  %s = 0;\n", LOW_VARIABLE_NAME);
8694  fprintf (output_file, "  %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8695	   HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8696  fprintf (output_file, "  while (%s <= %s)\n    {\n",
8697	   LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8698  fprintf (output_file, "      %s = (%s + %s) / 2;\n",
8699	   MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8700  fprintf (output_file, "      %s = strcmp (%s, %s [%s].%s);\n",
8701	   CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8702	   NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8703  fprintf (output_file, "      if (%s < 0)\n", CMP_VARIABLE_NAME);
8704  fprintf (output_file, "        %s = %s - 1;\n",
8705	   HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8706  fprintf (output_file, "      else if (%s > 0)\n", CMP_VARIABLE_NAME);
8707  fprintf (output_file, "        %s = %s + 1;\n",
8708	   LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8709  fprintf (output_file, "      else\n");
8710  fprintf (output_file, "        return %s [%s].%s;\n    }\n",
8711	   NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8712  fprintf (output_file, "  return -1;\n}\n\n");
8713  free (units);
8714}
8715
8716/* The following function outputs function to check reservation of cpu
8717   unit (its internal code will be passed as the function argument) in
8718   given cpu state.  */
8719static void
8720output_cpu_unit_reservation_p ()
8721{
8722  automaton_t automaton;
8723
8724  fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8725	   CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8726	   CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8727	   CPU_CODE_PARAMETER_NAME);
8728  fprintf (output_file, "{\n  if (%s < 0 || %s >= %d)\n    abort ();\n",
8729	   CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8730	   description->query_units_num);
8731  for (automaton = description->first_automaton;
8732       automaton != NULL;
8733       automaton = automaton->next_automaton)
8734    {
8735      fprintf (output_file, "  if ((");
8736      output_reserved_units_table_name (output_file, automaton);
8737      fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8738      output_chip_member_name (output_file, automaton);
8739      fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8740	       (description->query_units_num + 7) / 8,
8741	       CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8742      fprintf (output_file, "    return 1;\n");
8743    }
8744  fprintf (output_file, "  return 0;\n}\n\n");
8745}
8746
8747/* The function outputs PHR interface function `dfa_start'.  */
8748static void
8749output_dfa_start_func ()
8750{
8751  fprintf (output_file,
8752	   "void\n%s ()\n{\n  int %s;\n\n  %s = get_max_uid ();\n",
8753	   DFA_START_FUNC_NAME, I_VARIABLE_NAME,
8754	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8755  fprintf (output_file, "  %s = (int *) xmalloc (%s * sizeof (int));\n",
8756	   DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8757  fprintf (output_file,
8758	   "  for (%s = 0; %s < %s; %s++)\n    %s [%s] = -1;\n}\n\n",
8759	   I_VARIABLE_NAME, I_VARIABLE_NAME,
8760	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8761	   DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8762}
8763
8764/* The function outputs PHR interface function `dfa_finish'.  */
8765static void
8766output_dfa_finish_func ()
8767{
8768  fprintf (output_file, "void\n%s ()\n{\n  free (%s);\n}\n\n",
8769	   DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8770}
8771
8772
8773
8774/* The page contains code for output description file (readable
8775   representation of original description and generated DFA(s).  */
8776
8777/* The function outputs string representation of IR reservation.  */
8778static void
8779output_regexp (regexp)
8780     regexp_t regexp;
8781{
8782  fprintf (output_description_file, "%s", regexp_representation (regexp));
8783  finish_regexp_representation ();
8784}
8785
8786/* Output names of units in LIST separated by comma.  */
8787static void
8788output_unit_set_el_list (list)
8789     unit_set_el_t list;
8790{
8791  unit_set_el_t el;
8792
8793  for (el = list; el != NULL; el = el->next_unit_set_el)
8794    {
8795      if (el != list)
8796	fprintf (output_description_file, ",");
8797      fprintf (output_description_file, "%s", el->unit_decl->name);
8798    }
8799}
8800
8801/* The function outputs string representation of IR define_reservation
8802   and define_insn_reservation.  */
8803static void
8804output_description ()
8805{
8806  decl_t decl;
8807  int i;
8808
8809  for (i = 0; i < description->decls_num; i++)
8810    {
8811      decl = description->decls [i];
8812      if (decl->mode == dm_unit)
8813	{
8814	  if (DECL_UNIT (decl)->excl_list != NULL)
8815	    {
8816	      fprintf (output_description_file, "unit %s exlusion_set: ",
8817		       DECL_UNIT (decl)->name);
8818	      output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8819	      fprintf (output_description_file, "\n");
8820	    }
8821	  if (DECL_UNIT (decl)->presence_list != NULL)
8822	    {
8823	      fprintf (output_description_file, "unit %s presence_set: ",
8824		       DECL_UNIT (decl)->name);
8825	      output_unit_set_el_list (DECL_UNIT (decl)->presence_list);
8826	      fprintf (output_description_file, "\n");
8827	    }
8828	  if (DECL_UNIT (decl)->absence_list != NULL)
8829	    {
8830	      fprintf (output_description_file, "unit %s absence_set: ",
8831		       DECL_UNIT (decl)->name);
8832	      output_unit_set_el_list (DECL_UNIT (decl)->absence_list);
8833	      fprintf (output_description_file, "\n");
8834	    }
8835	}
8836    }
8837  fprintf (output_description_file, "\n");
8838  for (i = 0; i < description->decls_num; i++)
8839    {
8840      decl = description->decls [i];
8841      if (decl->mode == dm_reserv)
8842	{
8843          fprintf (output_description_file, "reservation ");
8844          fprintf (output_description_file, DECL_RESERV (decl)->name);
8845          fprintf (output_description_file, ": ");
8846          output_regexp (DECL_RESERV (decl)->regexp);
8847          fprintf (output_description_file, "\n");
8848        }
8849      else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8850        {
8851          fprintf (output_description_file, "insn reservation %s ",
8852		   DECL_INSN_RESERV (decl)->name);
8853          print_rtl (output_description_file,
8854		     DECL_INSN_RESERV (decl)->condexp);
8855          fprintf (output_description_file, ": ");
8856          output_regexp (DECL_INSN_RESERV (decl)->regexp);
8857          fprintf (output_description_file, "\n");
8858        }
8859      else if (decl->mode == dm_bypass)
8860	fprintf (output_description_file, "bypass %d %s %s\n",
8861		 DECL_BYPASS (decl)->latency,
8862		 DECL_BYPASS (decl)->out_insn_name,
8863		 DECL_BYPASS (decl)->in_insn_name);
8864    }
8865  fprintf (output_description_file, "\n\f\n");
8866}
8867
8868/* The function outputs name of AUTOMATON.  */
8869static void
8870output_automaton_name (f, automaton)
8871     FILE *f;
8872     automaton_t automaton;
8873{
8874  if (automaton->corresponding_automaton_decl == NULL)
8875    fprintf (f, "#%d", automaton->automaton_order_num);
8876  else
8877    fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8878}
8879
8880/* Maximal length of line for pretty printing into description
8881   file.  */
8882#define MAX_LINE_LENGTH 70
8883
8884/* The function outputs units name belonging to AUTOMATON.  */
8885static void
8886output_automaton_units (automaton)
8887     automaton_t automaton;
8888{
8889  decl_t decl;
8890  char *name;
8891  int curr_line_length;
8892  int there_is_an_automaton_unit;
8893  int i;
8894
8895  fprintf (output_description_file, "\n  Coresponding units:\n");
8896  fprintf (output_description_file, "    ");
8897  curr_line_length = 4;
8898  there_is_an_automaton_unit = 0;
8899  for (i = 0; i < description->decls_num; i++)
8900    {
8901      decl = description->decls [i];
8902      if (decl->mode == dm_unit
8903          && (DECL_UNIT (decl)->corresponding_automaton_num
8904	      == automaton->automaton_order_num))
8905	{
8906	  there_is_an_automaton_unit = 1;
8907	  name = DECL_UNIT (decl)->name;
8908	  if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8909	    {
8910	      curr_line_length = strlen (name) + 4;
8911	      fprintf (output_description_file, "\n    ");
8912	    }
8913	  else
8914	    {
8915	      curr_line_length += strlen (name) + 1;
8916	      fprintf (output_description_file, " ");
8917	    }
8918	  fprintf (output_description_file, name);
8919	}
8920    }
8921  if (!there_is_an_automaton_unit)
8922    fprintf (output_description_file, "<None>");
8923  fprintf (output_description_file, "\n\n");
8924}
8925
8926/* The following variable is used for forming array of all possible cpu unit
8927   reservations described by the current DFA state.  */
8928static vla_ptr_t state_reservs;
8929
8930/* The function forms `state_reservs' for STATE.  */
8931static void
8932add_state_reservs (state)
8933     state_t state;
8934{
8935  alt_state_t curr_alt_state;
8936  reserv_sets_t reservs;
8937
8938  if (state->component_states != NULL)
8939    for (curr_alt_state = state->component_states;
8940         curr_alt_state != NULL;
8941         curr_alt_state = curr_alt_state->next_sorted_alt_state)
8942      add_state_reservs (curr_alt_state->state);
8943  else
8944    {
8945      reservs = state->reservs;
8946      VLA_PTR_ADD (state_reservs, reservs);
8947    }
8948}
8949
8950/* The function outputs readable represenatation of all out arcs of
8951   STATE.  */
8952static void
8953output_state_arcs (state)
8954     state_t state;
8955{
8956  arc_t arc;
8957  ainsn_t ainsn;
8958  char *insn_name;
8959  int curr_line_length;
8960
8961  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8962    {
8963      ainsn = arc->insn;
8964      if (!ainsn->first_insn_with_same_reservs)
8965	abort ();
8966      fprintf (output_description_file, "    ");
8967      curr_line_length = 7;
8968      fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8969      do
8970        {
8971          insn_name = ainsn->insn_reserv_decl->name;
8972          if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8973            {
8974              if (ainsn != arc->insn)
8975                {
8976                  fprintf (output_description_file, ",\n      ");
8977                  curr_line_length = strlen (insn_name) + 6;
8978                }
8979              else
8980                curr_line_length += strlen (insn_name);
8981            }
8982          else
8983            {
8984              curr_line_length += strlen (insn_name);
8985              if (ainsn != arc->insn)
8986                {
8987                  curr_line_length += 2;
8988                  fprintf (output_description_file, ", ");
8989                }
8990            }
8991          fprintf (output_description_file, insn_name);
8992          ainsn = ainsn->next_same_reservs_insn;
8993        }
8994      while (ainsn != NULL);
8995      fprintf (output_description_file, "    %d (%d)\n",
8996	       arc->to_state->order_state_num, arc->state_alts);
8997    }
8998  fprintf (output_description_file, "\n");
8999}
9000
9001/* The following function is used for sorting possible cpu unit
9002   reservation of a DFA state.  */
9003static int
9004state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
9005     const void *reservs_ptr_1;
9006     const void *reservs_ptr_2;
9007{
9008  return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
9009                          *(reserv_sets_t *) reservs_ptr_2);
9010}
9011
9012/* The following function is used for sorting possible cpu unit
9013   reservation of a DFA state.  */
9014static void
9015remove_state_duplicate_reservs ()
9016{
9017  reserv_sets_t *reservs_ptr;
9018  reserv_sets_t *last_formed_reservs_ptr;
9019
9020  last_formed_reservs_ptr = NULL;
9021  for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9022       reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9023       reservs_ptr++)
9024    if (last_formed_reservs_ptr == NULL)
9025      last_formed_reservs_ptr = reservs_ptr;
9026    else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
9027      {
9028        ++last_formed_reservs_ptr;
9029        *last_formed_reservs_ptr = *reservs_ptr;
9030      }
9031  VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
9032}
9033
9034/* The following function output readable representation of DFA(s)
9035   state used for fast recognition of pipeline hazards.  State is
9036   described by possible (current and scehduled) cpu unit
9037   reservations.  */
9038static void
9039output_state (state)
9040     state_t state;
9041{
9042  reserv_sets_t *reservs_ptr;
9043
9044  VLA_PTR_CREATE (state_reservs, 150, "state reservations");
9045  fprintf (output_description_file, "  State #%d", state->order_state_num);
9046  fprintf (output_description_file,
9047	   state->new_cycle_p ? " (new cycle)\n" : "\n");
9048  add_state_reservs (state);
9049  qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
9050         sizeof (reserv_sets_t), state_reservs_cmp);
9051  remove_state_duplicate_reservs ();
9052  for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
9053       reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
9054       reservs_ptr++)
9055    {
9056      fprintf (output_description_file, "    ");
9057      output_reserv_sets (output_description_file, *reservs_ptr);
9058      fprintf (output_description_file, "\n");
9059    }
9060  fprintf (output_description_file, "\n");
9061  output_state_arcs (state);
9062  VLA_PTR_DELETE (state_reservs);
9063}
9064
9065/* The following function output readable representation of
9066   DFAs used for fast recognition of pipeline hazards.  */
9067static void
9068output_automaton_descriptions ()
9069{
9070  automaton_t automaton;
9071
9072  for (automaton = description->first_automaton;
9073       automaton != NULL;
9074       automaton = automaton->next_automaton)
9075    {
9076      fprintf (output_description_file, "\nAutomaton ");
9077      output_automaton_name (output_description_file, automaton);
9078      fprintf (output_description_file, "\n");
9079      output_automaton_units (automaton);
9080      pass_states (automaton, output_state);
9081    }
9082}
9083
9084
9085
9086/* The page contains top level function for generation DFA(s) used for
9087   PHR.  */
9088
9089/* The function outputs statistics about work of different phases of
9090   DFA generator.  */
9091static void
9092output_statistics (f)
9093     FILE *f;
9094{
9095  automaton_t automaton;
9096#ifndef NDEBUG
9097  int transition_comb_vect_els = 0;
9098  int transition_full_vect_els = 0;
9099  int state_alts_comb_vect_els = 0;
9100  int state_alts_full_vect_els = 0;
9101  int min_issue_delay_vect_els = 0;
9102#endif
9103
9104  for (automaton = description->first_automaton;
9105       automaton != NULL;
9106       automaton = automaton->next_automaton)
9107    {
9108      fprintf (f, "\nAutomaton ");
9109      output_automaton_name (f, automaton);
9110      fprintf (f, "\n    %5d NDFA states,          %5d NDFA arcs\n",
9111	       automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9112      fprintf (f, "    %5d DFA states,           %5d DFA arcs\n",
9113	       automaton->DFA_states_num, automaton->DFA_arcs_num);
9114      if (!no_minimization_flag)
9115	fprintf (f, "    %5d minimal DFA states,   %5d minimal DFA arcs\n",
9116		 automaton->minimal_DFA_states_num,
9117		 automaton->minimal_DFA_arcs_num);
9118      fprintf (f, "    %5d all insns      %5d insn equivalence classes\n",
9119	       description->insns_num, automaton->insn_equiv_classes_num);
9120#ifndef NDEBUG
9121      fprintf
9122	(f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9123	 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
9124	 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
9125	 (comb_vect_p (automaton->trans_table)
9126	  ? "use comb vect" : "use simple vect"));
9127      fprintf
9128        (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
9129         (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
9130         (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
9131         (comb_vect_p (automaton->state_alts_table)
9132          ? "use comb vect" : "use simple vect"));
9133      fprintf
9134        (f, "%5ld min delay table els, compression factor %d\n",
9135         (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num,
9136	 automaton->min_issue_delay_table_compression_factor);
9137      transition_comb_vect_els
9138	+= VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
9139      transition_full_vect_els
9140        += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
9141      state_alts_comb_vect_els
9142        += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
9143      state_alts_full_vect_els
9144        += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
9145      min_issue_delay_vect_els
9146        += automaton->DFA_states_num * automaton->insn_equiv_classes_num;
9147#endif
9148    }
9149#ifndef NDEBUG
9150  fprintf (f, "\n%5d all allocated states,     %5d all allocated arcs\n",
9151	   allocated_states_num, allocated_arcs_num);
9152  fprintf (f, "%5d all allocated alternative states\n",
9153	   allocated_alt_states_num);
9154  fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9155	   transition_comb_vect_els, transition_full_vect_els);
9156  fprintf
9157    (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
9158     state_alts_comb_vect_els, state_alts_full_vect_els);
9159  fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9160  fprintf (f, "%5d locked states num\n", locked_states_num);
9161#endif
9162}
9163
9164/* The function output times of work of different phases of DFA
9165   generator.  */
9166static void
9167output_time_statistics (f)
9168     FILE *f;
9169{
9170  fprintf (f, "\n  transformation: ");
9171  print_active_time (f, transform_time);
9172  fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9173  print_active_time (f, NDFA_time);
9174  if (ndfa_flag)
9175    {
9176      fprintf (f, ", NDFA -> DFA: ");
9177      print_active_time (f, NDFA_to_DFA_time);
9178    }
9179  fprintf (f, "\n  DFA minimization: ");
9180  print_active_time (f, minimize_time);
9181  fprintf (f, ", making insn equivalence: ");
9182  print_active_time (f, equiv_time);
9183  fprintf (f, "\n all automaton generation: ");
9184  print_active_time (f, automaton_generation_time);
9185  fprintf (f, ", output: ");
9186  print_active_time (f, output_time);
9187  fprintf (f, "\n");
9188}
9189
9190/* The function generates DFA (deterministic finate state automaton)
9191   for fast recognition of pipeline hazards.  No errors during
9192   checking must be fixed before this function call.  */
9193static void
9194generate ()
9195{
9196  automata_num = split_argument;
9197  if (description->units_num < automata_num)
9198    automata_num = description->units_num;
9199  initiate_states ();
9200  initiate_arcs ();
9201  initiate_automata_lists ();
9202  initiate_pass_states ();
9203  initiate_excl_sets ();
9204  initiate_presence_absence_sets ();
9205  automaton_generation_time = create_ticker ();
9206  create_automata ();
9207  ticker_off (&automaton_generation_time);
9208}
9209
9210
9211
9212/* The following function creates insn attribute whose values are
9213   number alternatives in insn reservations.  */
9214static void
9215make_insn_alts_attr ()
9216{
9217  int i, insn_num;
9218  decl_t decl;
9219  rtx condexp;
9220
9221  condexp = rtx_alloc (COND);
9222  XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9223  XEXP (condexp, 1) = make_numeric_value (0);
9224  for (i = insn_num = 0; i < description->decls_num; i++)
9225    {
9226      decl = description->decls [i];
9227      if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9228	{
9229          XVECEXP (condexp, 0, 2 * insn_num)
9230	    = DECL_INSN_RESERV (decl)->condexp;
9231          XVECEXP (condexp, 0, 2 * insn_num + 1)
9232            = make_numeric_value
9233	      (DECL_INSN_RESERV (decl)->transformed_regexp->mode != rm_oneof
9234	       ? 1 : REGEXP_ONEOF (DECL_INSN_RESERV (decl)
9235				   ->transformed_regexp)->regexps_num);
9236          insn_num++;
9237        }
9238    }
9239  if (description->insns_num != insn_num + 1)
9240    abort ();
9241  make_internal_attr (attr_printf (sizeof ("*")
9242				   + strlen (INSN_ALTS_FUNC_NAME) + 1,
9243				   "*%s", INSN_ALTS_FUNC_NAME),
9244		      condexp, 0);
9245}
9246
9247
9248
9249/* The following function creates attribute which is order number of
9250   insn in pipeline hazard description translator.  */
9251static void
9252make_internal_dfa_insn_code_attr ()
9253{
9254  int i, insn_num;
9255  decl_t decl;
9256  rtx condexp;
9257
9258  condexp = rtx_alloc (COND);
9259  XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9260  XEXP (condexp, 1)
9261    = make_numeric_value (DECL_INSN_RESERV (advance_cycle_insn_decl)
9262			  ->insn_num + 1);
9263  for (i = insn_num = 0; i < description->decls_num; i++)
9264    {
9265      decl = description->decls [i];
9266      if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9267	{
9268          XVECEXP (condexp, 0, 2 * insn_num)
9269	    = DECL_INSN_RESERV (decl)->condexp;
9270          XVECEXP (condexp, 0, 2 * insn_num + 1)
9271            = make_numeric_value (DECL_INSN_RESERV (decl)->insn_num);
9272          insn_num++;
9273        }
9274    }
9275  if (description->insns_num != insn_num + 1)
9276    abort ();
9277  make_internal_attr
9278    (attr_printf (sizeof ("*")
9279		  + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9280		  "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9281     condexp, 0);
9282}
9283
9284
9285
9286/* The following function creates attribute which order number of insn
9287   in pipeline hazard description translator.  */
9288static void
9289make_default_insn_latency_attr ()
9290{
9291  int i, insn_num;
9292  decl_t decl;
9293  rtx condexp;
9294
9295  condexp = rtx_alloc (COND);
9296  XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9297  XEXP (condexp, 1) = make_numeric_value (0);
9298  for (i = insn_num = 0; i < description->decls_num; i++)
9299    {
9300      decl = description->decls [i];
9301      if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9302	{
9303          XVECEXP (condexp, 0, 2 * insn_num)
9304	    = DECL_INSN_RESERV (decl)->condexp;
9305          XVECEXP (condexp, 0, 2 * insn_num + 1)
9306            = make_numeric_value (DECL_INSN_RESERV (decl)->default_latency);
9307          insn_num++;
9308        }
9309    }
9310  if (description->insns_num != insn_num + 1)
9311    abort ();
9312  make_internal_attr (attr_printf (sizeof ("*")
9313				   + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9314				   + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9315		      condexp, 0);
9316}
9317
9318
9319
9320/* The following function creates attribute which returns 1 if given
9321   output insn has bypassing and 0 otherwise.  */
9322static void
9323make_bypass_attr ()
9324{
9325  int i, bypass_insn;
9326  int bypass_insns_num = 0;
9327  decl_t decl;
9328  rtx result_rtx;
9329
9330  for (i = 0; i < description->decls_num; i++)
9331    {
9332      decl = description->decls [i];
9333      if (decl->mode == dm_insn_reserv
9334	  && DECL_INSN_RESERV (decl)->condexp != NULL
9335	  && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9336	bypass_insns_num++;
9337    }
9338  if (bypass_insns_num == 0)
9339    result_rtx = make_numeric_value (0);
9340  else
9341    {
9342      result_rtx = rtx_alloc (COND);
9343      XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9344      XEXP (result_rtx, 1) = make_numeric_value (0);
9345
9346      for (i = bypass_insn = 0; i < description->decls_num; i++)
9347        {
9348          decl = description->decls [i];
9349          if (decl->mode == dm_insn_reserv
9350	      && DECL_INSN_RESERV (decl)->condexp != NULL
9351	      && DECL_INSN_RESERV (decl)->bypass_list != NULL)
9352	    {
9353              XVECEXP (result_rtx, 0, 2 * bypass_insn)
9354		= DECL_INSN_RESERV (decl)->condexp;
9355              XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9356	        = make_numeric_value (1);
9357              bypass_insn++;
9358            }
9359        }
9360    }
9361  make_internal_attr (attr_printf (sizeof ("*")
9362				   + strlen (BYPASS_P_FUNC_NAME) + 1,
9363				   "*%s", BYPASS_P_FUNC_NAME),
9364		      result_rtx, 0);
9365}
9366
9367
9368
9369/* This page mainly contains top level functions of pipeline hazards
9370   description translator.  */
9371
9372/* The following macro value is suffix of name of description file of
9373   pipeline hazards description translator.  */
9374#define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9375
9376/* The function returns suffix of given file name.  The returned
9377   string can not be changed.  */
9378static const char *
9379file_name_suffix (file_name)
9380     const char *file_name;
9381{
9382  const char *last_period;
9383
9384  for (last_period = NULL; *file_name != '\0'; file_name++)
9385    if (*file_name == '.')
9386      last_period = file_name;
9387  return (last_period == NULL ? file_name : last_period);
9388}
9389
9390/* The function returns base name of given file name, i.e. pointer to
9391   first char after last `/' (or `\' for WIN32) in given file name,
9392   given file name itself if the directory name is absent.  The
9393   returned string can not be changed.  */
9394static const char *
9395base_file_name (file_name)
9396     const char *file_name;
9397{
9398  int directory_name_length;
9399
9400  directory_name_length = strlen (file_name);
9401#ifdef WIN32
9402  while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9403         && file_name[directory_name_length] != '\\')
9404#else
9405  while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9406#endif
9407    directory_name_length--;
9408  return file_name + directory_name_length + 1;
9409}
9410
9411/* The following is top level function to initialize the work of
9412   pipeline hazards description translator.  */
9413void
9414initiate_automaton_gen (argc, argv)
9415     int argc;
9416     char **argv;
9417{
9418  const char *base_name;
9419  int i;
9420
9421  ndfa_flag = 0;
9422  split_argument = 0;  /* default value */
9423  no_minimization_flag = 0;
9424  time_flag = 0;
9425  v_flag = 0;
9426  w_flag = 0;
9427  for (i = 2; i < argc; i++)
9428    if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9429      no_minimization_flag = 1;
9430    else if (strcmp (argv [i], TIME_OPTION) == 0)
9431      time_flag = 1;
9432    else if (strcmp (argv [i], V_OPTION) == 0)
9433      v_flag = 1;
9434    else if (strcmp (argv [i], W_OPTION) == 0)
9435      w_flag = 1;
9436    else if (strcmp (argv [i], NDFA_OPTION) == 0)
9437      ndfa_flag = 1;
9438    else if (strcmp (argv [i], "-split") == 0)
9439      {
9440	if (i + 1 >= argc)
9441	  fatal ("-split has no argument.");
9442	fatal ("option `-split' has not been implemented yet\n");
9443	/* split_argument = atoi (argument_vect [i + 1]); */
9444      }
9445  VLA_PTR_CREATE (decls, 150, "decls");
9446  /* Initialize IR storage.  */
9447  obstack_init (&irp);
9448  initiate_automaton_decl_table ();
9449  initiate_insn_decl_table ();
9450  initiate_decl_table ();
9451  output_file = stdout;
9452  output_description_file = NULL;
9453  base_name = base_file_name (argv[1]);
9454  obstack_grow (&irp, base_name,
9455		strlen (base_name) - strlen (file_name_suffix (base_name)));
9456  obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9457		strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9458  obstack_1grow (&irp, '\0');
9459  output_description_file_name = obstack_base (&irp);
9460  obstack_finish (&irp);
9461}
9462
9463/* The following function checks existence at least one arc marked by
9464   each insn.  */
9465static void
9466check_automata_insn_issues ()
9467{
9468  automaton_t automaton;
9469  ainsn_t ainsn, reserv_ainsn;
9470
9471  for (automaton = description->first_automaton;
9472       automaton != NULL;
9473       automaton = automaton->next_automaton)
9474    {
9475      for (ainsn = automaton->ainsn_list;
9476	   ainsn != NULL;
9477	   ainsn = ainsn->next_ainsn)
9478	if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9479	  {
9480	    for (reserv_ainsn = ainsn;
9481		 reserv_ainsn != NULL;
9482		 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9483	      if (automaton->corresponding_automaton_decl != NULL)
9484		{
9485		  if (!w_flag)
9486		    error ("Automaton `%s': Insn `%s' will never be issued",
9487			   automaton->corresponding_automaton_decl->name,
9488			   reserv_ainsn->insn_reserv_decl->name);
9489		  else
9490		    warning
9491		      ("Automaton `%s': Insn `%s' will never be issued",
9492		       automaton->corresponding_automaton_decl->name,
9493		       reserv_ainsn->insn_reserv_decl->name);
9494		}
9495	      else
9496		{
9497		  if (!w_flag)
9498		    error ("Insn `%s' will never be issued",
9499			   reserv_ainsn->insn_reserv_decl->name);
9500		  else
9501		    warning ("Insn `%s' will never be issued",
9502			     reserv_ainsn->insn_reserv_decl->name);
9503		}
9504	  }
9505    }
9506}
9507
9508/* The following vla is used for storing pointers to all achieved
9509   states.  */
9510static vla_ptr_t automaton_states;
9511
9512/* This function is called by function pass_states to add an achieved
9513   STATE.  */
9514static void
9515add_automaton_state (state)
9516     state_t state;
9517{
9518  VLA_PTR_ADD (automaton_states, state);
9519}
9520
9521/* The following function forms list of important automata (whose
9522   states may be changed after the insn issue) for each insn.  */
9523static void
9524form_important_insn_automata_lists ()
9525{
9526  automaton_t automaton;
9527  state_t *state_ptr;
9528  decl_t decl;
9529  ainsn_t ainsn;
9530  arc_t arc;
9531  int i;
9532
9533  VLA_PTR_CREATE (automaton_states, 1500,
9534		  "automaton states for forming important insn automata sets");
9535  /* Mark important ainsns.  */
9536  for (automaton = description->first_automaton;
9537       automaton != NULL;
9538       automaton = automaton->next_automaton)
9539    {
9540      VLA_PTR_NULLIFY (automaton_states);
9541      pass_states (automaton, add_automaton_state);
9542      for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9543	   state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9544	   state_ptr++)
9545	{
9546	  for (arc = first_out_arc (*state_ptr);
9547	       arc != NULL;
9548	       arc = next_out_arc (arc))
9549	    if (arc->to_state != *state_ptr)
9550	      {
9551		if (!arc->insn->first_insn_with_same_reservs)
9552		  abort ();
9553		for (ainsn = arc->insn;
9554		     ainsn != NULL;
9555		     ainsn = ainsn->next_same_reservs_insn)
9556		  ainsn->important_p = TRUE;
9557	      }
9558	}
9559    }
9560  VLA_PTR_DELETE (automaton_states);
9561  /* Create automata sets for the insns.  */
9562  for (i = 0; i < description->decls_num; i++)
9563    {
9564      decl = description->decls [i];
9565      if (decl->mode == dm_insn_reserv)
9566	{
9567	  automata_list_start ();
9568	  for (automaton = description->first_automaton;
9569	       automaton != NULL;
9570	       automaton = automaton->next_automaton)
9571	    for (ainsn = automaton->ainsn_list;
9572		 ainsn != NULL;
9573		 ainsn = ainsn->next_ainsn)
9574	      if (ainsn->important_p
9575		  && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9576		{
9577		  automata_list_add (automaton);
9578		  break;
9579		}
9580	  DECL_INSN_RESERV (decl)->important_automata_list
9581	    = automata_list_finish ();
9582	}
9583    }
9584}
9585
9586
9587/* The following is top level function to generate automat(a,on) for
9588   fast recognition of pipeline hazards.  */
9589void
9590expand_automata ()
9591{
9592  int i;
9593
9594  description = create_node (sizeof (struct description)
9595			     /* One entry for cycle advancing insn.  */
9596			     + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9597  description->decls_num = VLA_PTR_LENGTH (decls);
9598  description->query_units_num = 0;
9599  for (i = 0; i < description->decls_num; i++)
9600    {
9601      description->decls [i] = VLA_PTR (decls, i);
9602      if (description->decls [i]->mode == dm_unit
9603	  && DECL_UNIT (description->decls [i])->query_p)
9604        DECL_UNIT (description->decls [i])->query_num
9605	  = description->query_units_num++;
9606    }
9607  all_time = create_ticker ();
9608  check_time = create_ticker ();
9609  fprintf (stderr, "Check description...");
9610  fflush (stderr);
9611  check_all_description ();
9612  fprintf (stderr, "done\n");
9613  ticker_off (&check_time);
9614  generation_time = create_ticker ();
9615  if (!have_error)
9616    {
9617      transform_insn_regexps ();
9618      check_unit_distributions_to_automata ();
9619    }
9620  if (!have_error)
9621    {
9622      generate ();
9623      check_automata_insn_issues ();
9624    }
9625  if (!have_error)
9626    {
9627      form_important_insn_automata_lists ();
9628      fprintf (stderr, "Generation of attributes...");
9629      fflush (stderr);
9630      make_internal_dfa_insn_code_attr ();
9631      make_insn_alts_attr ();
9632      make_default_insn_latency_attr ();
9633      make_bypass_attr ();
9634      fprintf (stderr, "done\n");
9635    }
9636  ticker_off (&generation_time);
9637  ticker_off (&all_time);
9638  fprintf (stderr, "All other genattrtab stuff...");
9639  fflush (stderr);
9640}
9641
9642/* The following is top level function to output PHR and to finish
9643   work with pipeline description translator.  */
9644void
9645write_automata ()
9646{
9647  fprintf (stderr, "done\n");
9648  if (have_error)
9649    fatal ("Errors in DFA description");
9650  ticker_on (&all_time);
9651  output_time = create_ticker ();
9652  fprintf (stderr, "Forming and outputing automata tables...");
9653  fflush (stderr);
9654  output_dfa_max_issue_rate ();
9655  output_tables ();
9656  fprintf (stderr, "done\n");
9657  fprintf (stderr, "Output functions to work with automata...");
9658  fflush (stderr);
9659  output_chip_definitions ();
9660  output_max_insn_queue_index_def ();
9661  output_internal_min_issue_delay_func ();
9662  output_internal_trans_func ();
9663  /* Cache of insn dfa codes: */
9664  fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9665  fprintf (output_file, "\nstatic int %s;\n\n",
9666	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9667  output_dfa_insn_code_func ();
9668  output_trans_func ();
9669  fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9670  output_internal_state_alts_func ();
9671  output_state_alts_func ();
9672  fprintf (output_file, "\n#endif /* #if %s */\n\n",
9673	   AUTOMATON_STATE_ALTS_MACRO_NAME);
9674  output_min_issue_delay_func ();
9675  output_internal_dead_lock_func ();
9676  output_dead_lock_func ();
9677  output_size_func ();
9678  output_internal_reset_func ();
9679  output_reset_func ();
9680  output_min_insn_conflict_delay_func ();
9681  output_internal_insn_latency_func ();
9682  output_insn_latency_func ();
9683  output_print_reservation_func ();
9684  if (no_minimization_flag)
9685    {
9686      fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9687      output_get_cpu_unit_code_func ();
9688      output_cpu_unit_reservation_p ();
9689      fprintf (output_file, "\n#endif /* #if %s */\n\n",
9690	       CPU_UNITS_QUERY_MACRO_NAME);
9691    }
9692  output_dfa_start_func ();
9693  output_dfa_finish_func ();
9694  fprintf (stderr, "done\n");
9695  if (v_flag)
9696    {
9697      output_description_file = fopen (output_description_file_name, "w");
9698      if (output_description_file == NULL)
9699	{
9700	  perror (output_description_file_name);
9701	  exit (FATAL_EXIT_CODE);
9702	}
9703      fprintf (stderr, "Output automata description...");
9704      fflush (stderr);
9705      output_description ();
9706      output_automaton_descriptions ();
9707      fprintf (stderr, "done\n");
9708      output_statistics (output_description_file);
9709    }
9710  output_statistics (stderr);
9711  ticker_off (&output_time);
9712  output_time_statistics (stderr);
9713  finish_states ();
9714  finish_arcs ();
9715  finish_automata_lists ();
9716  if (time_flag)
9717    {
9718      fprintf (stderr, "Summary:\n");
9719      fprintf (stderr, "  check time ");
9720      print_active_time (stderr, check_time);
9721      fprintf (stderr, ", generation time ");
9722      print_active_time (stderr, generation_time);
9723      fprintf (stderr, ", all time ");
9724      print_active_time (stderr, all_time);
9725      fprintf (stderr, "\n");
9726    }
9727  /* Finish all work.  */
9728  if (output_description_file != NULL)
9729    {
9730      fflush (output_description_file);
9731      if (ferror (stdout) != 0)
9732	fatal ("Error in writing DFA description file %s",
9733               output_description_file_name);
9734      fclose (output_description_file);
9735    }
9736  finish_automaton_decl_table ();
9737  finish_insn_decl_table ();
9738  finish_decl_table ();
9739  obstack_free (&irp, NULL);
9740  if (have_error && output_description_file != NULL)
9741    remove (output_description_file_name);
9742}
9743