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