OSDN Git Service

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