OSDN Git Service

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