OSDN Git Service

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