OSDN Git Service

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