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