OSDN Git Service

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