OSDN Git Service

* tree-ssa-ifcombine.c (get_name_for_bit_test): Use
[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 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
6863
6864 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME  "dfa_clean_insn_cache"
6865
6866 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6867
6868 #define DFA_START_FUNC_NAME  "dfa_start"
6869
6870 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6871
6872 /* Names of parameters of the PHR interface functions.  */
6873 #define STATE_NAME "state"
6874
6875 #define INSN_PARAMETER_NAME "insn"
6876
6877 #define INSN2_PARAMETER_NAME "insn2"
6878
6879 #define CHIP_PARAMETER_NAME "chip"
6880
6881 #define FILE_PARAMETER_NAME "f"
6882
6883 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6884
6885 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6886
6887 /* Names of the variables whose values are internal insn code of rtx
6888    insn.  */
6889 #define INTERNAL_INSN_CODE_NAME "insn_code"
6890
6891 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6892
6893 /* Names of temporary variables in some functions.  */
6894 #define TEMPORARY_VARIABLE_NAME "temp"
6895
6896 #define I_VARIABLE_NAME "i"
6897
6898 /* Name of result variable in some functions.  */
6899 #define RESULT_VARIABLE_NAME "res"
6900
6901 /* Name of function (attribute) to translate insn into internal insn
6902    code.  */
6903 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6904
6905 /* Name of function (attribute) to translate insn into internal insn
6906    code with caching.  */
6907 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6908
6909 /* Output C type which is used for representation of codes of states
6910    of AUTOMATON.  */
6911 static void
6912 output_state_member_type (FILE *f, automaton_t automaton)
6913 {
6914   output_range_type (f, 0, automaton->achieved_states_num);
6915 }
6916
6917 /* Output definition of the structure representing current DFA(s)
6918    state(s).  */
6919 static void
6920 output_chip_definitions (void)
6921 {
6922   automaton_t automaton;
6923
6924   fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6925   for (automaton = description->first_automaton;
6926        automaton != NULL;
6927        automaton = automaton->next_automaton)
6928     {
6929       fprintf (output_file, "  ");
6930       output_state_member_type (output_file, automaton);
6931       fprintf (output_file, " ");
6932       output_chip_member_name (output_file, automaton);
6933       fprintf (output_file, ";\n");
6934     }
6935   fprintf (output_file, "};\n\n");
6936 #if 0
6937   fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6938 #endif
6939 }
6940
6941
6942 /* The function outputs translate vector of internal insn code into
6943    insn equivalence class number.  The equivalence class number is
6944    used to access to table and vectors representing DFA(s).  */
6945 static void
6946 output_translate_vect (automaton_t automaton)
6947 {
6948   ainsn_t ainsn;
6949   int insn_value;
6950   vla_hwint_t translate_vect;
6951
6952   translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6953
6954   for (insn_value = 0; insn_value < description->insns_num; insn_value++)
6955     /* Undefined value */
6956     VEC_quick_push (vect_el_t, translate_vect,
6957                     automaton->insn_equiv_classes_num);
6958
6959   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6960     VEC_replace (vect_el_t, translate_vect,
6961                  ainsn->insn_reserv_decl->insn_num,
6962                  ainsn->insn_equiv_class_num);
6963
6964   fprintf (output_file,
6965            "/* Vector translating external insn codes to internal ones.*/\n");
6966   fprintf (output_file, "static const ");
6967   output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
6968   fprintf (output_file, " ");
6969   output_translate_vect_name (output_file, automaton);
6970   fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
6971   output_vect (translate_vect);
6972   fprintf (output_file, "};\n\n");
6973   VEC_free (vect_el_t,heap, translate_vect);
6974 }
6975
6976 /* The value in a table state x ainsn -> something which represents
6977    undefined value.  */
6978 static int undefined_vect_el_value;
6979
6980 /* The following function returns nonzero value if the best
6981    representation of the table is comb vector.  */
6982 static int
6983 comb_vect_p (state_ainsn_table_t tab)
6984 {
6985   return  (2 * VEC_length (vect_el_t, tab->full_vect)
6986            > 5 * VEC_length (vect_el_t, tab->comb_vect));
6987 }
6988
6989 /* The following function creates new table for AUTOMATON.  */
6990 static state_ainsn_table_t
6991 create_state_ainsn_table (automaton_t automaton)
6992 {
6993   state_ainsn_table_t tab;
6994   int full_vect_length;
6995   int i;
6996
6997   tab = create_node (sizeof (struct state_ainsn_table));
6998   tab->automaton = automaton;
6999
7000   tab->comb_vect  = VEC_alloc (vect_el_t,heap, 10000);
7001   tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7002
7003   tab->base_vect  = 0;
7004   VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7005                  automaton->achieved_states_num);
7006
7007   full_vect_length = (automaton->insn_equiv_classes_num
7008                       * automaton->achieved_states_num);
7009   tab->full_vect  = VEC_alloc (vect_el_t,heap, full_vect_length);
7010   for (i = 0; i < full_vect_length; i++)
7011     VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7012
7013   tab->min_base_vect_el_value = 0;
7014   tab->max_base_vect_el_value = 0;
7015   tab->min_comb_vect_el_value = 0;
7016   tab->max_comb_vect_el_value = 0;
7017   return tab;
7018 }
7019
7020 /* The following function outputs the best C representation of the
7021    table TAB of given TABLE_NAME.  */
7022 static void
7023 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7024                           void (*output_full_vect_name_func) (FILE *, automaton_t),
7025                           void (*output_comb_vect_name_func) (FILE *, automaton_t),
7026                           void (*output_check_vect_name_func) (FILE *, automaton_t),
7027                           void (*output_base_vect_name_func) (FILE *, automaton_t))
7028 {
7029   if (!comb_vect_p (tab))
7030     {
7031       fprintf (output_file, "/* Vector for %s.  */\n", table_name);
7032       fprintf (output_file, "static const ");
7033       output_range_type (output_file, tab->min_comb_vect_el_value,
7034                          tab->max_comb_vect_el_value);
7035       fprintf (output_file, " ");
7036       (*output_full_vect_name_func) (output_file, tab->automaton);
7037       fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7038       output_vect (tab->full_vect);
7039       fprintf (output_file, "};\n\n");
7040     }
7041   else
7042     {
7043       fprintf (output_file, "/* Comb vector for %s.  */\n", table_name);
7044       fprintf (output_file, "static const ");
7045       output_range_type (output_file, tab->min_comb_vect_el_value,
7046                          tab->max_comb_vect_el_value);
7047       fprintf (output_file, " ");
7048       (*output_comb_vect_name_func) (output_file, tab->automaton);
7049       fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7050       output_vect (tab->comb_vect);
7051       fprintf (output_file, "};\n\n");
7052       fprintf (output_file, "/* Check vector for %s.  */\n", table_name);
7053       fprintf (output_file, "static const ");
7054       output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7055       fprintf (output_file, " ");
7056       (*output_check_vect_name_func) (output_file, tab->automaton);
7057       fprintf (output_file, "[] = {\n");
7058       output_vect (tab->check_vect);
7059       fprintf (output_file, "};\n\n");
7060       fprintf (output_file, "/* Base vector for %s.  */\n", table_name);
7061       fprintf (output_file, "static const ");
7062       output_range_type (output_file, tab->min_base_vect_el_value,
7063                          tab->max_base_vect_el_value);
7064       fprintf (output_file, " ");
7065       (*output_base_vect_name_func) (output_file, tab->automaton);
7066       fprintf (output_file, "[] = {\n");
7067       output_vect (tab->base_vect);
7068       fprintf (output_file, "};\n\n");
7069     }
7070 }
7071
7072 /* The following function adds vector VECT to table TAB as its line
7073    with number VECT_NUM.  */
7074 static void
7075 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7076 {
7077   int vect_length;
7078   size_t real_vect_length;
7079   int comb_vect_index;
7080   int comb_vect_els_num;
7081   int vect_index;
7082   int first_unempty_vect_index;
7083   int additional_els_num;
7084   int no_state_value;
7085   vect_el_t vect_el;
7086   int i;
7087   unsigned long vect_mask, comb_vect_mask;
7088
7089   vect_length = VEC_length (vect_el_t, vect);
7090   gcc_assert (vect_length);
7091   gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7092   real_vect_length = tab->automaton->insn_equiv_classes_num;
7093   /* Form full vector in the table: */
7094   {
7095     size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7096     if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7097       VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7098                      full_base + vect_length);
7099     for (i = 0; i < vect_length; i++)
7100       VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7101                    VEC_index (vect_el_t, vect, i));
7102   }
7103   /* Form comb vector in the table: */
7104   gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7105               == VEC_length (vect_el_t, tab->check_vect));
7106
7107   comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7108   for (first_unempty_vect_index = 0;
7109        first_unempty_vect_index < vect_length;
7110        first_unempty_vect_index++)
7111     if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7112         != undefined_vect_el_value)
7113       break;
7114
7115   /* Search for the place in comb vect for the inserted vect.  */
7116
7117   /* Slow case.  */
7118   if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7119     {
7120       for (comb_vect_index = 0;
7121            comb_vect_index < comb_vect_els_num;
7122            comb_vect_index++)
7123         {
7124           for (vect_index = first_unempty_vect_index;
7125                vect_index < vect_length
7126                && vect_index + comb_vect_index < comb_vect_els_num;
7127                vect_index++)
7128             if (VEC_index (vect_el_t, vect, vect_index)
7129                 != undefined_vect_el_value
7130                 && (VEC_index (vect_el_t, tab->comb_vect,
7131                                vect_index + comb_vect_index)
7132                     != undefined_vect_el_value))
7133               break;
7134           if (vect_index >= vect_length
7135               || vect_index + comb_vect_index >= comb_vect_els_num)
7136             break;
7137         }
7138       goto found;
7139     }
7140
7141   /* Fast case.  */
7142   vect_mask = 0;
7143   for (vect_index = first_unempty_vect_index;
7144        vect_index < vect_length;
7145        vect_index++)
7146     {
7147       vect_mask = vect_mask << 1;
7148       if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7149         vect_mask |= 1;
7150     }
7151
7152   /* Search for the place in comb vect for the inserted vect.  */
7153   comb_vect_index = 0;
7154   if (comb_vect_els_num == 0)
7155     goto found;
7156
7157   comb_vect_mask = 0;
7158   for (vect_index = first_unempty_vect_index;
7159        vect_index < vect_length && vect_index < comb_vect_els_num;
7160        vect_index++)
7161     {
7162       comb_vect_mask <<= 1;
7163       if (vect_index + comb_vect_index < comb_vect_els_num
7164           && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7165              != undefined_vect_el_value)
7166         comb_vect_mask |= 1;
7167     }
7168   if ((vect_mask & comb_vect_mask) == 0)
7169     goto found;
7170
7171   for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7172        comb_vect_index++, i++)
7173     {
7174       comb_vect_mask = (comb_vect_mask << 1) | 1;
7175       comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7176                          == undefined_vect_el_value);
7177       if ((vect_mask & comb_vect_mask) == 0)
7178         goto found;
7179     }
7180   for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7181     {
7182       comb_vect_mask <<= 1;
7183       if ((vect_mask & comb_vect_mask) == 0)
7184         goto found;
7185     }
7186
7187  found:
7188   /* Slot was found.  */
7189   additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7190   if (additional_els_num < 0)
7191     additional_els_num = 0;
7192   /* Expand comb and check vectors.  */
7193   vect_el = undefined_vect_el_value;
7194   no_state_value = tab->automaton->achieved_states_num;
7195   while (additional_els_num > 0)
7196     {
7197       VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7198       VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7199       additional_els_num--;
7200     }
7201   gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7202               >= comb_vect_index + real_vect_length);
7203   /* Fill comb and check vectors.  */
7204   for (vect_index = 0; vect_index < vect_length; vect_index++)
7205     if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7206       {
7207         vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7208         gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7209                                comb_vect_index + vect_index)
7210                     == undefined_vect_el_value);
7211         gcc_assert (x >= 0);
7212         if (tab->max_comb_vect_el_value < x)
7213           tab->max_comb_vect_el_value = x;
7214         if (tab->min_comb_vect_el_value > x)
7215           tab->min_comb_vect_el_value = x;
7216         VEC_replace (vect_el_t, tab->comb_vect,
7217                      comb_vect_index + vect_index, x);
7218         VEC_replace (vect_el_t, tab->check_vect,
7219                      comb_vect_index + vect_index, vect_num);
7220       }
7221   if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7222     tab->max_comb_vect_el_value = undefined_vect_el_value;
7223   if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7224     tab->min_comb_vect_el_value = undefined_vect_el_value;
7225   if (tab->max_base_vect_el_value < comb_vect_index)
7226     tab->max_base_vect_el_value = comb_vect_index;
7227   if (tab->min_base_vect_el_value > comb_vect_index)
7228     tab->min_base_vect_el_value = comb_vect_index;
7229
7230   VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7231 }
7232
7233 /* Return number of out arcs of STATE.  */
7234 static int
7235 out_state_arcs_num (const_state_t state)
7236 {
7237   int result;
7238   arc_t arc;
7239
7240   result = 0;
7241   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7242     {
7243       gcc_assert (arc->insn);
7244       if (arc->insn->first_ainsn_with_given_equivalence_num)
7245         result++;
7246     }
7247   return result;
7248 }
7249
7250 /* Compare number of possible transitions from the states.  */
7251 static int
7252 compare_transition_els_num (const void *state_ptr_1,
7253                             const void *state_ptr_2)
7254 {
7255   const int transition_els_num_1
7256     = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7257   const int transition_els_num_2
7258     = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7259
7260   if (transition_els_num_1 < transition_els_num_2)
7261     return 1;
7262   else if (transition_els_num_1 == transition_els_num_2)
7263     return 0;
7264   else
7265     return -1;
7266 }
7267
7268 /* The function adds element EL_VALUE to vector VECT for a table state
7269    x AINSN.  */
7270 static void
7271 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7272 {
7273   int equiv_class_num;
7274   int vect_index;
7275
7276   gcc_assert (ainsn);
7277   equiv_class_num = ainsn->insn_equiv_class_num;
7278   for (vect_index = VEC_length (vect_el_t, *vect);
7279        vect_index <= equiv_class_num;
7280        vect_index++)
7281     VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7282   VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7283 }
7284
7285 /* This is for forming vector of states of an automaton.  */
7286 static VEC(state_t,heap) *output_states_vect;
7287
7288 /* The function is called by function pass_states.  The function adds
7289    STATE to `output_states_vect'.  */
7290 static void
7291 add_states_vect_el (state_t state)
7292 {
7293   VEC_safe_push (state_t,heap, output_states_vect, state);
7294 }
7295
7296 /* Form and output vectors (comb, check, base or full vector)
7297    representing transition table of AUTOMATON.  */
7298 static void
7299 output_trans_table (automaton_t automaton)
7300 {
7301   size_t i;
7302   arc_t arc;
7303   vla_hwint_t transition_vect = 0;
7304
7305   undefined_vect_el_value = automaton->achieved_states_num;
7306   automaton->trans_table = create_state_ainsn_table (automaton);
7307   /* Create vect of pointers to states ordered by num of transitions
7308      from the state (state with the maximum num is the first).  */
7309   output_states_vect = 0;
7310   pass_states (automaton, add_states_vect_el);
7311   qsort (VEC_address (state_t, output_states_vect),
7312          VEC_length (state_t, output_states_vect),
7313          sizeof (state_t), compare_transition_els_num);
7314
7315   for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7316     {
7317       VEC_truncate (vect_el_t, transition_vect, 0);
7318       for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7319            arc != NULL;
7320            arc = next_out_arc (arc))
7321         {
7322           gcc_assert (arc->insn);
7323           if (arc->insn->first_ainsn_with_given_equivalence_num)
7324             add_vect_el (&transition_vect, arc->insn,
7325                          arc->to_state->order_state_num);
7326         }
7327       add_vect (automaton->trans_table,
7328                 VEC_index (state_t, output_states_vect, i)->order_state_num,
7329                 transition_vect);
7330     }
7331   output_state_ainsn_table
7332     (automaton->trans_table, "state transitions",
7333      output_trans_full_vect_name, output_trans_comb_vect_name,
7334      output_trans_check_vect_name, output_trans_base_vect_name);
7335
7336   VEC_free (state_t,heap, output_states_vect);
7337   VEC_free (vect_el_t,heap, transition_vect);
7338 }
7339
7340 /* The current number of passing states to find minimal issue delay
7341    value for an ainsn and state.  */
7342 static int curr_state_pass_num;
7343
7344 /* This recursive function passes states to find minimal issue delay
7345    value for AINSN.  The state being visited is STATE.  The function
7346    returns minimal issue delay value for AINSN in STATE or -1 if we
7347    enter into a loop.  */
7348 static int
7349 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7350 {
7351   arc_t arc;
7352   int min_insn_issue_delay, insn_issue_delay;
7353
7354   if (state->state_pass_num == curr_state_pass_num
7355       || state->min_insn_issue_delay != -1)
7356     /* We've entered into a loop or already have the correct value for
7357        given state and ainsn.  */
7358     return state->min_insn_issue_delay;
7359   state->state_pass_num = curr_state_pass_num;
7360   min_insn_issue_delay = -1;
7361   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7362     if (arc->insn == ainsn)
7363       {
7364         min_insn_issue_delay = 0;
7365         break;
7366       }
7367     else
7368       {
7369         insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7370         if (insn_issue_delay != -1)
7371           {
7372             if (arc->insn->insn_reserv_decl
7373                 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7374               insn_issue_delay++;
7375             if (min_insn_issue_delay == -1
7376                 || min_insn_issue_delay > insn_issue_delay)
7377               {
7378                 min_insn_issue_delay = insn_issue_delay;
7379                 if (insn_issue_delay == 0)
7380                   break;
7381               }
7382           }
7383       }
7384   return min_insn_issue_delay;
7385 }
7386
7387 /* The function searches minimal issue delay value for AINSN in STATE.
7388    The function can return negative value if we can not issue AINSN.  We
7389    will report about it later.  */
7390 static int
7391 min_issue_delay (state_t state, ainsn_t ainsn)
7392 {
7393   curr_state_pass_num++;
7394   state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7395   return state->min_insn_issue_delay;
7396 }
7397
7398 /* The function initiates code for finding minimal issue delay values.
7399    It should be called only once.  */
7400 static void
7401 initiate_min_issue_delay_pass_states (void)
7402 {
7403   curr_state_pass_num = 0;
7404 }
7405
7406 /* Form and output vectors representing minimal issue delay table of
7407    AUTOMATON.  The table is state x ainsn -> minimal issue delay of
7408    the ainsn.  */
7409 static void
7410 output_min_issue_delay_table (automaton_t automaton)
7411 {
7412   vla_hwint_t min_issue_delay_vect;
7413   vla_hwint_t compressed_min_issue_delay_vect;
7414   vect_el_t min_delay;
7415   ainsn_t ainsn;
7416   size_t i, min_issue_delay_len;
7417   size_t compressed_min_issue_delay_len;
7418   size_t cfactor;
7419
7420   /* Create vect of pointers to states ordered by num of transitions
7421      from the state (state with the maximum num is the first).  */
7422   output_states_vect = 0;
7423   pass_states (automaton, add_states_vect_el);
7424
7425   min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7426                          * automaton->insn_equiv_classes_num);
7427   min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7428   for (i = 0; i < min_issue_delay_len; i++)
7429     VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7430
7431   automaton->max_min_delay = 0;
7432   for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7433     if (ainsn->first_ainsn_with_given_equivalence_num)
7434       {
7435         for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7436           VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7437         for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7438           {
7439             state_t s = VEC_index (state_t, output_states_vect, i);
7440             min_delay = min_issue_delay (s, ainsn);
7441             if (automaton->max_min_delay < min_delay)
7442               automaton->max_min_delay = min_delay;
7443             VEC_replace (vect_el_t, min_issue_delay_vect,
7444                          s->order_state_num
7445                          * automaton->insn_equiv_classes_num
7446                          + ainsn->insn_equiv_class_num,
7447                          min_delay);
7448           }
7449       }
7450   fprintf (output_file, "/* Vector of min issue delay of insns.  */\n");
7451   fprintf (output_file, "static const ");
7452   output_range_type (output_file, 0, automaton->max_min_delay);
7453   fprintf (output_file, " ");
7454   output_min_issue_delay_vect_name (output_file, automaton);
7455   fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7456   /* Compress the vector.  */
7457   if (automaton->max_min_delay < 2)
7458     cfactor = 8;
7459   else if (automaton->max_min_delay < 4)
7460     cfactor = 4;
7461   else if (automaton->max_min_delay < 16)
7462     cfactor = 2;
7463   else
7464     cfactor = 1;
7465   automaton->min_issue_delay_table_compression_factor = cfactor;
7466
7467   compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7468   compressed_min_issue_delay_vect
7469     = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7470
7471   for (i = 0; i < compressed_min_issue_delay_len; i++)
7472     VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7473
7474   for (i = 0; i < min_issue_delay_len; i++)
7475     {
7476       size_t ci = i / cfactor;
7477       vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7478       vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7479
7480       cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7481       VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7482     }
7483   output_vect (compressed_min_issue_delay_vect);
7484   fprintf (output_file, "};\n\n");
7485   VEC_free (state_t,heap, output_states_vect);
7486   VEC_free (vect_el_t,heap, min_issue_delay_vect);
7487   VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7488 }
7489
7490 /* Form and output vector representing the locked states of
7491    AUTOMATON.  */
7492 static void
7493 output_dead_lock_vect (automaton_t automaton)
7494 {
7495   size_t i;
7496   arc_t arc;
7497   vla_hwint_t dead_lock_vect = 0;
7498
7499   /* Create vect of pointers to states ordered by num of
7500      transitions from the state (state with the maximum num is the
7501      first).  */
7502   automaton->locked_states = 0;
7503   output_states_vect = 0;
7504   pass_states (automaton, add_states_vect_el);
7505
7506   VEC_safe_grow (vect_el_t,heap, dead_lock_vect, 
7507                  VEC_length (state_t, output_states_vect));
7508   for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7509     {
7510       state_t s = VEC_index (state_t, output_states_vect, i);
7511       arc = first_out_arc (s);
7512       gcc_assert (arc);
7513       if (next_out_arc (arc) == NULL
7514           && (arc->insn->insn_reserv_decl
7515               == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7516         {
7517           VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7518           automaton->locked_states++;
7519         }
7520       else
7521         VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7522     }
7523   if (automaton->locked_states == 0)
7524     return;
7525
7526   fprintf (output_file, "/* Vector for locked state flags.  */\n");
7527   fprintf (output_file, "static const ");
7528   output_range_type (output_file, 0, 1);
7529   fprintf (output_file, " ");
7530   output_dead_lock_vect_name (output_file, automaton);
7531   fprintf (output_file, "[] = {\n");
7532   output_vect (dead_lock_vect);
7533   fprintf (output_file, "};\n\n");
7534   VEC_free (state_t,heap, output_states_vect);
7535   VEC_free (vect_el_t,heap, dead_lock_vect);
7536 }
7537
7538 /* Form and output vector representing reserved units of the states of
7539    AUTOMATON.  */
7540 static void
7541 output_reserved_units_table (automaton_t automaton)
7542 {
7543   vla_hwint_t reserved_units_table = 0;
7544   int state_byte_size;
7545   int reserved_units_size;
7546   size_t n;
7547   int i;
7548
7549   if (description->query_units_num == 0)
7550     return;
7551
7552   /* Create vect of pointers to states.  */
7553   output_states_vect = 0;
7554   pass_states (automaton, add_states_vect_el);
7555   /* Create vector.  */
7556   state_byte_size = (description->query_units_num + 7) / 8;
7557   reserved_units_size = (VEC_length (state_t, output_states_vect)
7558                          * state_byte_size);
7559
7560   reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7561                  
7562   for (i = 0; i < reserved_units_size; i++)
7563     VEC_quick_push (vect_el_t, reserved_units_table, 0);
7564   for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7565     {
7566       state_t s = VEC_index (state_t, output_states_vect, n);
7567       for (i = 0; i < description->units_num; i++)
7568         if (units_array [i]->query_p
7569             && first_cycle_unit_presence (s, i))
7570           {
7571             int ri = (s->order_state_num * state_byte_size
7572                       + units_array [i]->query_num / 8);
7573             vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7574
7575             x += 1 << (units_array [i]->query_num % 8);
7576             VEC_replace (vect_el_t, reserved_units_table, ri, x);
7577           }
7578     }
7579   fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7580   fprintf (output_file, "/* Vector for reserved units of states.  */\n");
7581   fprintf (output_file, "static const ");
7582   output_range_type (output_file, 0, 255);
7583   fprintf (output_file, " ");
7584   output_reserved_units_table_name (output_file, automaton);
7585   fprintf (output_file, "[] = {\n");
7586   output_vect (reserved_units_table);
7587   fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7588            CPU_UNITS_QUERY_MACRO_NAME);
7589
7590   VEC_free (state_t,heap, output_states_vect);
7591   VEC_free (vect_el_t,heap, reserved_units_table);
7592 }
7593
7594 /* The function outputs all tables representing DFA(s) used for fast
7595    pipeline hazards recognition.  */
7596 static void
7597 output_tables (void)
7598 {
7599   automaton_t automaton;
7600
7601   initiate_min_issue_delay_pass_states ();
7602   for (automaton = description->first_automaton;
7603        automaton != NULL;
7604        automaton = automaton->next_automaton)
7605     {
7606       output_translate_vect (automaton);
7607       output_trans_table (automaton);
7608       output_min_issue_delay_table (automaton);
7609       output_dead_lock_vect (automaton);
7610       output_reserved_units_table (automaton);
7611     }
7612   fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7613            DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7614 }
7615
7616 /* The function outputs definition and value of PHR interface variable
7617    `max_insn_queue_index'.  Its value is not less than maximal queue
7618    length needed for the insn scheduler.  */
7619 static void
7620 output_max_insn_queue_index_def (void)
7621 {
7622   int i, max, latency;
7623   decl_t decl;
7624
7625   max = description->max_insn_reserv_cycles;
7626   for (i = 0; i < description->decls_num; i++)
7627     {
7628       decl = description->decls [i];
7629       if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7630         {
7631           latency = DECL_INSN_RESERV (decl)->default_latency;
7632           if (latency > max)
7633             max = latency;
7634         }
7635       else if (decl->mode == dm_bypass)
7636         {
7637           latency = DECL_BYPASS (decl)->latency;
7638           if (latency > max)
7639             max = latency;
7640         }
7641     }
7642   for (i = 0; (1 << i) <= max; i++)
7643     ;
7644   gcc_assert (i >= 0);
7645   fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7646            (1 << i) - 1);
7647 }
7648
7649 /* The function outputs switch cases for insn reservations using
7650    function *output_automata_list_code.  */
7651 static void
7652 output_insn_code_cases (void (*output_automata_list_code)
7653                         (automata_list_el_t))
7654 {
7655   decl_t decl, decl2;
7656   int i, j;
7657
7658   for (i = 0; i < description->decls_num; i++)
7659     {
7660       decl = description->decls [i];
7661       if (decl->mode == dm_insn_reserv)
7662         DECL_INSN_RESERV (decl)->processed_p = FALSE;
7663     }
7664   for (i = 0; i < description->decls_num; i++)
7665     {
7666       decl = description->decls [i];
7667       if (decl->mode == dm_insn_reserv
7668           && !DECL_INSN_RESERV (decl)->processed_p)
7669         {
7670           for (j = i; j < description->decls_num; j++)
7671             {
7672               decl2 = description->decls [j];
7673               if (decl2->mode == dm_insn_reserv
7674                   && (DECL_INSN_RESERV (decl2)->important_automata_list
7675                       == DECL_INSN_RESERV (decl)->important_automata_list))
7676                 {
7677                   DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7678                   fprintf (output_file, "    case %d: /* %s */\n",
7679                            DECL_INSN_RESERV (decl2)->insn_num,
7680                            DECL_INSN_RESERV (decl2)->name);
7681                 }
7682             }
7683           (*output_automata_list_code)
7684             (DECL_INSN_RESERV (decl)->important_automata_list);
7685         }
7686     }
7687 }
7688
7689
7690 /* The function outputs a code for evaluation of a minimal delay of
7691    issue of insns which have reservations in given AUTOMATA_LIST.  */
7692 static void
7693 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7694 {
7695   automata_list_el_t el;
7696   automaton_t automaton;
7697
7698   for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7699     {
7700       automaton = el->automaton;
7701       fprintf (output_file, "\n      %s = ", TEMPORARY_VARIABLE_NAME);
7702       output_min_issue_delay_vect_name (output_file, automaton);
7703       fprintf (output_file,
7704                (automaton->min_issue_delay_table_compression_factor != 1
7705                 ? " [(" : " ["));
7706       output_translate_vect_name (output_file, automaton);
7707       fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7708       fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7709       output_chip_member_name (output_file, automaton);
7710       fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7711       if (automaton->min_issue_delay_table_compression_factor == 1)
7712         fprintf (output_file, "];\n");
7713       else
7714         {
7715           fprintf (output_file, ") / %d];\n",
7716                    automaton->min_issue_delay_table_compression_factor);
7717           fprintf (output_file, "      %s = (%s >> (8 - (",
7718                    TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7719           output_translate_vect_name (output_file, automaton);
7720           fprintf
7721             (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7722              INTERNAL_INSN_CODE_NAME,
7723              automaton->min_issue_delay_table_compression_factor,
7724              8 / automaton->min_issue_delay_table_compression_factor,
7725              (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7726              - 1);
7727         }
7728       if (el == automata_list)
7729         fprintf (output_file, "      %s = %s;\n",
7730                  RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7731       else
7732         {
7733           fprintf (output_file, "      if (%s > %s)\n",
7734                    TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7735           fprintf (output_file, "        %s = %s;\n",
7736                    RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7737         }
7738     }
7739   fprintf (output_file, "      break;\n\n");
7740 }
7741
7742 /* Output function `internal_min_issue_delay'.  */
7743 static void
7744 output_internal_min_issue_delay_func (void)
7745 {
7746   fprintf (output_file,
7747            "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7748            INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7749            CHIP_NAME, CHIP_PARAMETER_NAME);
7750   fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n  int %s = -1;\n",
7751            TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7752   fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
7753   output_insn_code_cases (output_automata_list_min_issue_delay_code);
7754   fprintf (output_file,
7755            "\n    default:\n      %s = -1;\n      break;\n    }\n",
7756            RESULT_VARIABLE_NAME);
7757   fprintf (output_file, "  return %s;\n", RESULT_VARIABLE_NAME);
7758   fprintf (output_file, "}\n\n");
7759 }
7760
7761 /* The function outputs a code changing state after issue of insns
7762    which have reservations in given AUTOMATA_LIST.  */
7763 static void
7764 output_automata_list_transition_code (automata_list_el_t automata_list)
7765 {
7766   automata_list_el_t el, next_el;
7767
7768   fprintf (output_file, "      {\n");
7769   if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7770     for (el = automata_list;; el = next_el)
7771       {
7772         next_el = el->next_automata_list_el;
7773         if (next_el == NULL)
7774           break;
7775         fprintf (output_file, "        ");
7776         output_state_member_type (output_file, el->automaton);
7777         fprintf (output_file, " ");
7778         output_temp_chip_member_name (output_file, el->automaton);
7779         fprintf (output_file, ";\n");
7780       }
7781   for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7782     if (comb_vect_p (el->automaton->trans_table))
7783       {
7784         fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);
7785         output_trans_base_vect_name (output_file, el->automaton);
7786         fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7787         output_chip_member_name (output_file, el->automaton);
7788         fprintf (output_file, "] + ");
7789         output_translate_vect_name (output_file, el->automaton);
7790         fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7791         fprintf (output_file, "        if (");
7792         output_trans_check_vect_name (output_file, el->automaton);
7793         fprintf (output_file, " [%s] != %s->",
7794                  TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7795         output_chip_member_name (output_file, el->automaton);
7796         fprintf (output_file, ")\n");
7797         fprintf (output_file, "          return %s (%s, %s);\n",
7798                  INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7799                  CHIP_PARAMETER_NAME);
7800         fprintf (output_file, "        else\n");
7801         fprintf (output_file, "          ");
7802         if (el->next_automata_list_el != NULL)
7803           output_temp_chip_member_name (output_file, el->automaton);
7804         else
7805           {
7806             fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7807             output_chip_member_name (output_file, el->automaton);
7808           }
7809         fprintf (output_file, " = ");
7810         output_trans_comb_vect_name (output_file, el->automaton);
7811         fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7812       }
7813     else
7814       {
7815         fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);
7816         output_trans_full_vect_name (output_file, el->automaton);
7817         fprintf (output_file, " [");
7818         output_translate_vect_name (output_file, el->automaton);
7819         fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7820         fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7821         output_chip_member_name (output_file, el->automaton);
7822         fprintf (output_file, " * %d];\n",
7823                  el->automaton->insn_equiv_classes_num);
7824         fprintf (output_file, "        if (%s >= %d)\n",
7825                  TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7826         fprintf (output_file, "          return %s (%s, %s);\n",
7827                  INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7828                  CHIP_PARAMETER_NAME);
7829         fprintf (output_file, "        else\n          ");
7830         if (el->next_automata_list_el != NULL)
7831           output_temp_chip_member_name (output_file, el->automaton);
7832         else
7833           {
7834             fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7835             output_chip_member_name (output_file, el->automaton);
7836           }
7837         fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7838       }
7839   if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7840     for (el = automata_list;; el = next_el)
7841       {
7842         next_el = el->next_automata_list_el;
7843         if (next_el == NULL)
7844           break;
7845         fprintf (output_file, "        %s->", CHIP_PARAMETER_NAME);
7846         output_chip_member_name (output_file, el->automaton);
7847         fprintf (output_file, " = ");
7848         output_temp_chip_member_name (output_file, el->automaton);
7849         fprintf (output_file, ";\n");
7850       }
7851   fprintf (output_file, "        return -1;\n");
7852   fprintf (output_file, "      }\n");
7853 }
7854
7855 /* Output function `internal_state_transition'.  */
7856 static void
7857 output_internal_trans_func (void)
7858 {
7859   fprintf (output_file,
7860            "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7861            INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7862            CHIP_NAME, CHIP_PARAMETER_NAME);
7863   fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7864   fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
7865   output_insn_code_cases (output_automata_list_transition_code);
7866   fprintf (output_file, "\n    default:\n      return -1;\n    }\n");
7867   fprintf (output_file, "}\n\n");
7868 }
7869
7870 /* Output code
7871
7872   if (insn != 0)
7873     {
7874       insn_code = dfa_insn_code (insn);
7875       if (insn_code > DFA__ADVANCE_CYCLE)
7876         return code;
7877     }
7878   else
7879     insn_code = DFA__ADVANCE_CYCLE;
7880
7881   where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7882   code denotes CODE.  */
7883 static void
7884 output_internal_insn_code_evaluation (const char *insn_name,
7885                                       const char *insn_code_name,
7886                                       int code)
7887 {
7888   fprintf (output_file, "\n  if (%s != 0)\n    {\n", insn_name);
7889   fprintf (output_file, "      %s = %s (%s);\n", insn_code_name,
7890            DFA_INSN_CODE_FUNC_NAME, insn_name);
7891   fprintf (output_file, "      if (%s > %s)\n        return %d;\n",
7892            insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7893   fprintf (output_file, "    }\n  else\n    %s = %s;\n\n",
7894            insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7895 }
7896
7897
7898 /* This function outputs `dfa_insn_code' and its helper function
7899    `dfa_insn_code_enlarge'.  */
7900 static void
7901 output_dfa_insn_code_func (void)
7902 {
7903   /* Emacs c-mode gets really confused if there's a { or } in column 0
7904      inside a string, so don't do that.  */
7905   fprintf (output_file, "\
7906 static void\n\
7907 dfa_insn_code_enlarge (int uid)\n\
7908 {\n\
7909   int i = %s;\n\
7910   %s = 2 * uid;\n\
7911   %s = xrealloc (%s,\n\
7912                  %s * sizeof(int));\n\
7913   for (; i < %s; i++)\n\
7914     %s[i] = -1;\n}\n\n",
7915            DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7916            DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7917            DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7918            DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7919            DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7920            DFA_INSN_CODES_VARIABLE_NAME);
7921   fprintf (output_file, "\
7922 static inline int\n%s (rtx %s)\n\
7923 {\n\
7924   int uid = INSN_UID (%s);\n\
7925   int %s;\n\n",
7926            DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7927            INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7928
7929   fprintf (output_file,
7930            "  if (uid >= %s)\n    dfa_insn_code_enlarge (uid);\n\n",
7931            DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7932   fprintf (output_file, "  %s = %s[uid];\n",
7933            INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7934   fprintf (output_file, "\
7935   if (%s < 0)\n\
7936     {\n\
7937       %s = %s (%s);\n\
7938       %s[uid] = %s;\n\
7939     }\n",
7940            INTERNAL_INSN_CODE_NAME,
7941            INTERNAL_INSN_CODE_NAME,
7942            INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7943            DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7944   fprintf (output_file, "  return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7945 }
7946
7947 /* The function outputs PHR interface function `state_transition'.  */
7948 static void
7949 output_trans_func (void)
7950 {
7951   fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7952            TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7953            INSN_PARAMETER_NAME);
7954   fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
7955   output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
7956                                         INTERNAL_INSN_CODE_NAME, -1);
7957   fprintf (output_file, "  return %s (%s, %s);\n}\n\n",
7958            INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
7959 }
7960
7961 /* Output function `min_issue_delay'.  */
7962 static void
7963 output_min_issue_delay_func (void)
7964 {
7965   fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7966            MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7967            INSN_PARAMETER_NAME);
7968   fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
7969   fprintf (output_file, "\n  if (%s != 0)\n    {\n", INSN_PARAMETER_NAME);
7970   fprintf (output_file, "      %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
7971            DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
7972   fprintf (output_file, "      if (%s > %s)\n        return 0;\n",
7973            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7974   fprintf (output_file, "    }\n  else\n    %s = %s;\n",
7975            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7976   fprintf (output_file, "\n  return %s (%s, %s);\n",
7977            INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7978            STATE_NAME);
7979   fprintf (output_file, "}\n\n");
7980 }
7981
7982 /* Output function `internal_dead_lock'.  */
7983 static void
7984 output_internal_dead_lock_func (void)
7985 {
7986   automaton_t automaton;
7987
7988   fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7989            INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
7990   fprintf (output_file, "{\n");
7991   for (automaton = description->first_automaton;
7992        automaton != NULL;
7993        automaton = automaton->next_automaton)
7994     if (automaton->locked_states)
7995       {
7996         fprintf (output_file, "  if (");
7997         output_dead_lock_vect_name (output_file, automaton);
7998         fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7999         output_chip_member_name (output_file, automaton);
8000         fprintf (output_file, "])\n    return 1/* TRUE */;\n");
8001       }
8002   fprintf (output_file, "  return 0/* FALSE */;\n}\n\n");
8003 }
8004
8005 /* The function outputs PHR interface function `state_dead_lock_p'.  */
8006 static void
8007 output_dead_lock_func (void)
8008 {
8009   fprintf (output_file, "int\n%s (%s %s)\n",
8010            DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8011   fprintf (output_file, "{\n  return %s (%s);\n}\n\n",
8012            INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8013 }
8014
8015 /* Output function `internal_reset'.  */
8016 static void
8017 output_internal_reset_func (void)
8018 {
8019   fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8020            INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8021   fprintf (output_file, "{\n  memset (%s, 0, sizeof (struct %s));\n}\n\n",
8022            CHIP_PARAMETER_NAME, CHIP_NAME);
8023 }
8024
8025 /* The function outputs PHR interface function `state_size'.  */
8026 static void
8027 output_size_func (void)
8028 {
8029   fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8030   fprintf (output_file, "{\n  return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8031 }
8032
8033 /* The function outputs PHR interface function `state_reset'.  */
8034 static void
8035 output_reset_func (void)
8036 {
8037   fprintf (output_file, "void\n%s (%s %s)\n",
8038            RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8039   fprintf (output_file, "{\n  %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8040            STATE_NAME);
8041 }
8042
8043 /* Output function `min_insn_conflict_delay'.  */
8044 static void
8045 output_min_insn_conflict_delay_func (void)
8046 {
8047   fprintf (output_file,
8048            "int\n%s (%s %s, rtx %s, rtx %s)\n",
8049            MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8050            STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8051   fprintf (output_file, "{\n  struct %s %s;\n  int %s, %s, transition;\n",
8052            CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8053            INTERNAL_INSN2_CODE_NAME);
8054   output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8055                                         INTERNAL_INSN_CODE_NAME, 0);
8056   output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8057                                         INTERNAL_INSN2_CODE_NAME, 0);
8058   fprintf (output_file, "  memcpy (&%s, %s, sizeof (%s));\n",
8059            CHIP_NAME, STATE_NAME, CHIP_NAME);
8060   fprintf (output_file, "  %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8061   fprintf (output_file, "  transition = %s (%s, &%s);\n",
8062            INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8063   fprintf (output_file, "  gcc_assert (transition <= 0);\n");
8064   fprintf (output_file, "  return %s (%s, &%s);\n",
8065            INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8066            CHIP_NAME);
8067   fprintf (output_file, "}\n\n");
8068 }
8069
8070 /* Output function `internal_insn_latency'.  */
8071 static void
8072 output_internal_insn_latency_func (void)
8073 {
8074   decl_t decl;
8075   struct bypass_decl *bypass;
8076   int i, j, col;
8077   const char *tabletype = "unsigned char";
8078
8079   /* Find the smallest integer type that can hold all the default
8080      latency values.  */
8081   for (i = 0; i < description->decls_num; i++)
8082     if (description->decls[i]->mode == dm_insn_reserv)
8083       {
8084         decl = description->decls[i];
8085         if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8086             && tabletype[0] != 'i')  /* Don't shrink it.  */
8087           tabletype = "unsigned short";
8088         if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8089           tabletype = "int";
8090       }
8091
8092   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",
8093            INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8094            INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8095            INSN2_PARAMETER_NAME);
8096   fprintf (output_file, "{\n");
8097
8098   if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8099     {
8100       fputs ("  return 0;\n}\n\n", output_file);
8101       return;
8102     }
8103
8104   fprintf (output_file, "  static const %s default_latencies[] =\n    {",
8105            tabletype);
8106
8107   for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8108     if (description->decls[i]->mode == dm_insn_reserv
8109         && description->decls[i] != advance_cycle_insn_decl)
8110       {
8111         if ((col = (col+1) % 8) == 0)
8112           fputs ("\n     ", output_file);
8113         decl = description->decls[i];
8114         gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8115         fprintf (output_file, "% 4d,",
8116                  DECL_INSN_RESERV (decl)->default_latency);
8117       }
8118   gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8119   fputs ("\n    };\n", output_file);
8120
8121   fprintf (output_file, "  if (%s >= %s || %s >= %s)\n    return 0;\n",
8122            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8123            INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8124
8125   fprintf (output_file, "  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8126   for (i = 0; i < description->decls_num; i++)
8127     if (description->decls[i]->mode == dm_insn_reserv
8128         && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8129       {
8130         decl = description->decls [i];
8131         fprintf (output_file,
8132                  "    case %d:\n      switch (%s)\n        {\n",
8133                  DECL_INSN_RESERV (decl)->insn_num,
8134                  INTERNAL_INSN2_CODE_NAME);
8135         for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8136              bypass != NULL;
8137              bypass = bypass->next)
8138           {
8139             gcc_assert (bypass->in_insn_reserv->insn_num
8140                         != (DECL_INSN_RESERV
8141                             (advance_cycle_insn_decl)->insn_num));
8142             fprintf (output_file, "        case %d:\n",
8143                      bypass->in_insn_reserv->insn_num);
8144             if (bypass->bypass_guard_name == NULL)
8145               fprintf (output_file, "          return %d;\n",
8146                        bypass->latency);
8147             else
8148               {
8149                 fprintf (output_file,
8150                          "          if (%s (%s, %s))\n",
8151                          bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8152                          INSN2_PARAMETER_NAME);
8153                 fprintf (output_file,
8154                          "            return %d;\n          break;\n",
8155                          bypass->latency);
8156               }
8157           }
8158         fputs ("        }\n      break;\n", output_file);
8159       }
8160
8161   fprintf (output_file, "    }\n  return default_latencies[%s];\n}\n\n",
8162            INTERNAL_INSN_CODE_NAME);
8163 }
8164
8165 /* The function outputs PHR interface function `insn_latency'.  */
8166 static void
8167 output_insn_latency_func (void)
8168 {
8169   fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8170            INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8171   fprintf (output_file, "{\n  int %s, %s;\n",
8172            INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8173   output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8174                                         INTERNAL_INSN_CODE_NAME, 0);
8175   output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8176                                         INTERNAL_INSN2_CODE_NAME, 0);
8177   fprintf (output_file, "  return %s (%s, %s, %s, %s);\n}\n\n",
8178            INTERNAL_INSN_LATENCY_FUNC_NAME,
8179            INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8180            INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8181 }
8182
8183 /* The function outputs PHR interface function `print_reservation'.  */
8184 static void
8185 output_print_reservation_func (void)
8186 {
8187   decl_t decl;
8188   int i, j;
8189
8190   fprintf (output_file,
8191            "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8192            PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8193            INSN_PARAMETER_NAME);
8194
8195   if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8196     {
8197       fprintf (output_file, "  fputs (\"%s\", %s);\n}\n\n",
8198                NOTHING_NAME, FILE_PARAMETER_NAME);
8199       return;
8200     }
8201
8202
8203   fputs ("  static const char *const reservation_names[] =\n    {",
8204          output_file);
8205
8206   for (i = 0, j = 0; i < description->decls_num; i++)
8207     {
8208       decl = description->decls [i];
8209       if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8210         {
8211           gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8212           j++;
8213           
8214           fprintf (output_file, "\n      \"%s\",",
8215                    regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8216           finish_regexp_representation ();
8217         }
8218     }
8219   gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8220
8221   fprintf (output_file, "\n      \"%s\"\n    };\n  int %s;\n\n",
8222            NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8223
8224   fprintf (output_file, "  if (%s == 0)\n    %s = %s;\n",
8225            INSN_PARAMETER_NAME,
8226            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8227   fprintf (output_file, "  else\n\
8228     {\n\
8229       %s = %s (%s);\n\
8230       if (%s > %s)\n\
8231         %s = %s;\n\
8232     }\n",
8233            INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8234                INSN_PARAMETER_NAME,
8235            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8236            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8237
8238   fprintf (output_file, "  fputs (reservation_names[%s], %s);\n}\n\n",
8239            INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8240 }
8241
8242 /* The following function is used to sort unit declaration by their
8243    names.  */
8244 static int
8245 units_cmp (const void *unit1, const void *unit2)
8246 {
8247   const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8248   const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8249
8250   return strcmp (u1->name, u2->name);
8251 }
8252
8253 /* The following macro value is name of struct containing unit name
8254    and unit code.  */
8255 #define NAME_CODE_STRUCT_NAME  "name_code"
8256
8257 /* The following macro value is name of table of struct name_code.  */
8258 #define NAME_CODE_TABLE_NAME   "name_code_table"
8259
8260 /* The following macro values are member names for struct name_code.  */
8261 #define NAME_MEMBER_NAME       "name"
8262 #define CODE_MEMBER_NAME       "code"
8263
8264 /* The following macro values are local variable names for function
8265    `get_cpu_unit_code'.  */
8266 #define CMP_VARIABLE_NAME      "cmp"
8267 #define LOW_VARIABLE_NAME      "l"
8268 #define MIDDLE_VARIABLE_NAME   "m"
8269 #define HIGH_VARIABLE_NAME     "h"
8270
8271 /* The following function outputs function to obtain internal cpu unit
8272    code by the cpu unit name.  */
8273 static void
8274 output_get_cpu_unit_code_func (void)
8275 {
8276   int i;
8277   unit_decl_t *units;
8278
8279   fprintf (output_file, "int\n%s (const char *%s)\n",
8280            GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8281   fprintf (output_file, "{\n  struct %s {const char *%s; int %s;};\n",
8282            NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8283   fprintf (output_file, "  int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8284            LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8285   fprintf (output_file, "  static struct %s %s [] =\n    {\n",
8286            NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8287   units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8288   memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8289   qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8290   for (i = 0; i < description->units_num; i++)
8291     if (units [i]->query_p)
8292       fprintf (output_file, "      {\"%s\", %d},\n",
8293                units[i]->name, units[i]->query_num);
8294   fprintf (output_file, "    };\n\n");
8295   fprintf (output_file, "  /* The following is binary search: */\n");
8296   fprintf (output_file, "  %s = 0;\n", LOW_VARIABLE_NAME);
8297   fprintf (output_file, "  %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8298            HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8299   fprintf (output_file, "  while (%s <= %s)\n    {\n",
8300            LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8301   fprintf (output_file, "      %s = (%s + %s) / 2;\n",
8302            MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8303   fprintf (output_file, "      %s = strcmp (%s, %s [%s].%s);\n",
8304            CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8305            NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8306   fprintf (output_file, "      if (%s < 0)\n", CMP_VARIABLE_NAME);
8307   fprintf (output_file, "        %s = %s - 1;\n",
8308            HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8309   fprintf (output_file, "      else if (%s > 0)\n", CMP_VARIABLE_NAME);
8310   fprintf (output_file, "        %s = %s + 1;\n",
8311            LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8312   fprintf (output_file, "      else\n");
8313   fprintf (output_file, "        return %s [%s].%s;\n    }\n",
8314            NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8315   fprintf (output_file, "  return -1;\n}\n\n");
8316   free (units);
8317 }
8318
8319 /* The following function outputs function to check reservation of cpu
8320    unit (its internal code will be passed as the function argument) in
8321    given cpu state.  */
8322 static void
8323 output_cpu_unit_reservation_p (void)
8324 {
8325   automaton_t automaton;
8326
8327   fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8328            CPU_UNIT_RESERVATION_P_FUNC_NAME,
8329            STATE_TYPE_NAME, STATE_NAME,
8330            CPU_CODE_PARAMETER_NAME);
8331   fprintf (output_file, "{\n  gcc_assert (%s >= 0 && %s < %d);\n",
8332            CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8333            description->query_units_num);
8334   if (description->query_units_num > 0)
8335     for (automaton = description->first_automaton;
8336          automaton != NULL;
8337          automaton = automaton->next_automaton)
8338       {
8339         fprintf (output_file, "  if ((");
8340         output_reserved_units_table_name (output_file, automaton);
8341         fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8342         output_chip_member_name (output_file, automaton);
8343         fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8344                  (description->query_units_num + 7) / 8,
8345                  CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8346         fprintf (output_file, "    return 1;\n");
8347       }
8348   fprintf (output_file, "  return 0;\n}\n\n");
8349 }
8350
8351 /* The following function outputs a function to check if insn
8352    has a dfa reservation.  */
8353 static void
8354 output_insn_has_dfa_reservation_p (void)
8355 {
8356   fprintf (output_file,
8357            "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8358            INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8359            INSN_PARAMETER_NAME);
8360
8361   if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8362     {
8363       fprintf (output_file, "  return false;\n}\n\n");
8364       return;
8365     }
8366
8367   fprintf (output_file, "  int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8368
8369   fprintf (output_file, "  if (%s == 0)\n    %s = %s;\n",
8370            INSN_PARAMETER_NAME,
8371            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8372   fprintf (output_file, "  else\n\
8373     {\n\
8374       %s = %s (%s);\n\
8375       if (%s > %s)\n\
8376         %s = %s;\n\
8377     }\n\n",
8378            INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8379                INSN_PARAMETER_NAME,
8380            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8381            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8382
8383   fprintf (output_file, "  return %s != %s;\n}\n\n",
8384            INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8385 }
8386
8387 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8388    and 'dfa_clear_single_insn_cache'.  */
8389 static void
8390 output_dfa_clean_insn_cache_func (void)
8391 {
8392   fprintf (output_file,
8393            "void\n%s (void)\n{\n  int %s;\n\n",
8394            DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8395   fprintf (output_file,
8396            "  for (%s = 0; %s < %s; %s++)\n    %s [%s] = -1;\n}\n\n",
8397            I_VARIABLE_NAME, I_VARIABLE_NAME,
8398            DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8399            DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8400
8401   fprintf (output_file,
8402            "void\n%s (rtx %s)\n{\n  int %s;\n\n",
8403            DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8404            I_VARIABLE_NAME);
8405   fprintf (output_file,
8406            "  %s = INSN_UID (%s);\n  if (%s < %s)\n    %s [%s] = -1;\n}\n\n",
8407            I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8408            DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8409            I_VARIABLE_NAME);
8410 }
8411
8412 /* The function outputs PHR interface function `dfa_start'.  */
8413 static void
8414 output_dfa_start_func (void)
8415 {
8416   fprintf (output_file,
8417            "void\n%s (void)\n{\n  %s = get_max_uid ();\n",
8418            DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8419   fprintf (output_file, "  %s = xmalloc (%s * sizeof (int));\n",
8420            DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8421   fprintf (output_file, "  %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8422 }
8423
8424 /* The function outputs PHR interface function `dfa_finish'.  */
8425 static void
8426 output_dfa_finish_func (void)
8427 {
8428   fprintf (output_file, "void\n%s (void)\n{\n  free (%s);\n}\n\n",
8429            DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8430 }
8431
8432 \f
8433
8434 /* The page contains code for output description file (readable
8435    representation of original description and generated DFA(s).  */
8436
8437 /* The function outputs string representation of IR reservation.  */
8438 static void
8439 output_regexp (regexp_t regexp)
8440 {
8441   fprintf (output_description_file, "%s", regexp_representation (regexp));
8442   finish_regexp_representation ();
8443 }
8444
8445 /* Output names of units in LIST separated by comma.  */
8446 static void
8447 output_unit_set_el_list (unit_set_el_t list)
8448 {
8449   unit_set_el_t el;
8450
8451   for (el = list; el != NULL; el = el->next_unit_set_el)
8452     {
8453       if (el != list)
8454         fprintf (output_description_file, ", ");
8455       fprintf (output_description_file, "%s", el->unit_decl->name);
8456     }
8457 }
8458
8459 /* Output patterns in LIST separated by comma.  */
8460 static void
8461 output_pattern_set_el_list (pattern_set_el_t list)
8462 {
8463   pattern_set_el_t el;
8464   int i;
8465
8466   for (el = list; el != NULL; el = el->next_pattern_set_el)
8467     {
8468       if (el != list)
8469         fprintf (output_description_file, ", ");
8470       for (i = 0; i < el->units_num; i++)
8471         fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8472                  el->unit_decls [i]->name);
8473     }
8474 }
8475
8476 /* The function outputs string representation of IR define_reservation
8477    and define_insn_reservation.  */
8478 static void
8479 output_description (void)
8480 {
8481   decl_t decl;
8482   int i;
8483
8484   for (i = 0; i < description->decls_num; i++)
8485     {
8486       decl = description->decls [i];
8487       if (decl->mode == dm_unit)
8488         {
8489           if (DECL_UNIT (decl)->excl_list != NULL)
8490             {
8491               fprintf (output_description_file, "unit %s exlusion_set: ",
8492                        DECL_UNIT (decl)->name);
8493               output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8494               fprintf (output_description_file, "\n");
8495             }
8496           if (DECL_UNIT (decl)->presence_list != NULL)
8497             {
8498               fprintf (output_description_file, "unit %s presence_set: ",
8499                        DECL_UNIT (decl)->name);
8500               output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8501               fprintf (output_description_file, "\n");
8502             }
8503           if (DECL_UNIT (decl)->final_presence_list != NULL)
8504             {
8505               fprintf (output_description_file, "unit %s final_presence_set: ",
8506                        DECL_UNIT (decl)->name);
8507               output_pattern_set_el_list
8508                 (DECL_UNIT (decl)->final_presence_list);
8509               fprintf (output_description_file, "\n");
8510             }
8511           if (DECL_UNIT (decl)->absence_list != NULL)
8512             {
8513               fprintf (output_description_file, "unit %s absence_set: ",
8514                        DECL_UNIT (decl)->name);
8515               output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8516               fprintf (output_description_file, "\n");
8517             }
8518           if (DECL_UNIT (decl)->final_absence_list != NULL)
8519             {
8520               fprintf (output_description_file, "unit %s final_absence_set: ",
8521                        DECL_UNIT (decl)->name);
8522               output_pattern_set_el_list
8523                 (DECL_UNIT (decl)->final_absence_list);
8524               fprintf (output_description_file, "\n");
8525             }
8526         }
8527     }
8528   fprintf (output_description_file, "\n");
8529   for (i = 0; i < description->decls_num; i++)
8530     {
8531       decl = description->decls [i];
8532       if (decl->mode == dm_reserv)
8533         {
8534           fprintf (output_description_file, "reservation %s: ",
8535                    DECL_RESERV (decl)->name);
8536           output_regexp (DECL_RESERV (decl)->regexp);
8537           fprintf (output_description_file, "\n");
8538         }
8539       else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8540         {
8541           fprintf (output_description_file, "insn reservation %s ",
8542                    DECL_INSN_RESERV (decl)->name);
8543           print_rtl (output_description_file,
8544                      DECL_INSN_RESERV (decl)->condexp);
8545           fprintf (output_description_file, ": ");
8546           output_regexp (DECL_INSN_RESERV (decl)->regexp);
8547           fprintf (output_description_file, "\n");
8548         }
8549       else if (decl->mode == dm_bypass)
8550         fprintf (output_description_file, "bypass %d %s %s\n",
8551                  DECL_BYPASS (decl)->latency,
8552                  DECL_BYPASS (decl)->out_insn_name,
8553                  DECL_BYPASS (decl)->in_insn_name);
8554     }
8555   fprintf (output_description_file, "\n\f\n");
8556 }
8557
8558 /* The function outputs name of AUTOMATON.  */
8559 static void
8560 output_automaton_name (FILE *f, automaton_t automaton)
8561 {
8562   if (automaton->corresponding_automaton_decl == NULL)
8563     fprintf (f, "#%d", automaton->automaton_order_num);
8564   else
8565     fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8566 }
8567
8568 /* Maximal length of line for pretty printing into description
8569    file.  */
8570 #define MAX_LINE_LENGTH 70
8571
8572 /* The function outputs units name belonging to AUTOMATON.  */
8573 static void
8574 output_automaton_units (automaton_t automaton)
8575 {
8576   decl_t decl;
8577   const char *name;
8578   int curr_line_length;
8579   int there_is_an_automaton_unit;
8580   int i;
8581
8582   fprintf (output_description_file, "\n  Corresponding units:\n");
8583   fprintf (output_description_file, "    ");
8584   curr_line_length = 4;
8585   there_is_an_automaton_unit = 0;
8586   for (i = 0; i < description->decls_num; i++)
8587     {
8588       decl = description->decls [i];
8589       if (decl->mode == dm_unit
8590           && (DECL_UNIT (decl)->corresponding_automaton_num
8591               == automaton->automaton_order_num))
8592         {
8593           there_is_an_automaton_unit = 1;
8594           name = DECL_UNIT (decl)->name;
8595           if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8596             {
8597               curr_line_length = strlen (name) + 4;
8598               fprintf (output_description_file, "\n    ");
8599             }
8600           else
8601             {
8602               curr_line_length += strlen (name) + 1;
8603               fprintf (output_description_file, " ");
8604             }
8605           fprintf (output_description_file, "%s", name);
8606         }
8607     }
8608   if (!there_is_an_automaton_unit)
8609     fprintf (output_description_file, "<None>");
8610   fprintf (output_description_file, "\n\n");
8611 }
8612
8613 /* The following variable is used for forming array of all possible cpu unit
8614    reservations described by the current DFA state.  */
8615 static VEC(reserv_sets_t,heap) *state_reservs;
8616
8617 /* The function forms `state_reservs' for STATE.  */
8618 static void
8619 add_state_reservs (state_t state)
8620 {
8621   alt_state_t curr_alt_state;
8622
8623   if (state->component_states != NULL)
8624     for (curr_alt_state = state->component_states;
8625          curr_alt_state != NULL;
8626          curr_alt_state = curr_alt_state->next_sorted_alt_state)
8627       add_state_reservs (curr_alt_state->state);
8628   else
8629     VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8630 }
8631
8632 /* The function outputs readable representation of all out arcs of
8633    STATE.  */
8634 static void
8635 output_state_arcs (state_t state)
8636 {
8637   arc_t arc;
8638   ainsn_t ainsn;
8639   const char *insn_name;
8640   int curr_line_length;
8641
8642   for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8643     {
8644       ainsn = arc->insn;
8645       gcc_assert (ainsn->first_insn_with_same_reservs);
8646       fprintf (output_description_file, "    ");
8647       curr_line_length = 7;
8648       fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8649       do
8650         {
8651           insn_name = ainsn->insn_reserv_decl->name;
8652           if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8653             {
8654               if (ainsn != arc->insn)
8655                 {
8656                   fprintf (output_description_file, ",\n      ");
8657                   curr_line_length = strlen (insn_name) + 6;
8658                 }
8659               else
8660                 curr_line_length += strlen (insn_name);
8661             }
8662           else
8663             {
8664               curr_line_length += strlen (insn_name);
8665               if (ainsn != arc->insn)
8666                 {
8667                   curr_line_length += 2;
8668                   fprintf (output_description_file, ", ");
8669                 }
8670             }
8671           fprintf (output_description_file, "%s", insn_name);
8672           ainsn = ainsn->next_same_reservs_insn;
8673         }
8674       while (ainsn != NULL);
8675       fprintf (output_description_file, "    %d \n",
8676                arc->to_state->order_state_num);
8677     }
8678   fprintf (output_description_file, "\n");
8679 }
8680
8681 /* The following function is used for sorting possible cpu unit
8682    reservation of a DFA state.  */
8683 static int
8684 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8685 {
8686   return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8687                           *(const_reserv_sets_t const*) reservs_ptr_2);
8688 }
8689
8690 /* The following function is used for sorting possible cpu unit
8691    reservation of a DFA state.  */
8692 static void
8693 remove_state_duplicate_reservs (void)
8694 {
8695   size_t i, j;
8696
8697   for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8698     if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8699                          VEC_index (reserv_sets_t, state_reservs, i)))
8700       {
8701         j++;
8702         VEC_replace (reserv_sets_t, state_reservs, j,
8703                      VEC_index (reserv_sets_t, state_reservs, i));
8704       }
8705   VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8706 }
8707
8708 /* The following function output readable representation of DFA(s)
8709    state used for fast recognition of pipeline hazards.  State is
8710    described by possible (current and scheduled) cpu unit
8711    reservations.  */
8712 static void
8713 output_state (state_t state)
8714 {
8715   size_t i;
8716
8717   state_reservs = 0;
8718
8719   fprintf (output_description_file, "  State #%d", state->order_state_num);
8720   fprintf (output_description_file,
8721            state->new_cycle_p ? " (new cycle)\n" : "\n");
8722   add_state_reservs (state);
8723   qsort (VEC_address (reserv_sets_t, state_reservs),
8724          VEC_length (reserv_sets_t, state_reservs),
8725          sizeof (reserv_sets_t), state_reservs_cmp);
8726   remove_state_duplicate_reservs ();
8727   for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8728     {
8729       fprintf (output_description_file, "    ");
8730       output_reserv_sets (output_description_file,
8731                           VEC_index (reserv_sets_t, state_reservs, i));
8732       fprintf (output_description_file, "\n");
8733     }
8734   fprintf (output_description_file, "\n");
8735   output_state_arcs (state);
8736   VEC_free (reserv_sets_t,heap, state_reservs);
8737 }
8738
8739 /* The following function output readable representation of
8740    DFAs used for fast recognition of pipeline hazards.  */
8741 static void
8742 output_automaton_descriptions (void)
8743 {
8744   automaton_t automaton;
8745
8746   for (automaton = description->first_automaton;
8747        automaton != NULL;
8748        automaton = automaton->next_automaton)
8749     {
8750       fprintf (output_description_file, "\nAutomaton ");
8751       output_automaton_name (output_description_file, automaton);
8752       fprintf (output_description_file, "\n");
8753       output_automaton_units (automaton);
8754       pass_states (automaton, output_state);
8755     }
8756 }
8757
8758 \f
8759
8760 /* The page contains top level function for generation DFA(s) used for
8761    PHR.  */
8762
8763 /* The function outputs statistics about work of different phases of
8764    DFA generator.  */
8765 static void
8766 output_statistics (FILE *f)
8767 {
8768   automaton_t automaton;
8769   int states_num;
8770 #ifndef NDEBUG
8771   int transition_comb_vect_els = 0;
8772   int transition_full_vect_els = 0;
8773   int min_issue_delay_vect_els = 0;
8774   int locked_states = 0;
8775 #endif
8776
8777   for (automaton = description->first_automaton;
8778        automaton != NULL;
8779        automaton = automaton->next_automaton)
8780     {
8781       fprintf (f, "\nAutomaton ");
8782       output_automaton_name (f, automaton);
8783       fprintf (f, "\n    %5d NDFA states,          %5d NDFA arcs\n",
8784                automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8785       fprintf (f, "    %5d DFA states,           %5d DFA arcs\n",
8786                automaton->DFA_states_num, automaton->DFA_arcs_num);
8787       states_num = automaton->DFA_states_num;
8788       if (!no_minimization_flag)
8789         {
8790           fprintf (f, "    %5d minimal DFA states,   %5d minimal DFA arcs\n",
8791                    automaton->minimal_DFA_states_num,
8792                    automaton->minimal_DFA_arcs_num);
8793           states_num = automaton->minimal_DFA_states_num;
8794         }
8795       fprintf (f, "    %5d all insns      %5d insn equivalence classes\n",
8796                description->insns_num, automaton->insn_equiv_classes_num);
8797       fprintf (f, "    %d locked states\n", automaton->locked_states);
8798 #ifndef NDEBUG
8799       fprintf
8800         (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8801          (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8802          (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8803          (comb_vect_p (automaton->trans_table)
8804           ? "use comb vect" : "use simple vect"));
8805       fprintf
8806         (f, "%5ld min delay table els, compression factor %d\n",
8807          (long) states_num * automaton->insn_equiv_classes_num,
8808          automaton->min_issue_delay_table_compression_factor);
8809       transition_comb_vect_els
8810         += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8811       transition_full_vect_els
8812         += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8813       min_issue_delay_vect_els
8814         += states_num * automaton->insn_equiv_classes_num;
8815       locked_states
8816         += automaton->locked_states;
8817 #endif
8818     }
8819 #ifndef NDEBUG
8820   fprintf (f, "\n%5d all allocated states,     %5d all allocated arcs\n",
8821            allocated_states_num, allocated_arcs_num);
8822   fprintf (f, "%5d all allocated alternative states\n",
8823            allocated_alt_states_num);
8824   fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8825            transition_comb_vect_els, transition_full_vect_els);
8826   fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8827   fprintf (f, "%5d all locked states\n", locked_states);
8828 #endif
8829 }
8830
8831 /* The function output times of work of different phases of DFA
8832    generator.  */
8833 static void
8834 output_time_statistics (FILE *f)
8835 {
8836   fprintf (f, "\n  transformation: ");
8837   print_active_time (f, transform_time);
8838   fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8839   print_active_time (f, NDFA_time);
8840   if (ndfa_flag)
8841     {
8842       fprintf (f, ", NDFA -> DFA: ");
8843       print_active_time (f, NDFA_to_DFA_time);
8844     }
8845   fprintf (f, "\n  DFA minimization: ");
8846   print_active_time (f, minimize_time);
8847   fprintf (f, ", making insn equivalence: ");
8848   print_active_time (f, equiv_time);
8849   fprintf (f, "\n all automaton generation: ");
8850   print_active_time (f, automaton_generation_time);
8851   fprintf (f, ", output: ");
8852   print_active_time (f, output_time);
8853   fprintf (f, "\n");
8854 }
8855
8856 /* The function generates DFA (deterministic finite state automaton)
8857    for fast recognition of pipeline hazards.  No errors during
8858    checking must be fixed before this function call.  */
8859 static void
8860 generate (void)
8861 {
8862   automata_num = split_argument;
8863   if (description->units_num < automata_num)
8864     automata_num = description->units_num;
8865   initiate_states ();
8866   initiate_arcs ();
8867   initiate_automata_lists ();
8868   initiate_pass_states ();
8869   initiate_excl_sets ();
8870   initiate_presence_absence_pattern_sets ();
8871   automaton_generation_time = create_ticker ();
8872   create_automata ();
8873   ticker_off (&automaton_generation_time);
8874 }
8875
8876 \f
8877
8878 /* This page mainly contains top level functions of pipeline hazards
8879    description translator.  */
8880
8881 /* The following macro value is suffix of name of description file of
8882    pipeline hazards description translator.  */
8883 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8884
8885 /* The function returns suffix of given file name.  The returned
8886    string can not be changed.  */
8887 static const char *
8888 file_name_suffix (const char *file_name)
8889 {
8890   const char *last_period;
8891
8892   for (last_period = NULL; *file_name != '\0'; file_name++)
8893     if (*file_name == '.')
8894       last_period = file_name;
8895   return (last_period == NULL ? file_name : last_period);
8896 }
8897
8898 /* The function returns base name of given file name, i.e. pointer to
8899    first char after last `/' (or `\' for WIN32) in given file name,
8900    given file name itself if the directory name is absent.  The
8901    returned string can not be changed.  */
8902 static const char *
8903 base_file_name (const char *file_name)
8904 {
8905   int directory_name_length;
8906
8907   directory_name_length = strlen (file_name);
8908 #ifdef WIN32
8909   while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8910          && file_name[directory_name_length] != '\\')
8911 #else
8912   while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8913 #endif
8914     directory_name_length--;
8915   return file_name + directory_name_length + 1;
8916 }
8917
8918 /* The following is top level function to initialize the work of
8919    pipeline hazards description translator.  */
8920 static void
8921 initiate_automaton_gen (int argc, char **argv)
8922 {
8923   const char *base_name;
8924   int i;
8925
8926   ndfa_flag = 0;
8927   split_argument = 0;  /* default value */
8928   no_minimization_flag = 0;
8929   time_flag = 0;
8930   stats_flag = 0;
8931   v_flag = 0;
8932   w_flag = 0;
8933   progress_flag = 0;
8934   for (i = 2; i < argc; i++)
8935     if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8936       no_minimization_flag = 1;
8937     else if (strcmp (argv [i], TIME_OPTION) == 0)
8938       time_flag = 1;
8939     else if (strcmp (argv [i], STATS_OPTION) == 0)
8940       stats_flag = 1;
8941     else if (strcmp (argv [i], V_OPTION) == 0)
8942       v_flag = 1;
8943     else if (strcmp (argv [i], W_OPTION) == 0)
8944       w_flag = 1;
8945     else if (strcmp (argv [i], NDFA_OPTION) == 0)
8946       ndfa_flag = 1;
8947     else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8948       progress_flag = 1;
8949     else if (strcmp (argv [i], "-split") == 0)
8950       {
8951         if (i + 1 >= argc)
8952           fatal ("-split has no argument.");
8953         fatal ("option `-split' has not been implemented yet\n");
8954         /* split_argument = atoi (argument_vect [i + 1]); */
8955       }
8956
8957   /* Initialize IR storage.  */
8958   obstack_init (&irp);
8959   initiate_automaton_decl_table ();
8960   initiate_insn_decl_table ();
8961   initiate_decl_table ();
8962   output_file = stdout;
8963   output_description_file = NULL;
8964   base_name = base_file_name (argv[1]);
8965   obstack_grow (&irp, base_name,
8966                 strlen (base_name) - strlen (file_name_suffix (base_name)));
8967   obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8968                 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8969   obstack_1grow (&irp, '\0');
8970   output_description_file_name = obstack_base (&irp);
8971   obstack_finish (&irp);
8972 }
8973
8974 /* The following function checks existence at least one arc marked by
8975    each insn.  */
8976 static void
8977 check_automata_insn_issues (void)
8978 {
8979   automaton_t automaton;
8980   ainsn_t ainsn, reserv_ainsn;
8981
8982   for (automaton = description->first_automaton;
8983        automaton != NULL;
8984        automaton = automaton->next_automaton)
8985     {
8986       for (ainsn = automaton->ainsn_list;
8987            ainsn != NULL;
8988            ainsn = ainsn->next_ainsn)
8989         if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
8990           {
8991             for (reserv_ainsn = ainsn;
8992                  reserv_ainsn != NULL;
8993                  reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
8994               if (automaton->corresponding_automaton_decl != NULL)
8995                 {
8996                   if (!w_flag)
8997                     error ("Automaton `%s': Insn `%s' will never be issued",
8998                            automaton->corresponding_automaton_decl->name,
8999                            reserv_ainsn->insn_reserv_decl->name);
9000                   else
9001                     warning
9002                       (0, "Automaton `%s': Insn `%s' will never be issued",
9003                        automaton->corresponding_automaton_decl->name,
9004                        reserv_ainsn->insn_reserv_decl->name);
9005                 }
9006               else
9007                 {
9008                   if (!w_flag)
9009                     error ("Insn `%s' will never be issued",
9010                            reserv_ainsn->insn_reserv_decl->name);
9011                   else
9012                     warning (0, "Insn `%s' will never be issued",
9013                              reserv_ainsn->insn_reserv_decl->name);
9014                 }
9015           }
9016     }
9017 }
9018
9019 /* The following vla is used for storing pointers to all achieved
9020    states.  */
9021 static VEC(state_t,heap) *automaton_states;
9022
9023 /* This function is called by function pass_states to add an achieved
9024    STATE.  */
9025 static void
9026 add_automaton_state (state_t state)
9027 {
9028   VEC_safe_push (state_t,heap, automaton_states, state);
9029 }
9030
9031 /* The following function forms list of important automata (whose
9032    states may be changed after the insn issue) for each insn.  */
9033 static void
9034 form_important_insn_automata_lists (void)
9035 {
9036   automaton_t automaton;
9037   decl_t decl;
9038   ainsn_t ainsn;
9039   arc_t arc;
9040   int i;
9041   size_t n;
9042
9043   automaton_states = 0;
9044   /* Mark important ainsns.  */
9045   for (automaton = description->first_automaton;
9046        automaton != NULL;
9047        automaton = automaton->next_automaton)
9048     {
9049       VEC_truncate (state_t, automaton_states, 0);
9050       pass_states (automaton, add_automaton_state);
9051       for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9052         {
9053           state_t s = VEC_index (state_t, automaton_states, n);
9054           for (arc = first_out_arc (s);
9055                arc != NULL;
9056                arc = next_out_arc (arc))
9057             if (arc->to_state != s)
9058               {
9059                 gcc_assert (arc->insn->first_insn_with_same_reservs);
9060                 for (ainsn = arc->insn;
9061                      ainsn != NULL;
9062                      ainsn = ainsn->next_same_reservs_insn)
9063                   ainsn->important_p = TRUE;
9064               }
9065         }
9066     }
9067   VEC_free (state_t,heap, automaton_states);
9068
9069   /* Create automata sets for the insns.  */
9070   for (i = 0; i < description->decls_num; i++)
9071     {
9072       decl = description->decls [i];
9073       if (decl->mode == dm_insn_reserv)
9074         {
9075           automata_list_start ();
9076           for (automaton = description->first_automaton;
9077                automaton != NULL;
9078                automaton = automaton->next_automaton)
9079             for (ainsn = automaton->ainsn_list;
9080                  ainsn != NULL;
9081                  ainsn = ainsn->next_ainsn)
9082               if (ainsn->important_p
9083                   && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9084                 {
9085                   automata_list_add (automaton);
9086                   break;
9087                 }
9088           DECL_INSN_RESERV (decl)->important_automata_list
9089             = automata_list_finish ();
9090         }
9091     }
9092 }
9093
9094
9095 /* The following is top level function to generate automat(a,on) for
9096    fast recognition of pipeline hazards.  */
9097 static void
9098 expand_automata (void)
9099 {
9100   int i;
9101
9102   description = create_node (sizeof (struct description)
9103                              /* One entry for cycle advancing insn.  */
9104                              + sizeof (decl_t) * VEC_length (decl_t, decls));
9105   description->decls_num = VEC_length (decl_t, decls);
9106   description->query_units_num = 0;
9107   for (i = 0; i < description->decls_num; i++)
9108     {
9109       description->decls [i] = VEC_index (decl_t, decls, i);
9110       if (description->decls [i]->mode == dm_unit
9111           && DECL_UNIT (description->decls [i])->query_p)
9112         DECL_UNIT (description->decls [i])->query_num
9113           = description->query_units_num++;
9114     }
9115   all_time = create_ticker ();
9116   check_time = create_ticker ();
9117   if (progress_flag)
9118     fprintf (stderr, "Check description...");
9119   check_all_description ();
9120   if (progress_flag)
9121     fprintf (stderr, "done\n");
9122   ticker_off (&check_time);
9123   generation_time = create_ticker ();
9124   if (!have_error)
9125     {
9126       transform_insn_regexps ();
9127       check_unit_distributions_to_automata ();
9128     }
9129   if (!have_error)
9130     {
9131       generate ();
9132       check_automata_insn_issues ();
9133     }
9134   if (!have_error)
9135     {
9136       form_important_insn_automata_lists ();
9137     }
9138   ticker_off (&generation_time);
9139 }
9140
9141 /* The following is top level function to output PHR and to finish
9142    work with pipeline description translator.  */
9143 static void
9144 write_automata (void)
9145 {
9146   output_time = create_ticker ();
9147   if (progress_flag)
9148     fprintf (stderr, "Forming and outputting automata tables...");
9149   output_tables ();
9150   if (progress_flag)
9151     {
9152       fprintf (stderr, "done\n");
9153       fprintf (stderr, "Output functions to work with automata...");
9154     }
9155   output_chip_definitions ();
9156   output_max_insn_queue_index_def ();
9157   output_internal_min_issue_delay_func ();
9158   output_internal_trans_func ();
9159   /* Cache of insn dfa codes: */
9160   fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9161   fprintf (output_file, "\nstatic int %s;\n\n",
9162            DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9163   output_dfa_insn_code_func ();
9164   output_trans_func ();
9165   output_min_issue_delay_func ();
9166   output_internal_dead_lock_func ();
9167   output_dead_lock_func ();
9168   output_size_func ();
9169   output_internal_reset_func ();
9170   output_reset_func ();
9171   output_min_insn_conflict_delay_func ();
9172   output_internal_insn_latency_func ();
9173   output_insn_latency_func ();
9174   output_print_reservation_func ();
9175   /* Output function get_cpu_unit_code.  */
9176   fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9177   output_get_cpu_unit_code_func ();
9178   output_cpu_unit_reservation_p ();
9179   output_insn_has_dfa_reservation_p ();
9180   fprintf (output_file, "\n#endif /* #if %s */\n\n",
9181            CPU_UNITS_QUERY_MACRO_NAME);
9182   output_dfa_clean_insn_cache_func ();
9183   output_dfa_start_func ();
9184   output_dfa_finish_func ();
9185   if (progress_flag)
9186     fprintf (stderr, "done\n");
9187   if (v_flag)
9188     {
9189       output_description_file = fopen (output_description_file_name, "w");
9190       if (output_description_file == NULL)
9191         {
9192           perror (output_description_file_name);
9193           exit (FATAL_EXIT_CODE);
9194         }
9195       if (progress_flag)
9196         fprintf (stderr, "Output automata description...");
9197       output_description ();
9198       output_automaton_descriptions ();
9199       if (progress_flag)
9200         fprintf (stderr, "done\n");
9201       output_statistics (output_description_file);
9202     }
9203   if (stats_flag)
9204     output_statistics (stderr);
9205   ticker_off (&output_time);
9206   if (time_flag)
9207     output_time_statistics (stderr);
9208   finish_states ();
9209   finish_arcs ();
9210   finish_automata_lists ();
9211   if (time_flag)
9212     {
9213       fprintf (stderr, "Summary:\n");
9214       fprintf (stderr, "  check time ");
9215       print_active_time (stderr, check_time);
9216       fprintf (stderr, ", generation time ");
9217       print_active_time (stderr, generation_time);
9218       fprintf (stderr, ", all time ");
9219       print_active_time (stderr, all_time);
9220       fprintf (stderr, "\n");
9221     }
9222   /* Finish all work.  */
9223   if (output_description_file != NULL)
9224     {
9225       fflush (output_description_file);
9226       if (ferror (stdout) != 0)
9227         fatal ("Error in writing DFA description file %s: %s",
9228                output_description_file_name, xstrerror (errno));
9229       fclose (output_description_file);
9230     }
9231   finish_automaton_decl_table ();
9232   finish_insn_decl_table ();
9233   finish_decl_table ();
9234   obstack_free (&irp, NULL);
9235   if (have_error && output_description_file != NULL)
9236     remove (output_description_file_name);
9237 }
9238
9239 int
9240 main (int argc, char **argv)
9241 {
9242   rtx desc;
9243
9244   progname = "genautomata";
9245
9246   if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9247     return (FATAL_EXIT_CODE);
9248
9249   initiate_automaton_gen (argc, argv);
9250   while (1)
9251     {
9252       int lineno;
9253       int insn_code_number;
9254
9255       desc = read_md_rtx (&lineno, &insn_code_number);
9256       if (desc == NULL)
9257         break;
9258
9259       switch (GET_CODE (desc))
9260         {
9261         case DEFINE_CPU_UNIT:
9262           gen_cpu_unit (desc);
9263           break;
9264
9265         case DEFINE_QUERY_CPU_UNIT:
9266           gen_query_cpu_unit (desc);
9267           break;
9268
9269         case DEFINE_BYPASS:
9270           gen_bypass (desc);
9271           break;
9272
9273         case EXCLUSION_SET:
9274           gen_excl_set (desc);
9275           break;
9276
9277         case PRESENCE_SET:
9278           gen_presence_set (desc);
9279           break;
9280
9281         case FINAL_PRESENCE_SET:
9282           gen_final_presence_set (desc);
9283           break;
9284
9285         case ABSENCE_SET:
9286           gen_absence_set (desc);
9287           break;
9288
9289         case FINAL_ABSENCE_SET:
9290           gen_final_absence_set (desc);
9291           break;
9292
9293         case DEFINE_AUTOMATON:
9294           gen_automaton (desc);
9295           break;
9296
9297         case AUTOMATA_OPTION:
9298           gen_automata_option (desc);
9299           break;
9300
9301         case DEFINE_RESERVATION:
9302           gen_reserv (desc);
9303           break;
9304
9305         case DEFINE_INSN_RESERVATION:
9306           gen_insn_reserv (desc);
9307           break;
9308
9309         default:
9310           break;
9311         }
9312     }
9313
9314   if (have_error)
9315     return FATAL_EXIT_CODE;
9316
9317   puts ("/* Generated automatically by the program `genautomata'\n"
9318         "   from the machine description file `md'.  */\n\n"
9319         "#include \"config.h\"\n"
9320         "#include \"system.h\"\n"
9321         "#include \"coretypes.h\"\n"
9322         "#include \"tm.h\"\n"
9323         "#include \"rtl.h\"\n"
9324         "#include \"tm_p.h\"\n"
9325         "#include \"insn-config.h\"\n"
9326         "#include \"recog.h\"\n"
9327         "#include \"regs.h\"\n"
9328         "#include \"real.h\"\n"
9329         "#include \"output.h\"\n"
9330         "#include \"insn-attr.h\"\n"
9331         "#include \"toplev.h\"\n"
9332         "#include \"flags.h\"\n"
9333         "#include \"function.h\"\n");
9334
9335   if (VEC_length (decl_t, decls) > 0)
9336     {
9337       expand_automata ();
9338       write_automata ();
9339     }
9340
9341   fflush (stdout);
9342   return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
9343 }