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