OSDN Git Service

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