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