1117395Skan/* Pipeline hazard description translator.
2169689Skan   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
3169689Skan   Free Software Foundation, Inc.
4117395Skan
5117395Skan   Written by Vladimir Makarov <vmakarov@redhat.com>
6117395Skan
7132718SkanThis file is part of GCC.
8132718Skan
9132718SkanGCC is free software; you can redistribute it and/or modify it
10117395Skanunder the terms of the GNU General Public License as published by the
11117395SkanFree Software Foundation; either version 2, or (at your option) any
12117395Skanlater version.
13117395Skan
14132718SkanGCC is distributed in the hope that it will be useful, but WITHOUT
15117395SkanANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16117395SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17117395Skanfor more details.
18117395Skan
19117395SkanYou should have received a copy of the GNU General Public License
20132718Skanalong with GCC; see the file COPYING.  If not, write to the Free
21169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22169689Skan02110-1301, USA.  */
23117395Skan
24117395Skan/* References:
25132718Skan
26117395Skan   1. Detecting pipeline structural hazards quickly. T. Proebsting,
27117395Skan      C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
28117395Skan      Principles of Programming Languages, pages 280--286, 1994.
29117395Skan
30117395Skan      This article is a good start point to understand usage of finite
31117395Skan      state automata for pipeline hazard recognizers.  But I'd
32117395Skan      recommend the 2nd article for more deep understanding.
33117395Skan
34117395Skan   2. Efficient Instruction Scheduling Using Finite State Automata:
35117395Skan      V. Bala and N. Rubin, Proceedings of MICRO-28.  This is the best
36117395Skan      article about usage of finite state automata for pipeline hazard
37117395Skan      recognizers.
38117395Skan
39117395Skan   The current implementation is different from the 2nd article in the
40117395Skan   following:
41117395Skan
42117395Skan   1. New operator `|' (alternative) is permitted in functional unit
43132718Skan      reservation which can be treated deterministically and
44132718Skan      non-deterministically.
45117395Skan
46117395Skan   2. Possibility of usage of nondeterministic automata too.
47117395Skan
48117395Skan   3. Possibility to query functional unit reservations for given
49117395Skan      automaton state.
50117395Skan
51117395Skan   4. Several constructions to describe impossible reservations
52132718Skan      (`exclusion_set', `presence_set', `final_presence_set',
53132718Skan      `absence_set', and `final_absence_set').
54117395Skan
55117395Skan   5. No reverse automata are generated.  Trace instruction scheduling
56117395Skan      requires this.  It can be easily added in the future if we
57117395Skan      really need this.
58117395Skan
59117395Skan   6. Union of automaton states are not generated yet.  It is planned
60117395Skan      to be implemented.  Such feature is needed to make more accurate
61117395Skan      interlock insn scheduling to get state describing functional
62132718Skan      unit reservation in a joint CFG point.  */
63117395Skan
64117395Skan/* This file code processes constructions of machine description file
65117395Skan   which describes automaton used for recognition of processor pipeline
66117395Skan   hazards by insn scheduler and can be used for other tasks (such as
67117395Skan   VLIW insn packing.
68117395Skan
69117395Skan   The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
70117395Skan   `gen_bypass', `gen_excl_set', `gen_presence_set',
71132718Skan   `gen_final_presence_set', `gen_absence_set',
72132718Skan   `gen_final_absence_set', `gen_automaton', `gen_automata_option',
73117395Skan   `gen_reserv', `gen_insn_reserv' are called from file
74117395Skan   `genattrtab.c'.  They transform RTL constructions describing
75117395Skan   automata in .md file into internal representation convenient for
76117395Skan   further processing.
77132718Skan
78117395Skan   The translator major function `expand_automata' processes the
79117395Skan   description internal representation into finite state automaton.
80117395Skan   It can be divided on:
81117395Skan
82117395Skan     o checking correctness of the automaton pipeline description
83117395Skan       (major function is `check_all_description').
84117395Skan
85117395Skan     o generating automaton (automata) from the description (major
86117395Skan       function is `make_automaton').
87117395Skan
88117395Skan     o optional transformation of nondeterministic finite state
89117395Skan       automata into deterministic ones if the alternative operator
90132718Skan       `|' is treated nondeterministically in the description (major
91117395Skan       function is NDFA_to_DFA).
92117395Skan
93117395Skan     o optional minimization of the finite state automata by merging
94117395Skan       equivalent automaton states (major function is `minimize_DFA').
95117395Skan
96117395Skan     o forming tables (some as comb vectors) and attributes
97117395Skan       representing the automata (functions output_..._table).
98117395Skan
99117395Skan   Function `write_automata' outputs the created finite state
100117395Skan   automaton as different tables and functions which works with the
101117395Skan   automata to inquire automaton state and to change its state.  These
102117395Skan   function are used by gcc instruction scheduler and may be some
103117395Skan   other gcc code.  */
104117395Skan
105132718Skan#include "bconfig.h"
106117395Skan#include "system.h"
107132718Skan#include "coretypes.h"
108132718Skan#include "tm.h"
109117395Skan#include "rtl.h"
110117395Skan#include "obstack.h"
111117395Skan#include "errors.h"
112169689Skan#include "gensupport.h"
113117395Skan
114117395Skan#include <math.h>
115117395Skan#include "hashtab.h"
116169689Skan#include "vec.h"
117117395Skan
118117395Skan#ifndef CHAR_BIT
119117395Skan#define CHAR_BIT 8
120117395Skan#endif
121117395Skan
122117395Skan/* Positions in machine description file.  Now they are not used.  But
123117395Skan   they could be used in the future for better diagnostic messages.  */
124117395Skantypedef int pos_t;
125117395Skan
126117395Skan/* The following is element of vector of current (and planned in the
127117395Skan   future) functional unit reservations.  */
128117395Skantypedef unsigned HOST_WIDE_INT set_el_t;
129117395Skan
130117395Skan/* Reservations of function units are represented by value of the following
131117395Skan   type.  */
132117395Skantypedef set_el_t *reserv_sets_t;
133117395Skan
134117395Skan/* The following structure describes a ticker.  */
135117395Skanstruct ticker
136117395Skan{
137117395Skan  /* The following member value is time of the ticker creation with
138117395Skan     taking into account time when the ticker is off.  Active time of
139117395Skan     the ticker is current time minus the value.  */
140117395Skan  int modified_creation_time;
141117395Skan  /* The following member value is time (incremented by one) when the
142117395Skan     ticker was off.  Zero value means that now the ticker is on.  */
143117395Skan  int incremented_off_time;
144117395Skan};
145117395Skan
146117395Skan/* The ticker is represented by the following type.  */
147117395Skantypedef struct ticker ticker_t;
148117395Skan
149117395Skan/* The following type describes elements of output vectors.  */
150117395Skantypedef HOST_WIDE_INT vect_el_t;
151117395Skan
152117395Skan/* Forward declaration of structures of internal representation of
153117395Skan   pipeline description based on NDFA.  */
154117395Skan
155117395Skanstruct unit_decl;
156117395Skanstruct bypass_decl;
157117395Skanstruct result_decl;
158117395Skanstruct automaton_decl;
159132718Skanstruct unit_pattern_rel_decl;
160117395Skanstruct reserv_decl;
161117395Skanstruct insn_reserv_decl;
162117395Skanstruct decl;
163117395Skanstruct unit_regexp;
164117395Skanstruct result_regexp;
165117395Skanstruct reserv_regexp;
166117395Skanstruct nothing_regexp;
167117395Skanstruct sequence_regexp;
168117395Skanstruct repeat_regexp;
169117395Skanstruct allof_regexp;
170117395Skanstruct oneof_regexp;
171117395Skanstruct regexp;
172117395Skanstruct description;
173117395Skanstruct unit_set_el;
174132718Skanstruct pattern_set_el;
175132718Skanstruct pattern_reserv;
176117395Skanstruct state;
177117395Skanstruct alt_state;
178117395Skanstruct arc;
179117395Skanstruct ainsn;
180117395Skanstruct automaton;
181117395Skanstruct state_ainsn_table;
182117395Skan
183117395Skan/* The following typedefs are for brevity.  */
184117395Skantypedef struct unit_decl *unit_decl_t;
185117395Skantypedef struct decl *decl_t;
186117395Skantypedef struct regexp *regexp_t;
187117395Skantypedef struct unit_set_el *unit_set_el_t;
188132718Skantypedef struct pattern_set_el *pattern_set_el_t;
189132718Skantypedef struct pattern_reserv *pattern_reserv_t;
190117395Skantypedef struct alt_state *alt_state_t;
191117395Skantypedef struct state *state_t;
192117395Skantypedef struct arc *arc_t;
193117395Skantypedef struct ainsn *ainsn_t;
194117395Skantypedef struct automaton *automaton_t;
195117395Skantypedef struct automata_list_el *automata_list_el_t;
196117395Skantypedef struct state_ainsn_table *state_ainsn_table_t;
197117395Skan
198117395Skan/* Undefined position.  */
199117395Skanstatic pos_t no_pos = 0;
200117395Skan
201117395Skan/* All IR is stored in the following obstack.  */
202117395Skanstatic struct obstack irp;
203117395Skan
204117395Skan
205169689Skan/* Declare vector types for various data structures: */
206117395Skan
207169689SkanDEF_VEC_P(alt_state_t);
208169689SkanDEF_VEC_ALLOC_P(alt_state_t,heap);
209169689SkanDEF_VEC_P(ainsn_t);
210169689SkanDEF_VEC_ALLOC_P(ainsn_t,heap);
211169689SkanDEF_VEC_P(state_t);
212169689SkanDEF_VEC_ALLOC_P(state_t,heap);
213169689SkanDEF_VEC_P(decl_t);
214169689SkanDEF_VEC_ALLOC_P(decl_t,heap);
215169689SkanDEF_VEC_P(reserv_sets_t);
216169689SkanDEF_VEC_ALLOC_P(reserv_sets_t,heap);
217117395Skan
218169689SkanDEF_VEC_I(vect_el_t);
219169689SkanDEF_VEC_ALLOC_I(vect_el_t, heap);
220169689Skantypedef VEC(vect_el_t,heap) *vla_hwint_t;
221169689Skan
222169689Skan/* Forward declarations of functions used before their definitions, only.  */
223169689Skanstatic regexp_t gen_regexp_sequence    (const char *);
224169689Skanstatic void reserv_sets_or             (reserv_sets_t, reserv_sets_t,
225169689Skan				        reserv_sets_t);
226169689Skanstatic reserv_sets_t get_excl_set      (reserv_sets_t);
227169689Skanstatic int check_presence_pattern_sets (reserv_sets_t,
228169689Skan					reserv_sets_t, int);
229169689Skanstatic int check_absence_pattern_sets  (reserv_sets_t, reserv_sets_t,
230169689Skan					int);
231169689Skanstatic arc_t first_out_arc             (state_t);
232169689Skanstatic arc_t next_out_arc              (arc_t);
233117395Skan
234117395Skan
235117395Skan
236117395Skan/* Options with the following names can be set up in automata_option
237117395Skan   construction.  Because the strings occur more one time we use the
238117395Skan   macros.  */
239117395Skan
240117395Skan#define NO_MINIMIZATION_OPTION "-no-minimization"
241117395Skan
242117395Skan#define TIME_OPTION "-time"
243117395Skan
244117395Skan#define V_OPTION "-v"
245117395Skan
246117395Skan#define W_OPTION "-w"
247117395Skan
248117395Skan#define NDFA_OPTION "-ndfa"
249117395Skan
250132718Skan#define PROGRESS_OPTION "-progress"
251132718Skan
252117395Skan/* The following flags are set up by function `initiate_automaton_gen'.  */
253117395Skan
254117395Skan/* Make automata with nondeterministic reservation by insns (`-ndfa').  */
255117395Skanstatic int ndfa_flag;
256117395Skan
257117395Skan/* Do not make minimization of DFA (`-no-minimization').  */
258117395Skanstatic int no_minimization_flag;
259117395Skan
260117395Skan/* Value of this variable is number of automata being generated.  The
261117395Skan   actual number of automata may be less this value if there is not
262117395Skan   sufficient number of units.  This value is defined by argument of
263117395Skan   option `-split' or by constructions automaton if the value is zero
264117395Skan   (it is default value of the argument).  */
265117395Skanstatic int split_argument;
266117395Skan
267117395Skan/* Flag of output time statistics (`-time').  */
268117395Skanstatic int time_flag;
269117395Skan
270117395Skan/* Flag of creation of description file which contains description of
271117395Skan   result automaton and statistics information (`-v').  */
272117395Skanstatic int v_flag;
273117395Skan
274132718Skan/* Flag of output of a progress bar showing how many states were
275132718Skan   generated so far for automaton being processed (`-progress').  */
276132718Skanstatic int progress_flag;
277132718Skan
278117395Skan/* Flag of generating warning instead of error for non-critical errors
279117395Skan   (`-w').  */
280117395Skanstatic int w_flag;
281117395Skan
282117395Skan
283117395Skan/* Output file for pipeline hazard recognizer (PHR) being generated.
284117395Skan   The value is NULL if the file is not defined.  */
285117395Skanstatic FILE *output_file;
286117395Skan
287117395Skan/* Description file of PHR.  The value is NULL if the file is not
288117395Skan   created.  */
289117395Skanstatic FILE *output_description_file;
290117395Skan
291117395Skan/* PHR description file name.  */
292117395Skanstatic char *output_description_file_name;
293117395Skan
294117395Skan/* Value of the following variable is node representing description
295117395Skan   being processed.  This is start point of IR.  */
296117395Skanstatic struct description *description;
297117395Skan
298117395Skan
299117395Skan
300117395Skan/* This page contains description of IR structure (nodes).  */
301117395Skan
302117395Skanenum decl_mode
303117395Skan{
304117395Skan  dm_unit,
305117395Skan  dm_bypass,
306117395Skan  dm_automaton,
307117395Skan  dm_excl,
308117395Skan  dm_presence,
309117395Skan  dm_absence,
310117395Skan  dm_reserv,
311117395Skan  dm_insn_reserv
312117395Skan};
313117395Skan
314117395Skan/* This describes define_cpu_unit and define_query_cpu_unit (see file
315117395Skan   rtl.def).  */
316117395Skanstruct unit_decl
317117395Skan{
318169689Skan  const char *name;
319117395Skan  /* NULL if the automaton name is absent.  */
320169689Skan  const char *automaton_name;
321117395Skan  /* If the following value is not zero, the cpu unit reservation is
322117395Skan     described in define_query_cpu_unit.  */
323117395Skan  char query_p;
324117395Skan
325117395Skan  /* The following fields are defined by checker.  */
326117395Skan
327117395Skan  /* The following field value is nonzero if the unit is used in an
328117395Skan     regexp.  */
329117395Skan  char unit_is_used;
330117395Skan
331117395Skan  /* The following field value is order number (0, 1, ...) of given
332117395Skan     unit.  */
333117395Skan  int unit_num;
334117395Skan  /* The following field value is corresponding declaration of
335117395Skan     automaton which was given in description.  If the field value is
336117395Skan     NULL then automaton in the unit declaration was absent.  */
337117395Skan  struct automaton_decl *automaton_decl;
338117395Skan  /* The following field value is maximal cycle number (1, ...) on
339117395Skan     which given unit occurs in insns.  Zero value means that given
340117395Skan     unit is not used in insns.  */
341117395Skan  int max_occ_cycle_num;
342132718Skan  /* The following field value is minimal cycle number (0, ...) on
343132718Skan     which given unit occurs in insns.  -1 value means that given
344132718Skan     unit is not used in insns.  */
345132718Skan  int min_occ_cycle_num;
346117395Skan  /* The following list contains units which conflict with given
347117395Skan     unit.  */
348117395Skan  unit_set_el_t excl_list;
349132718Skan  /* The following list contains patterns which are required to
350117395Skan     reservation of given unit.  */
351132718Skan  pattern_set_el_t presence_list;
352132718Skan  pattern_set_el_t final_presence_list;
353132718Skan  /* The following list contains patterns which should be not present
354132718Skan     in reservation for given unit.  */
355132718Skan  pattern_set_el_t absence_list;
356132718Skan  pattern_set_el_t final_absence_list;
357117395Skan  /* The following is used only when `query_p' has nonzero value.
358117395Skan     This is query number for the unit.  */
359117395Skan  int query_num;
360132718Skan  /* The following is the last cycle on which the unit was checked for
361132718Skan     correct distributions of units to automata in a regexp.  */
362132718Skan  int last_distribution_check_cycle;
363117395Skan
364117395Skan  /* The following fields are defined by automaton generator.  */
365117395Skan
366117395Skan  /* The following field value is number of the automaton to which
367117395Skan     given unit belongs.  */
368117395Skan  int corresponding_automaton_num;
369132718Skan  /* If the following value is not zero, the cpu unit is present in a
370132718Skan     `exclusion_set' or in right part of a `presence_set',
371132718Skan     `final_presence_set', `absence_set', and
372132718Skan     `final_absence_set'define_query_cpu_unit.  */
373132718Skan  char in_set_p;
374117395Skan};
375117395Skan
376117395Skan/* This describes define_bypass (see file rtl.def).  */
377117395Skanstruct bypass_decl
378117395Skan{
379117395Skan  int latency;
380169689Skan  const char *out_insn_name;
381169689Skan  const char *in_insn_name;
382169689Skan  const char *bypass_guard_name;
383117395Skan
384117395Skan  /* The following fields are defined by checker.  */
385117395Skan
386117395Skan  /* output and input insns of given bypass.  */
387117395Skan  struct insn_reserv_decl *out_insn_reserv;
388117395Skan  struct insn_reserv_decl *in_insn_reserv;
389117395Skan  /* The next bypass for given output insn.  */
390117395Skan  struct bypass_decl *next;
391117395Skan};
392117395Skan
393117395Skan/* This describes define_automaton (see file rtl.def).  */
394117395Skanstruct automaton_decl
395117395Skan{
396169689Skan  const char *name;
397117395Skan
398117395Skan  /* The following fields are defined by automaton generator.  */
399117395Skan
400117395Skan  /* The following field value is nonzero if the automaton is used in
401117395Skan     an regexp definition.  */
402117395Skan  char automaton_is_used;
403117395Skan
404117395Skan  /* The following fields are defined by checker.  */
405117395Skan
406117395Skan  /* The following field value is the corresponding automaton.  This
407117395Skan     field is not NULL only if the automaton is present in unit
408117395Skan     declarations and the automatic partition on automata is not
409117395Skan     used.  */
410117395Skan  automaton_t corresponding_automaton;
411117395Skan};
412117395Skan
413132718Skan/* This describes exclusion relations: exclusion_set (see file
414132718Skan   rtl.def).  */
415132718Skanstruct excl_rel_decl
416117395Skan{
417132718Skan  int all_names_num;
418117395Skan  int first_list_length;
419117395Skan  char *names [1];
420117395Skan};
421117395Skan
422132718Skan/* This describes unit relations: [final_]presence_set or
423132718Skan   [final_]absence_set (see file rtl.def).  */
424132718Skanstruct unit_pattern_rel_decl
425132718Skan{
426132718Skan  int final_p;
427132718Skan  int names_num;
428132718Skan  int patterns_num;
429132718Skan  char **names;
430132718Skan  char ***patterns;
431132718Skan};
432132718Skan
433117395Skan/* This describes define_reservation (see file rtl.def).  */
434117395Skanstruct reserv_decl
435117395Skan{
436169689Skan  const char *name;
437117395Skan  regexp_t regexp;
438117395Skan
439117395Skan  /* The following fields are defined by checker.  */
440117395Skan
441117395Skan  /* The following field value is nonzero if the unit is used in an
442117395Skan     regexp.  */
443117395Skan  char reserv_is_used;
444117395Skan  /* The following field is used to check up cycle in expression
445117395Skan     definition.  */
446117395Skan  int loop_pass_num;
447117395Skan};
448117395Skan
449132718Skan/* This describes define_insn_reservation (see file rtl.def).  */
450117395Skanstruct insn_reserv_decl
451117395Skan{
452117395Skan  rtx condexp;
453117395Skan  int default_latency;
454117395Skan  regexp_t regexp;
455169689Skan  const char *name;
456117395Skan
457117395Skan  /* The following fields are defined by checker.  */
458117395Skan
459117395Skan  /* The following field value is order number (0, 1, ...) of given
460117395Skan     insn.  */
461117395Skan  int insn_num;
462117395Skan  /* The following field value is list of bypasses in which given insn
463117395Skan     is output insn.  */
464117395Skan  struct bypass_decl *bypass_list;
465117395Skan
466117395Skan  /* The following fields are defined by automaton generator.  */
467117395Skan
468117395Skan  /* The following field is the insn regexp transformed that
469117395Skan     the regexp has not optional regexp, repetition regexp, and an
470117395Skan     reservation name (i.e. reservation identifiers are changed by the
471117395Skan     corresponding regexp) and all alternations are the topest level
472117395Skan     of the regexp.  The value can be NULL only if it is special
473117395Skan     insn `cycle advancing'.  */
474117395Skan  regexp_t transformed_regexp;
475117395Skan  /* The following field value is list of arcs marked given
476132718Skan     insn.  The field is used in transformation NDFA -> DFA.  */
477117395Skan  arc_t arcs_marked_by_insn;
478117395Skan  /* The two following fields are used during minimization of a finite state
479117395Skan     automaton.  */
480117395Skan  /* The field value is number of equivalence class of state into
481117395Skan     which arc marked by given insn enters from a state (fixed during
482117395Skan     an automaton minimization).  */
483117395Skan  int equiv_class_num;
484117395Skan  /* The following member value is the list to automata which can be
485117395Skan     changed by the insn issue.  */
486117395Skan  automata_list_el_t important_automata_list;
487117395Skan  /* The following member is used to process insn once for output.  */
488117395Skan  int processed_p;
489117395Skan};
490117395Skan
491117395Skan/* This contains a declaration mentioned above.  */
492117395Skanstruct decl
493117395Skan{
494117395Skan  /* What node in the union? */
495117395Skan  enum decl_mode mode;
496117395Skan  pos_t pos;
497117395Skan  union
498117395Skan  {
499117395Skan    struct unit_decl unit;
500117395Skan    struct bypass_decl bypass;
501117395Skan    struct automaton_decl automaton;
502132718Skan    struct excl_rel_decl excl;
503132718Skan    struct unit_pattern_rel_decl presence;
504132718Skan    struct unit_pattern_rel_decl absence;
505117395Skan    struct reserv_decl reserv;
506117395Skan    struct insn_reserv_decl insn_reserv;
507117395Skan  } decl;
508117395Skan};
509117395Skan
510117395Skan/* The following structures represent parsed reservation strings.  */
511117395Skanenum regexp_mode
512117395Skan{
513117395Skan  rm_unit,
514117395Skan  rm_reserv,
515117395Skan  rm_nothing,
516117395Skan  rm_sequence,
517117395Skan  rm_repeat,
518117395Skan  rm_allof,
519117395Skan  rm_oneof
520117395Skan};
521117395Skan
522117395Skan/* Cpu unit in reservation.  */
523117395Skanstruct unit_regexp
524117395Skan{
525169689Skan  const char *name;
526117395Skan  unit_decl_t unit_decl;
527117395Skan};
528117395Skan
529117395Skan/* Define_reservation in a reservation.  */
530117395Skanstruct reserv_regexp
531117395Skan{
532169689Skan  const char *name;
533117395Skan  struct reserv_decl *reserv_decl;
534117395Skan};
535117395Skan
536117395Skan/* Absence of reservation (represented by string `nothing').  */
537117395Skanstruct nothing_regexp
538117395Skan{
539117395Skan  /* This used to be empty but ISO C doesn't allow that.  */
540117395Skan  char unused;
541117395Skan};
542117395Skan
543117395Skan/* Representation of reservations separated by ',' (see file
544117395Skan   rtl.def).  */
545117395Skanstruct sequence_regexp
546117395Skan{
547117395Skan  int regexps_num;
548117395Skan  regexp_t regexps [1];
549117395Skan};
550117395Skan
551117395Skan/* Representation of construction `repeat' (see file rtl.def).  */
552117395Skanstruct repeat_regexp
553117395Skan{
554117395Skan  int repeat_num;
555117395Skan  regexp_t regexp;
556117395Skan};
557117395Skan
558117395Skan/* Representation of reservations separated by '+' (see file
559117395Skan   rtl.def).  */
560117395Skanstruct allof_regexp
561117395Skan{
562117395Skan  int regexps_num;
563117395Skan  regexp_t regexps [1];
564117395Skan};
565117395Skan
566117395Skan/* Representation of reservations separated by '|' (see file
567117395Skan   rtl.def).  */
568117395Skanstruct oneof_regexp
569117395Skan{
570117395Skan  int regexps_num;
571117395Skan  regexp_t regexps [1];
572117395Skan};
573117395Skan
574117395Skan/* Representation of a reservation string.  */
575117395Skanstruct regexp
576117395Skan{
577117395Skan  /* What node in the union? */
578117395Skan  enum regexp_mode mode;
579117395Skan  pos_t pos;
580117395Skan  union
581117395Skan  {
582117395Skan    struct unit_regexp unit;
583117395Skan    struct reserv_regexp reserv;
584117395Skan    struct nothing_regexp nothing;
585117395Skan    struct sequence_regexp sequence;
586117395Skan    struct repeat_regexp repeat;
587117395Skan    struct allof_regexp allof;
588117395Skan    struct oneof_regexp oneof;
589117395Skan  } regexp;
590117395Skan};
591117395Skan
592132718Skan/* Represents description of pipeline hazard description based on
593117395Skan   NDFA.  */
594117395Skanstruct description
595117395Skan{
596117395Skan  int decls_num;
597117395Skan
598117395Skan  /* The following fields are defined by checker.  */
599117395Skan
600117395Skan  /* The following fields values are correspondingly number of all
601117395Skan     units, query units, and insns in the description.  */
602117395Skan  int units_num;
603117395Skan  int query_units_num;
604117395Skan  int insns_num;
605117395Skan  /* The following field value is max length (in cycles) of
606117395Skan     reservations of insns.  The field value is defined only for
607117395Skan     correct programs.  */
608117395Skan  int max_insn_reserv_cycles;
609117395Skan
610117395Skan  /* The following fields are defined by automaton generator.  */
611117395Skan
612117395Skan  /* The following field value is the first automaton.  */
613117395Skan  automaton_t first_automaton;
614117395Skan
615117395Skan  /* The following field is created by pipeline hazard parser and
616117395Skan     contains all declarations.  We allocate additional entry for
617117395Skan     special insn "cycle advancing" which is added by the automaton
618117395Skan     generator.  */
619117395Skan  decl_t decls [1];
620117395Skan};
621117395Skan
622117395Skan
623117395Skan/* The following nodes are created in automaton checker.  */
624117395Skan
625132718Skan/* The following nodes represent exclusion set for cpu units.  Each
626132718Skan   element is accessed through only one excl_list.  */
627117395Skanstruct unit_set_el
628117395Skan{
629117395Skan  unit_decl_t unit_decl;
630117395Skan  unit_set_el_t next_unit_set_el;
631117395Skan};
632117395Skan
633132718Skan/* The following nodes represent presence or absence pattern for cpu
634132718Skan   units.  Each element is accessed through only one presence_list or
635132718Skan   absence_list.  */
636132718Skanstruct pattern_set_el
637132718Skan{
638132718Skan  /* The number of units in unit_decls.  */
639132718Skan  int units_num;
640132718Skan  /* The units forming the pattern.  */
641132718Skan  struct unit_decl **unit_decls;
642132718Skan  pattern_set_el_t next_pattern_set_el;
643132718Skan};
644117395Skan
645117395Skan
646117395Skan/* The following nodes are created in automaton generator.  */
647117395Skan
648132718Skan
649132718Skan/* The following nodes represent presence or absence pattern for cpu
650132718Skan   units.  Each element is accessed through only one element of
651132718Skan   unit_presence_set_table or unit_absence_set_table.  */
652132718Skanstruct pattern_reserv
653132718Skan{
654132718Skan  reserv_sets_t reserv;
655132718Skan  pattern_reserv_t next_pattern_reserv;
656132718Skan};
657132718Skan
658117395Skan/* The following node type describes state automaton.  The state may
659117395Skan   be deterministic or non-deterministic.  Non-deterministic state has
660117395Skan   several component states which represent alternative cpu units
661117395Skan   reservations.  The state also is used for describing a
662117395Skan   deterministic reservation of automaton insn.  */
663117395Skanstruct state
664117395Skan{
665117395Skan  /* The following member value is nonzero if there is a transition by
666117395Skan     cycle advancing.  */
667117395Skan  int new_cycle_p;
668117395Skan  /* The following field is list of processor unit reservations on
669117395Skan     each cycle.  */
670117395Skan  reserv_sets_t reservs;
671117395Skan  /* The following field is unique number of given state between other
672117395Skan     states.  */
673117395Skan  int unique_num;
674117395Skan  /* The following field value is automaton to which given state
675117395Skan     belongs.  */
676117395Skan  automaton_t automaton;
677117395Skan  /* The following field value is the first arc output from given
678117395Skan     state.  */
679117395Skan  arc_t first_out_arc;
680169689Skan  unsigned int num_out_arcs;
681117395Skan  /* The following field is used to form NDFA.  */
682117395Skan  char it_was_placed_in_stack_for_NDFA_forming;
683117395Skan  /* The following field is used to form DFA.  */
684117395Skan  char it_was_placed_in_stack_for_DFA_forming;
685132718Skan  /* The following field is used to transform NDFA to DFA and DFA
686132718Skan     minimization.  The field value is not NULL if the state is a
687132718Skan     compound state.  In this case the value of field `unit_sets_list'
688132718Skan     is NULL.  All states in the list are in the hash table.  The list
689132718Skan     is formed through field `next_sorted_alt_state'.  We should
690132718Skan     support only one level of nesting state.  */
691117395Skan  alt_state_t component_states;
692117395Skan  /* The following field is used for passing graph of states.  */
693117395Skan  int pass_num;
694117395Skan  /* The list of states belonging to one equivalence class is formed
695117395Skan     with the aid of the following field.  */
696117395Skan  state_t next_equiv_class_state;
697117395Skan  /* The two following fields are used during minimization of a finite
698117395Skan     state automaton.  */
699117395Skan  int equiv_class_num_1, equiv_class_num_2;
700117395Skan  /* The following field is used during minimization of a finite state
701117395Skan     automaton.  The field value is state corresponding to equivalence
702117395Skan     class to which given state belongs.  */
703117395Skan  state_t equiv_class_state;
704169689Skan  unsigned int *presence_signature;
705117395Skan  /* The following field value is the order number of given state.
706117395Skan     The states in final DFA is enumerated with the aid of the
707117395Skan     following field.  */
708117395Skan  int order_state_num;
709117395Skan  /* This member is used for passing states for searching minimal
710117395Skan     delay time.  */
711117395Skan  int state_pass_num;
712117395Skan  /* The following member is used to evaluate min issue delay of insn
713117395Skan     for a state.  */
714117395Skan  int min_insn_issue_delay;
715117395Skan  /* The following member is used to evaluate max issue rate of the
716117395Skan     processor.  The value of the member is maximal length of the path
717117395Skan     from given state no containing arcs marked by special insn `cycle
718117395Skan     advancing'.  */
719117395Skan  int longest_path_length;
720117395Skan};
721117395Skan
722117395Skan/* The following macro is an initial value of member
723117395Skan   `longest_path_length' of a state.  */
724117395Skan#define UNDEFINED_LONGEST_PATH_LENGTH -1
725117395Skan
726117395Skan/* Automaton arc.  */
727117395Skanstruct arc
728117395Skan{
729117395Skan  /* The following field refers for the state into which given arc
730117395Skan     enters.  */
731117395Skan  state_t to_state;
732117395Skan  /* The following field describes that the insn issue (with cycle
733117395Skan     advancing for special insn `cycle advancing' and without cycle
734117395Skan     advancing for others) makes transition from given state to
735117395Skan     another given state.  */
736117395Skan  ainsn_t insn;
737117395Skan  /* The following field value is the next arc output from the same
738117395Skan     state.  */
739117395Skan  arc_t next_out_arc;
740117395Skan  /* List of arcs marked given insn is formed with the following
741132718Skan     field.  The field is used in transformation NDFA -> DFA.  */
742117395Skan  arc_t next_arc_marked_by_insn;
743117395Skan};
744117395Skan
745117395Skan/* The following node type describes a deterministic alternative in
746117395Skan   non-deterministic state which characterizes cpu unit reservations
747117395Skan   of automaton insn or which is part of NDFA.  */
748117395Skanstruct alt_state
749117395Skan{
750132718Skan  /* The following field is a deterministic state which characterizes
751117395Skan     unit reservations of the instruction.  */
752117395Skan  state_t state;
753117395Skan  /* The following field refers to the next state which characterizes
754117395Skan     unit reservations of the instruction.  */
755117395Skan  alt_state_t next_alt_state;
756117395Skan  /* The following field refers to the next state in sorted list.  */
757117395Skan  alt_state_t next_sorted_alt_state;
758117395Skan};
759117395Skan
760117395Skan/* The following node type describes insn of automaton.  They are
761117395Skan   labels of FA arcs.  */
762117395Skanstruct ainsn
763117395Skan{
764117395Skan  /* The following field value is the corresponding insn declaration
765117395Skan     of description.  */
766117395Skan  struct insn_reserv_decl *insn_reserv_decl;
767117395Skan  /* The following field value is the next insn declaration for an
768117395Skan     automaton.  */
769117395Skan  ainsn_t next_ainsn;
770117395Skan  /* The following field is states which characterize automaton unit
771117395Skan     reservations of the instruction.  The value can be NULL only if it
772117395Skan     is special insn `cycle advancing'.  */
773117395Skan  alt_state_t alt_states;
774117395Skan  /* The following field is sorted list of states which characterize
775117395Skan     automaton unit reservations of the instruction.  The value can be
776117395Skan     NULL only if it is special insn `cycle advancing'.  */
777117395Skan  alt_state_t sorted_alt_states;
778117395Skan  /* The following field refers the next automaton insn with
779117395Skan     the same reservations.  */
780117395Skan  ainsn_t next_same_reservs_insn;
781117395Skan  /* The following field is flag of the first automaton insn with the
782117395Skan     same reservations in the declaration list.  Only arcs marked such
783117395Skan     insn is present in the automaton.  This significantly decreases
784117395Skan     memory requirements especially when several automata are
785117395Skan     formed.  */
786117395Skan  char first_insn_with_same_reservs;
787117395Skan  /* The following member has nonzero value if there is arc from state of
788117395Skan     the automaton marked by the ainsn.  */
789117395Skan  char arc_exists_p;
790117395Skan  /* Cyclic list of insns of an equivalence class is formed with the
791117395Skan     aid of the following field.  */
792117395Skan  ainsn_t next_equiv_class_insn;
793117395Skan  /* The following field value is nonzero if the insn declaration is
794117395Skan     the first insn declaration with given equivalence number.  */
795169689Skan  char first_ainsn_with_given_equivalence_num;
796117395Skan  /* The following field is number of class of equivalence of insns.
797117395Skan     It is necessary because many insns may be equivalent with the
798117395Skan     point of view of pipeline hazards.  */
799117395Skan  int insn_equiv_class_num;
800117395Skan  /* The following member value is TRUE if there is an arc in the
801117395Skan     automaton marked by the insn into another state.  In other
802117395Skan     words, the insn can change the state of the automaton.  */
803117395Skan  int important_p;
804117395Skan};
805117395Skan
806132718Skan/* The following describes an automaton for PHR.  */
807117395Skanstruct automaton
808117395Skan{
809117395Skan  /* The following field value is the list of insn declarations for
810117395Skan     given automaton.  */
811117395Skan  ainsn_t ainsn_list;
812117395Skan  /* The following field value is the corresponding automaton
813117395Skan     declaration.  This field is not NULL only if the automatic
814117395Skan     partition on automata is not used.  */
815117395Skan  struct automaton_decl *corresponding_automaton_decl;
816117395Skan  /* The following field value is the next automaton.  */
817117395Skan  automaton_t next_automaton;
818117395Skan  /* The following field is start state of FA.  There are not unit
819117395Skan     reservations in the state.  */
820117395Skan  state_t start_state;
821117395Skan  /* The following field value is number of equivalence classes of
822117395Skan     insns (see field `insn_equiv_class_num' in
823117395Skan     `insn_reserv_decl').  */
824117395Skan  int insn_equiv_classes_num;
825117395Skan  /* The following field value is number of states of final DFA.  */
826117395Skan  int achieved_states_num;
827117395Skan  /* The following field value is the order number (0, 1, ...) of
828117395Skan     given automaton.  */
829117395Skan  int automaton_order_num;
830117395Skan  /* The following fields contain statistics information about
831117395Skan     building automaton.  */
832117395Skan  int NDFA_states_num, DFA_states_num;
833117395Skan  /* The following field value is defined only if minimization of DFA
834117395Skan     is used.  */
835117395Skan  int minimal_DFA_states_num;
836117395Skan  int NDFA_arcs_num, DFA_arcs_num;
837117395Skan  /* The following field value is defined only if minimization of DFA
838117395Skan     is used.  */
839117395Skan  int minimal_DFA_arcs_num;
840169689Skan  /* The following member refers for two table state x ainsn -> int.
841169689Skan     ??? Above sentence is incomprehensible.  */
842117395Skan  state_ainsn_table_t trans_table;
843117395Skan  /* The following member value is maximal value of min issue delay
844117395Skan     for insns of the automaton.  */
845117395Skan  int max_min_delay;
846117395Skan  /* Usually min issue delay is small and we can place several (2, 4,
847117395Skan     8) elements in one vector element.  So the compression factor can
848117395Skan     be 1 (no compression), 2, 4, 8.  */
849117395Skan  int min_issue_delay_table_compression_factor;
850169689Skan  /* Total number of locked states in this automaton.  */
851169689Skan  int locked_states;
852117395Skan};
853117395Skan
854117395Skan/* The following is the element of the list of automata.  */
855117395Skanstruct automata_list_el
856117395Skan{
857117395Skan  /* The automaton itself.  */
858117395Skan  automaton_t automaton;
859117395Skan  /* The next automata set element.  */
860117395Skan  automata_list_el_t next_automata_list_el;
861117395Skan};
862117395Skan
863117395Skan/* The following structure describes a table state X ainsn -> int(>= 0).  */
864117395Skanstruct state_ainsn_table
865117395Skan{
866117395Skan  /* Automaton to which given table belongs.  */
867117395Skan  automaton_t automaton;
868117395Skan  /* The following tree vectors for comb vector implementation of the
869117395Skan     table.  */
870117395Skan  vla_hwint_t comb_vect;
871117395Skan  vla_hwint_t check_vect;
872117395Skan  vla_hwint_t base_vect;
873117395Skan  /* This is simple implementation of the table.  */
874117395Skan  vla_hwint_t full_vect;
875117395Skan  /* Minimal and maximal values of the previous vectors.  */
876117395Skan  int min_comb_vect_el_value, max_comb_vect_el_value;
877117395Skan  int min_base_vect_el_value, max_base_vect_el_value;
878117395Skan};
879117395Skan
880117395Skan/* Macros to access members of unions.  Use only them for access to
881117395Skan   union members of declarations and regexps.  */
882117395Skan
883117395Skan#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
884117395Skan
885117395Skan#define DECL_UNIT(d) __extension__					\
886117395Skan(({ struct decl *const _decl = (d);					\
887117395Skan     if (_decl->mode != dm_unit)					\
888117395Skan       decl_mode_check_failed (_decl->mode, "dm_unit",			\
889117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
890117395Skan     &(_decl)->decl.unit; }))
891117395Skan
892117395Skan#define DECL_BYPASS(d) __extension__					\
893117395Skan(({ struct decl *const _decl = (d);					\
894117395Skan     if (_decl->mode != dm_bypass)					\
895117395Skan       decl_mode_check_failed (_decl->mode, "dm_bypass",		\
896117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
897117395Skan     &(_decl)->decl.bypass; }))
898117395Skan
899117395Skan#define DECL_AUTOMATON(d) __extension__					\
900132718Skan(({ struct decl *const _decl = (d);					\
901117395Skan     if (_decl->mode != dm_automaton)					\
902117395Skan       decl_mode_check_failed (_decl->mode, "dm_automaton",		\
903117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
904117395Skan     &(_decl)->decl.automaton; }))
905117395Skan
906117395Skan#define DECL_EXCL(d) __extension__					\
907132718Skan(({ struct decl *const _decl = (d);					\
908117395Skan     if (_decl->mode != dm_excl)					\
909117395Skan       decl_mode_check_failed (_decl->mode, "dm_excl",			\
910117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
911117395Skan     &(_decl)->decl.excl; }))
912117395Skan
913117395Skan#define DECL_PRESENCE(d) __extension__					\
914117395Skan(({ struct decl *const _decl = (d);					\
915117395Skan     if (_decl->mode != dm_presence)					\
916117395Skan       decl_mode_check_failed (_decl->mode, "dm_presence",		\
917117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
918117395Skan     &(_decl)->decl.presence; }))
919117395Skan
920117395Skan#define DECL_ABSENCE(d) __extension__					\
921132718Skan(({ struct decl *const _decl = (d);					\
922117395Skan     if (_decl->mode != dm_absence)					\
923117395Skan       decl_mode_check_failed (_decl->mode, "dm_absence",		\
924117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
925117395Skan     &(_decl)->decl.absence; }))
926117395Skan
927117395Skan#define DECL_RESERV(d) __extension__					\
928117395Skan(({ struct decl *const _decl = (d);					\
929117395Skan     if (_decl->mode != dm_reserv)					\
930117395Skan       decl_mode_check_failed (_decl->mode, "dm_reserv",		\
931117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
932117395Skan     &(_decl)->decl.reserv; }))
933117395Skan
934117395Skan#define DECL_INSN_RESERV(d) __extension__				\
935132718Skan(({ struct decl *const _decl = (d);					\
936117395Skan     if (_decl->mode != dm_insn_reserv)					\
937117395Skan       decl_mode_check_failed (_decl->mode, "dm_insn_reserv",		\
938117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
939117395Skan     &(_decl)->decl.insn_reserv; }))
940117395Skan
941132718Skanstatic const char *decl_name (enum decl_mode);
942132718Skanstatic void decl_mode_check_failed (enum decl_mode, const char *,
943169689Skan				    const char *, int, const char *)
944169689Skan     ATTRIBUTE_NORETURN;
945117395Skan
946117395Skan/* Return string representation of declaration mode MODE.  */
947117395Skanstatic const char *
948132718Skandecl_name (enum decl_mode mode)
949117395Skan{
950117395Skan  static char str [100];
951117395Skan
952117395Skan  if (mode == dm_unit)
953117395Skan    return "dm_unit";
954117395Skan  else if (mode == dm_bypass)
955117395Skan    return "dm_bypass";
956117395Skan  else if (mode == dm_automaton)
957117395Skan    return "dm_automaton";
958117395Skan  else if (mode == dm_excl)
959117395Skan    return "dm_excl";
960117395Skan  else if (mode == dm_presence)
961117395Skan    return "dm_presence";
962117395Skan  else if (mode == dm_absence)
963117395Skan    return "dm_absence";
964117395Skan  else if (mode == dm_reserv)
965117395Skan    return "dm_reserv";
966117395Skan  else if (mode == dm_insn_reserv)
967117395Skan    return "dm_insn_reserv";
968117395Skan  else
969117395Skan    sprintf (str, "unknown (%d)", (int) mode);
970117395Skan  return str;
971117395Skan}
972117395Skan
973117395Skan/* The function prints message about unexpected declaration and finish
974117395Skan   the program.  */
975117395Skanstatic void
976132718Skandecl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
977132718Skan			const char *file, int line, const char *func)
978117395Skan{
979117395Skan  fprintf
980117395Skan    (stderr,
981117395Skan     "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
982117395Skan     file, line, func, expected_mode_str, decl_name (mode));
983117395Skan  exit (1);
984117395Skan}
985117395Skan
986117395Skan
987117395Skan#define REGEXP_UNIT(r) __extension__					\
988117395Skan(({ struct regexp *const _regexp = (r);					\
989117395Skan     if (_regexp->mode != rm_unit)					\
990117395Skan       regexp_mode_check_failed (_regexp->mode, "rm_unit",		\
991117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
992117395Skan     &(_regexp)->regexp.unit; }))
993117395Skan
994117395Skan#define REGEXP_RESERV(r) __extension__					\
995117395Skan(({ struct regexp *const _regexp = (r);					\
996117395Skan     if (_regexp->mode != rm_reserv)					\
997117395Skan       regexp_mode_check_failed (_regexp->mode, "rm_reserv",		\
998117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
999117395Skan     &(_regexp)->regexp.reserv; }))
1000117395Skan
1001117395Skan#define REGEXP_SEQUENCE(r) __extension__				\
1002117395Skan(({ struct regexp *const _regexp = (r);					\
1003117395Skan     if (_regexp->mode != rm_sequence)					\
1004117395Skan       regexp_mode_check_failed (_regexp->mode, "rm_sequence",		\
1005117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
1006117395Skan     &(_regexp)->regexp.sequence; }))
1007117395Skan
1008117395Skan#define REGEXP_REPEAT(r) __extension__					\
1009117395Skan(({ struct regexp *const _regexp = (r);					\
1010117395Skan     if (_regexp->mode != rm_repeat)					\
1011117395Skan       regexp_mode_check_failed (_regexp->mode, "rm_repeat",		\
1012117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
1013117395Skan     &(_regexp)->regexp.repeat; }))
1014117395Skan
1015117395Skan#define REGEXP_ALLOF(r) __extension__					\
1016117395Skan(({ struct regexp *const _regexp = (r);					\
1017117395Skan     if (_regexp->mode != rm_allof)					\
1018117395Skan       regexp_mode_check_failed (_regexp->mode, "rm_allof",		\
1019117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
1020117395Skan     &(_regexp)->regexp.allof; }))
1021117395Skan
1022117395Skan#define REGEXP_ONEOF(r) __extension__					\
1023117395Skan(({ struct regexp *const _regexp = (r);					\
1024117395Skan     if (_regexp->mode != rm_oneof)					\
1025117395Skan       regexp_mode_check_failed (_regexp->mode, "rm_oneof",		\
1026117395Skan			       __FILE__, __LINE__, __FUNCTION__);	\
1027117395Skan     &(_regexp)->regexp.oneof; }))
1028117395Skan
1029132718Skanstatic const char *regexp_name (enum regexp_mode);
1030132718Skanstatic void regexp_mode_check_failed (enum regexp_mode, const char *,
1031132718Skan				      const char *, int,
1032169689Skan				      const char *) ATTRIBUTE_NORETURN;
1033117395Skan
1034117395Skan
1035117395Skan/* Return string representation of regexp mode MODE.  */
1036117395Skanstatic const char *
1037132718Skanregexp_name (enum regexp_mode mode)
1038117395Skan{
1039169689Skan  switch (mode)
1040169689Skan    {
1041169689Skan    case rm_unit:
1042169689Skan      return "rm_unit";
1043169689Skan    case rm_reserv:
1044169689Skan      return "rm_reserv";
1045169689Skan    case rm_nothing:
1046169689Skan      return "rm_nothing";
1047169689Skan    case rm_sequence:
1048169689Skan      return "rm_sequence";
1049169689Skan    case rm_repeat:
1050169689Skan      return "rm_repeat";
1051169689Skan    case rm_allof:
1052169689Skan      return "rm_allof";
1053169689Skan    case rm_oneof:
1054169689Skan      return "rm_oneof";
1055169689Skan    default:
1056169689Skan      gcc_unreachable ();
1057169689Skan    }
1058117395Skan}
1059117395Skan
1060117395Skan/* The function prints message about unexpected regexp and finish the
1061117395Skan   program.  */
1062117395Skanstatic void
1063132718Skanregexp_mode_check_failed (enum regexp_mode mode,
1064132718Skan			  const char *expected_mode_str,
1065132718Skan			  const char *file, int line, const char *func)
1066117395Skan{
1067117395Skan  fprintf
1068117395Skan    (stderr,
1069117395Skan     "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1070117395Skan     file, line, func, expected_mode_str, regexp_name (mode));
1071117395Skan  exit (1);
1072117395Skan}
1073117395Skan
1074117395Skan#else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1075117395Skan
1076117395Skan#define DECL_UNIT(d) (&(d)->decl.unit)
1077117395Skan#define DECL_BYPASS(d) (&(d)->decl.bypass)
1078117395Skan#define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1079117395Skan#define DECL_EXCL(d) (&(d)->decl.excl)
1080117395Skan#define DECL_PRESENCE(d) (&(d)->decl.presence)
1081117395Skan#define DECL_ABSENCE(d) (&(d)->decl.absence)
1082117395Skan#define DECL_RESERV(d) (&(d)->decl.reserv)
1083117395Skan#define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1084117395Skan
1085117395Skan#define REGEXP_UNIT(r) (&(r)->regexp.unit)
1086117395Skan#define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1087117395Skan#define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1088117395Skan#define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1089117395Skan#define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1090117395Skan#define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1091117395Skan
1092117395Skan#endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1093117395Skan
1094117395Skan/* Create IR structure (node).  */
1095117395Skanstatic void *
1096132718Skancreate_node (size_t size)
1097117395Skan{
1098117395Skan  void *result;
1099117395Skan
1100117395Skan  obstack_blank (&irp, size);
1101117395Skan  result = obstack_base (&irp);
1102222097Sbenl  (void) obstack_finish (&irp);
1103117395Skan  /* Default values of members are NULL and zero.  */
1104117395Skan  memset (result, 0, size);
1105117395Skan  return result;
1106117395Skan}
1107117395Skan
1108117395Skan/* Copy IR structure (node).  */
1109117395Skanstatic void *
1110132718Skancopy_node (const void *from, size_t size)
1111117395Skan{
1112117395Skan  void *const result = create_node (size);
1113117395Skan  memcpy (result, from, size);
1114117395Skan  return result;
1115117395Skan}
1116117395Skan
1117117395Skan/* The function checks that NAME does not contain quotes (`"').  */
1118169689Skanstatic const char *
1119169689Skancheck_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1120117395Skan{
1121117395Skan  const char *str;
1122117395Skan
1123117395Skan  for (str = name; *str != '\0'; str++)
1124117395Skan    if (*str == '\"')
1125117395Skan      error ("Name `%s' contains quotes", name);
1126117395Skan  return name;
1127117395Skan}
1128117395Skan
1129132718Skan/* Pointers to all declarations during IR generation are stored in the
1130117395Skan   following.  */
1131169689Skanstatic VEC(decl_t,heap) *decls;
1132117395Skan
1133117395Skan/* Given a pointer to a (char *) and a separator, return an alloc'ed
1134117395Skan   string containing the next separated element, taking parentheses
1135117395Skan   into account if PAR_FLAG has nonzero value.  Advance the pointer to
1136117395Skan   after the string scanned, or the end-of-string.  Return NULL if at
1137117395Skan   end of string.  */
1138117395Skanstatic char *
1139169689Skannext_sep_el (const char **pstr, int sep, int par_flag)
1140117395Skan{
1141117395Skan  char *out_str;
1142169689Skan  const char *p;
1143117395Skan  int pars_num;
1144117395Skan  int n_spaces;
1145117395Skan
1146117395Skan  /* Remove leading whitespaces.  */
1147117395Skan  while (ISSPACE ((int) **pstr))
1148117395Skan    (*pstr)++;
1149117395Skan
1150117395Skan  if (**pstr == '\0')
1151117395Skan    return NULL;
1152117395Skan
1153117395Skan  n_spaces = 0;
1154117395Skan  for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1155117395Skan    {
1156117395Skan      if (par_flag && *p == '(')
1157117395Skan	pars_num++;
1158117395Skan      else if (par_flag && *p == ')')
1159117395Skan	pars_num--;
1160117395Skan      else if (pars_num == 0 && *p == sep)
1161117395Skan	break;
1162117395Skan      if (pars_num == 0 && ISSPACE ((int) *p))
1163117395Skan	n_spaces++;
1164117395Skan      else
1165117395Skan	{
1166117395Skan	  for (; n_spaces != 0; n_spaces--)
1167117395Skan	    obstack_1grow (&irp, p [-n_spaces]);
1168117395Skan	  obstack_1grow (&irp, *p);
1169117395Skan	}
1170117395Skan    }
1171117395Skan  obstack_1grow (&irp, '\0');
1172117395Skan  out_str = obstack_base (&irp);
1173222097Sbenl  (void) obstack_finish (&irp);
1174117395Skan
1175117395Skan  *pstr = p;
1176117395Skan  if (**pstr == sep)
1177117395Skan    (*pstr)++;
1178117395Skan
1179117395Skan  return out_str;
1180117395Skan}
1181117395Skan
1182117395Skan/* Given a string and a separator, return the number of separated
1183117395Skan   elements in it, taking parentheses into account if PAR_FLAG has
1184132718Skan   nonzero value.  Return 0 for the null string, -1 if parentheses is
1185117395Skan   not balanced.  */
1186117395Skanstatic int
1187169689Skann_sep_els (const char *s, int sep, int par_flag)
1188117395Skan{
1189117395Skan  int n;
1190117395Skan  int pars_num;
1191117395Skan
1192117395Skan  if (*s == '\0')
1193117395Skan    return 0;
1194117395Skan
1195117395Skan  for (pars_num = 0, n = 1; *s; s++)
1196117395Skan    if (par_flag && *s == '(')
1197117395Skan      pars_num++;
1198117395Skan    else if (par_flag && *s == ')')
1199117395Skan      pars_num--;
1200117395Skan    else if (pars_num == 0 && *s == sep)
1201117395Skan      n++;
1202117395Skan
1203117395Skan  return (pars_num != 0 ? -1 : n);
1204117395Skan}
1205117395Skan
1206117395Skan/* Given a string and a separator, return vector of strings which are
1207117395Skan   elements in the string and number of elements through els_num.
1208132718Skan   Take parentheses into account if PAREN_P has nonzero value.  The
1209132718Skan   function also inserts the end marker NULL at the end of vector.
1210132718Skan   Return 0 for the null string, -1 if parentheses are not balanced.  */
1211117395Skanstatic char **
1212169689Skanget_str_vect (const char *str, int *els_num, int sep, int paren_p)
1213117395Skan{
1214117395Skan  int i;
1215117395Skan  char **vect;
1216169689Skan  const char **pstr;
1217169689Skan  char *trail;
1218117395Skan
1219132718Skan  *els_num = n_sep_els (str, sep, paren_p);
1220117395Skan  if (*els_num <= 0)
1221117395Skan    return NULL;
1222132718Skan  obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1223117395Skan  vect = (char **) obstack_base (&irp);
1224222097Sbenl  (void) obstack_finish (&irp);
1225117395Skan  pstr = &str;
1226117395Skan  for (i = 0; i < *els_num; i++)
1227132718Skan    vect [i] = next_sep_el (pstr, sep, paren_p);
1228169689Skan  trail = next_sep_el (pstr, sep, paren_p);
1229169689Skan  gcc_assert (!trail);
1230132718Skan  vect [i] = NULL;
1231117395Skan  return vect;
1232117395Skan}
1233117395Skan
1234132718Skan/* Process a DEFINE_CPU_UNIT.
1235117395Skan
1236117395Skan   This gives information about a unit contained in CPU.  We fill a
1237117395Skan   struct unit_decl with information used later by `expand_automata'.  */
1238169689Skanstatic void
1239132718Skangen_cpu_unit (rtx def)
1240117395Skan{
1241117395Skan  decl_t decl;
1242117395Skan  char **str_cpu_units;
1243117395Skan  int vect_length;
1244117395Skan  int i;
1245117395Skan
1246169689Skan  str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1247117395Skan  if (str_cpu_units == NULL)
1248117395Skan    fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1249117395Skan  for (i = 0; i < vect_length; i++)
1250117395Skan    {
1251117395Skan      decl = create_node (sizeof (struct decl));
1252117395Skan      decl->mode = dm_unit;
1253117395Skan      decl->pos = 0;
1254117395Skan      DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1255169689Skan      DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1256117395Skan      DECL_UNIT (decl)->query_p = 0;
1257132718Skan      DECL_UNIT (decl)->min_occ_cycle_num = -1;
1258132718Skan      DECL_UNIT (decl)->in_set_p = 0;
1259169689Skan      VEC_safe_push (decl_t,heap, decls, decl);
1260117395Skan    }
1261117395Skan}
1262117395Skan
1263132718Skan/* Process a DEFINE_QUERY_CPU_UNIT.
1264117395Skan
1265117395Skan   This gives information about a unit contained in CPU.  We fill a
1266117395Skan   struct unit_decl with information used later by `expand_automata'.  */
1267169689Skanstatic void
1268132718Skangen_query_cpu_unit (rtx def)
1269117395Skan{
1270117395Skan  decl_t decl;
1271117395Skan  char **str_cpu_units;
1272117395Skan  int vect_length;
1273117395Skan  int i;
1274117395Skan
1275169689Skan  str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1276132718Skan				FALSE);
1277117395Skan  if (str_cpu_units == NULL)
1278117395Skan    fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1279117395Skan  for (i = 0; i < vect_length; i++)
1280117395Skan    {
1281117395Skan      decl = create_node (sizeof (struct decl));
1282117395Skan      decl->mode = dm_unit;
1283117395Skan      decl->pos = 0;
1284117395Skan      DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1285169689Skan      DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1286117395Skan      DECL_UNIT (decl)->query_p = 1;
1287169689Skan      VEC_safe_push (decl_t,heap, decls, decl);
1288117395Skan    }
1289117395Skan}
1290117395Skan
1291132718Skan/* Process a DEFINE_BYPASS.
1292117395Skan
1293117395Skan   This gives information about a unit contained in the CPU.  We fill
1294117395Skan   in a struct bypass_decl with information used later by
1295117395Skan   `expand_automata'.  */
1296169689Skanstatic void
1297132718Skangen_bypass (rtx def)
1298117395Skan{
1299117395Skan  decl_t decl;
1300117395Skan  char **out_insns;
1301117395Skan  int out_length;
1302117395Skan  char **in_insns;
1303117395Skan  int in_length;
1304117395Skan  int i, j;
1305117395Skan
1306169689Skan  out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1307117395Skan  if (out_insns == NULL)
1308117395Skan    fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1309169689Skan  in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1310117395Skan  if (in_insns == NULL)
1311117395Skan    fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1312117395Skan  for (i = 0; i < out_length; i++)
1313117395Skan    for (j = 0; j < in_length; j++)
1314117395Skan      {
1315117395Skan	decl = create_node (sizeof (struct decl));
1316117395Skan	decl->mode = dm_bypass;
1317117395Skan	decl->pos = 0;
1318117395Skan	DECL_BYPASS (decl)->latency = XINT (def, 0);
1319117395Skan	DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1320117395Skan	DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1321169689Skan	DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1322169689Skan	VEC_safe_push (decl_t,heap, decls, decl);
1323117395Skan      }
1324117395Skan}
1325117395Skan
1326132718Skan/* Process an EXCLUSION_SET.
1327117395Skan
1328117395Skan   This gives information about a cpu unit conflicts.  We fill a
1329132718Skan   struct excl_rel_decl (excl) with information used later by
1330117395Skan   `expand_automata'.  */
1331169689Skanstatic void
1332132718Skangen_excl_set (rtx def)
1333117395Skan{
1334117395Skan  decl_t decl;
1335117395Skan  char **first_str_cpu_units;
1336117395Skan  char **second_str_cpu_units;
1337117395Skan  int first_vect_length;
1338117395Skan  int length;
1339117395Skan  int i;
1340117395Skan
1341117395Skan  first_str_cpu_units
1342169689Skan    = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1343117395Skan  if (first_str_cpu_units == NULL)
1344117395Skan    fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1345169689Skan  second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1346132718Skan				       FALSE);
1347117395Skan  if (second_str_cpu_units == NULL)
1348117395Skan    fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1349117395Skan  length += first_vect_length;
1350117395Skan  decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1351117395Skan  decl->mode = dm_excl;
1352117395Skan  decl->pos = 0;
1353132718Skan  DECL_EXCL (decl)->all_names_num = length;
1354117395Skan  DECL_EXCL (decl)->first_list_length = first_vect_length;
1355117395Skan  for (i = 0; i < length; i++)
1356117395Skan    if (i < first_vect_length)
1357117395Skan      DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1358117395Skan    else
1359117395Skan      DECL_EXCL (decl)->names [i]
1360117395Skan	= second_str_cpu_units [i - first_vect_length];
1361169689Skan  VEC_safe_push (decl_t,heap, decls, decl);
1362117395Skan}
1363117395Skan
1364132718Skan/* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1365132718Skan   FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1366117395Skan
1367117395Skan   This gives information about a cpu unit reservation requirements.
1368132718Skan   We fill a struct unit_pattern_rel_decl with information used later
1369132718Skan   by `expand_automata'.  */
1370132718Skanstatic void
1371132718Skangen_presence_absence_set (rtx def, int presence_p, int final_p)
1372117395Skan{
1373117395Skan  decl_t decl;
1374132718Skan  char **str_cpu_units;
1375169689Skan  char **str_pattern_lists;
1376132718Skan  char ***str_patterns;
1377132718Skan  int cpu_units_length;
1378117395Skan  int length;
1379132718Skan  int patterns_length;
1380117395Skan  int i;
1381117395Skan
1382169689Skan  str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1383132718Skan				FALSE);
1384132718Skan  if (str_cpu_units == NULL)
1385132718Skan    fatal ((presence_p
1386132718Skan	    ? (final_p
1387132718Skan	       ? "invalid first string `%s' in final_presence_set"
1388132718Skan	       : "invalid first string `%s' in presence_set")
1389132718Skan	    : (final_p
1390132718Skan	       ? "invalid first string `%s' in final_absence_set"
1391132718Skan	       : "invalid first string `%s' in absence_set")),
1392132718Skan	   XSTR (def, 0));
1393169689Skan  str_pattern_lists = get_str_vect (XSTR (def, 1),
1394169689Skan				    &patterns_length, ',', FALSE);
1395169689Skan  if (str_pattern_lists == NULL)
1396132718Skan    fatal ((presence_p
1397132718Skan	    ? (final_p
1398132718Skan	       ? "invalid second string `%s' in final_presence_set"
1399132718Skan	       : "invalid second string `%s' in presence_set")
1400132718Skan	    : (final_p
1401132718Skan	       ? "invalid second string `%s' in final_absence_set"
1402132718Skan	       : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1403169689Skan  str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
1404132718Skan  for (i = 0; i < patterns_length; i++)
1405132718Skan    {
1406169689Skan      str_patterns [i] = get_str_vect (str_pattern_lists [i],
1407169689Skan				       &length, ' ', FALSE);
1408169689Skan      gcc_assert (str_patterns [i]);
1409132718Skan    }
1410132718Skan  decl = create_node (sizeof (struct decl));
1411117395Skan  decl->pos = 0;
1412132718Skan  if (presence_p)
1413132718Skan    {
1414132718Skan      decl->mode = dm_presence;
1415132718Skan      DECL_PRESENCE (decl)->names_num = cpu_units_length;
1416132718Skan      DECL_PRESENCE (decl)->names = str_cpu_units;
1417132718Skan      DECL_PRESENCE (decl)->patterns = str_patterns;
1418132718Skan      DECL_PRESENCE (decl)->patterns_num = patterns_length;
1419132718Skan      DECL_PRESENCE (decl)->final_p = final_p;
1420132718Skan    }
1421132718Skan  else
1422132718Skan    {
1423132718Skan      decl->mode = dm_absence;
1424132718Skan      DECL_ABSENCE (decl)->names_num = cpu_units_length;
1425132718Skan      DECL_ABSENCE (decl)->names = str_cpu_units;
1426132718Skan      DECL_ABSENCE (decl)->patterns = str_patterns;
1427132718Skan      DECL_ABSENCE (decl)->patterns_num = patterns_length;
1428132718Skan      DECL_ABSENCE (decl)->final_p = final_p;
1429132718Skan    }
1430169689Skan  VEC_safe_push (decl_t,heap, decls, decl);
1431117395Skan}
1432117395Skan
1433132718Skan/* Process a PRESENCE_SET.
1434117395Skan
1435132718Skan    This gives information about a cpu unit reservation requirements.
1436132718Skan   We fill a struct unit_pattern_rel_decl (presence) with information
1437132718Skan   used later by `expand_automata'.  */
1438169689Skanstatic void
1439132718Skangen_presence_set (rtx def)
1440132718Skan{
1441132718Skan  gen_presence_absence_set (def, TRUE, FALSE);
1442132718Skan}
1443132718Skan
1444132718Skan/* Process a FINAL_PRESENCE_SET.
1445132718Skan
1446117395Skan   This gives information about a cpu unit reservation requirements.
1447132718Skan   We fill a struct unit_pattern_rel_decl (presence) with information
1448132718Skan   used later by `expand_automata'.  */
1449169689Skanstatic void
1450132718Skangen_final_presence_set (rtx def)
1451117395Skan{
1452132718Skan  gen_presence_absence_set (def, TRUE, TRUE);
1453132718Skan}
1454117395Skan
1455132718Skan/* Process an ABSENCE_SET.
1456132718Skan
1457132718Skan   This gives information about a cpu unit reservation requirements.
1458132718Skan   We fill a struct unit_pattern_rel_decl (absence) with information
1459132718Skan   used later by `expand_automata'.  */
1460169689Skanstatic void
1461132718Skangen_absence_set (rtx def)
1462132718Skan{
1463132718Skan  gen_presence_absence_set (def, FALSE, FALSE);
1464117395Skan}
1465117395Skan
1466132718Skan/* Process a FINAL_ABSENCE_SET.
1467117395Skan
1468132718Skan   This gives information about a cpu unit reservation requirements.
1469132718Skan   We fill a struct unit_pattern_rel_decl (absence) with information
1470132718Skan   used later by `expand_automata'.  */
1471169689Skanstatic void
1472132718Skangen_final_absence_set (rtx def)
1473132718Skan{
1474132718Skan  gen_presence_absence_set (def, FALSE, TRUE);
1475132718Skan}
1476132718Skan
1477132718Skan/* Process a DEFINE_AUTOMATON.
1478132718Skan
1479117395Skan   This gives information about a finite state automaton used for
1480117395Skan   recognizing pipeline hazards.  We fill a struct automaton_decl
1481117395Skan   with information used later by `expand_automata'.  */
1482169689Skanstatic void
1483132718Skangen_automaton (rtx def)
1484117395Skan{
1485117395Skan  decl_t decl;
1486117395Skan  char **str_automata;
1487117395Skan  int vect_length;
1488117395Skan  int i;
1489117395Skan
1490169689Skan  str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1491117395Skan  if (str_automata == NULL)
1492117395Skan    fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1493117395Skan  for (i = 0; i < vect_length; i++)
1494117395Skan    {
1495117395Skan      decl = create_node (sizeof (struct decl));
1496117395Skan      decl->mode = dm_automaton;
1497117395Skan      decl->pos = 0;
1498117395Skan      DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1499169689Skan      VEC_safe_push (decl_t,heap, decls, decl);
1500117395Skan    }
1501117395Skan}
1502117395Skan
1503132718Skan/* Process an AUTOMATA_OPTION.
1504117395Skan
1505117395Skan   This gives information how to generate finite state automaton used
1506117395Skan   for recognizing pipeline hazards.  */
1507169689Skanstatic void
1508132718Skangen_automata_option (rtx def)
1509117395Skan{
1510132718Skan  if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1511117395Skan    no_minimization_flag = 1;
1512132718Skan  else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1513117395Skan    time_flag = 1;
1514132718Skan  else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1515117395Skan    v_flag = 1;
1516132718Skan  else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1517117395Skan    w_flag = 1;
1518132718Skan  else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1519117395Skan    ndfa_flag = 1;
1520132718Skan  else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1521132718Skan    progress_flag = 1;
1522117395Skan  else
1523117395Skan    fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1524117395Skan}
1525117395Skan
1526117395Skan/* Name in reservation to denote absence reservation.  */
1527117395Skan#define NOTHING_NAME "nothing"
1528117395Skan
1529117395Skan/* The following string contains original reservation string being
1530117395Skan   parsed.  */
1531169689Skanstatic const char *reserv_str;
1532117395Skan
1533117395Skan/* Parse an element in STR.  */
1534117395Skanstatic regexp_t
1535169689Skangen_regexp_el (const char *str)
1536117395Skan{
1537117395Skan  regexp_t regexp;
1538169689Skan  char *dstr;
1539117395Skan  int len;
1540117395Skan
1541117395Skan  if (*str == '(')
1542117395Skan    {
1543117395Skan      len = strlen (str);
1544117395Skan      if (str [len - 1] != ')')
1545117395Skan	fatal ("garbage after ) in reservation `%s'", reserv_str);
1546169689Skan      dstr = alloca (len - 1);
1547169689Skan      memcpy (dstr, str + 1, len - 2);
1548169689Skan      dstr [len-2] = '\0';
1549169689Skan      regexp = gen_regexp_sequence (dstr);
1550117395Skan    }
1551117395Skan  else if (strcmp (str, NOTHING_NAME) == 0)
1552117395Skan    {
1553117395Skan      regexp = create_node (sizeof (struct decl));
1554117395Skan      regexp->mode = rm_nothing;
1555117395Skan    }
1556117395Skan  else
1557117395Skan    {
1558117395Skan      regexp = create_node (sizeof (struct decl));
1559117395Skan      regexp->mode = rm_unit;
1560117395Skan      REGEXP_UNIT (regexp)->name = str;
1561117395Skan    }
1562117395Skan  return regexp;
1563117395Skan}
1564117395Skan
1565117395Skan/* Parse construction `repeat' in STR.  */
1566117395Skanstatic regexp_t
1567169689Skangen_regexp_repeat (const char *str)
1568117395Skan{
1569117395Skan  regexp_t regexp;
1570117395Skan  regexp_t repeat;
1571117395Skan  char **repeat_vect;
1572117395Skan  int els_num;
1573117395Skan  int i;
1574117395Skan
1575132718Skan  repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1576117395Skan  if (repeat_vect == NULL)
1577117395Skan    fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1578117395Skan  if (els_num > 1)
1579117395Skan    {
1580117395Skan      regexp = gen_regexp_el (repeat_vect [0]);
1581117395Skan      for (i = 1; i < els_num; i++)
1582117395Skan	{
1583117395Skan	  repeat = create_node (sizeof (struct regexp));
1584117395Skan	  repeat->mode = rm_repeat;
1585117395Skan	  REGEXP_REPEAT (repeat)->regexp = regexp;
1586117395Skan	  REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1587117395Skan          if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1588117395Skan            fatal ("repetition `%s' <= 1 in reservation `%s'",
1589117395Skan                   str, reserv_str);
1590117395Skan          regexp = repeat;
1591117395Skan	}
1592117395Skan      return regexp;
1593117395Skan    }
1594117395Skan  else
1595117395Skan    return gen_regexp_el (str);
1596117395Skan}
1597117395Skan
1598117395Skan/* Parse reservation STR which possibly contains separator '+'.  */
1599117395Skanstatic regexp_t
1600169689Skangen_regexp_allof (const char *str)
1601117395Skan{
1602117395Skan  regexp_t allof;
1603117395Skan  char **allof_vect;
1604117395Skan  int els_num;
1605117395Skan  int i;
1606117395Skan
1607132718Skan  allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1608117395Skan  if (allof_vect == NULL)
1609117395Skan    fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1610117395Skan  if (els_num > 1)
1611117395Skan    {
1612117395Skan      allof = create_node (sizeof (struct regexp)
1613117395Skan			   + sizeof (regexp_t) * (els_num - 1));
1614117395Skan      allof->mode = rm_allof;
1615117395Skan      REGEXP_ALLOF (allof)->regexps_num = els_num;
1616117395Skan      for (i = 0; i < els_num; i++)
1617117395Skan	REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1618117395Skan      return allof;
1619117395Skan    }
1620117395Skan  else
1621117395Skan    return gen_regexp_repeat (str);
1622117395Skan}
1623117395Skan
1624117395Skan/* Parse reservation STR which possibly contains separator '|'.  */
1625117395Skanstatic regexp_t
1626169689Skangen_regexp_oneof (const char *str)
1627117395Skan{
1628117395Skan  regexp_t oneof;
1629117395Skan  char **oneof_vect;
1630117395Skan  int els_num;
1631117395Skan  int i;
1632117395Skan
1633132718Skan  oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1634117395Skan  if (oneof_vect == NULL)
1635117395Skan    fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1636117395Skan  if (els_num > 1)
1637117395Skan    {
1638117395Skan      oneof = create_node (sizeof (struct regexp)
1639117395Skan			   + sizeof (regexp_t) * (els_num - 1));
1640117395Skan      oneof->mode = rm_oneof;
1641117395Skan      REGEXP_ONEOF (oneof)->regexps_num = els_num;
1642117395Skan      for (i = 0; i < els_num; i++)
1643117395Skan	REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1644117395Skan      return oneof;
1645117395Skan    }
1646117395Skan  else
1647117395Skan    return gen_regexp_allof (str);
1648117395Skan}
1649117395Skan
1650117395Skan/* Parse reservation STR which possibly contains separator ','.  */
1651117395Skanstatic regexp_t
1652169689Skangen_regexp_sequence (const char *str)
1653117395Skan{
1654117395Skan  regexp_t sequence;
1655117395Skan  char **sequence_vect;
1656117395Skan  int els_num;
1657117395Skan  int i;
1658117395Skan
1659132718Skan  sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1660117395Skan  if (els_num > 1)
1661117395Skan    {
1662117395Skan      sequence = create_node (sizeof (struct regexp)
1663117395Skan			      + sizeof (regexp_t) * (els_num - 1));
1664117395Skan      sequence->mode = rm_sequence;
1665117395Skan      REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1666117395Skan      for (i = 0; i < els_num; i++)
1667117395Skan	REGEXP_SEQUENCE (sequence)->regexps [i]
1668117395Skan          = gen_regexp_oneof (sequence_vect [i]);
1669117395Skan      return sequence;
1670117395Skan    }
1671117395Skan  else
1672117395Skan    return gen_regexp_oneof (str);
1673117395Skan}
1674117395Skan
1675117395Skan/* Parse construction reservation STR.  */
1676117395Skanstatic regexp_t
1677169689Skangen_regexp (const char *str)
1678117395Skan{
1679117395Skan  reserv_str = str;
1680117395Skan  return gen_regexp_sequence (str);;
1681117395Skan}
1682117395Skan
1683117395Skan/* Process a DEFINE_RESERVATION.
1684117395Skan
1685117395Skan   This gives information about a reservation of cpu units.  We fill
1686117395Skan   in a struct reserv_decl with information used later by
1687117395Skan   `expand_automata'.  */
1688169689Skanstatic void
1689132718Skangen_reserv (rtx def)
1690117395Skan{
1691117395Skan  decl_t decl;
1692117395Skan
1693117395Skan  decl = create_node (sizeof (struct decl));
1694117395Skan  decl->mode = dm_reserv;
1695117395Skan  decl->pos = 0;
1696169689Skan  DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1697169689Skan  DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1698169689Skan  VEC_safe_push (decl_t,heap, decls, decl);
1699117395Skan}
1700117395Skan
1701117395Skan/* Process a DEFINE_INSN_RESERVATION.
1702117395Skan
1703117395Skan   This gives information about the reservation of cpu units by an
1704117395Skan   insn.  We fill a struct insn_reserv_decl with information used
1705117395Skan   later by `expand_automata'.  */
1706169689Skanstatic void
1707132718Skangen_insn_reserv (rtx def)
1708117395Skan{
1709117395Skan  decl_t decl;
1710117395Skan
1711117395Skan  decl = create_node (sizeof (struct decl));
1712117395Skan  decl->mode = dm_insn_reserv;
1713117395Skan  decl->pos = 0;
1714117395Skan  DECL_INSN_RESERV (decl)->name
1715169689Skan    = check_name (XSTR (def, 0), decl->pos);
1716117395Skan  DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1717117395Skan  DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1718169689Skan  DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1719169689Skan  VEC_safe_push (decl_t,heap, decls, decl);
1720117395Skan}
1721117395Skan
1722117395Skan
1723117395Skan
1724117395Skan/* The function evaluates hash value (0..UINT_MAX) of string.  */
1725117395Skanstatic unsigned
1726132718Skanstring_hash (const char *string)
1727117395Skan{
1728117395Skan  unsigned result, i;
1729117395Skan
1730117395Skan  for (result = i = 0;*string++ != '\0'; i++)
1731117395Skan    result += ((unsigned char) *string << (i % CHAR_BIT));
1732117395Skan  return result;
1733117395Skan}
1734117395Skan
1735117395Skan
1736117395Skan
1737117395Skan/* This page contains abstract data `table of automaton declarations'.
1738117395Skan   Elements of the table is nodes representing automaton declarations.
1739132718Skan   Key of the table elements is name of given automaton.  Remember
1740117395Skan   that automaton names have own space.  */
1741117395Skan
1742117395Skan/* The function evaluates hash value of an automaton declaration.  The
1743117395Skan   function is used by abstract data `hashtab'.  The function returns
1744117395Skan   hash value (0..UINT_MAX) of given automaton declaration.  */
1745117395Skanstatic hashval_t
1746132718Skanautomaton_decl_hash (const void *automaton_decl)
1747117395Skan{
1748117395Skan  const decl_t decl = (decl_t) automaton_decl;
1749117395Skan
1750169689Skan  gcc_assert (decl->mode != dm_automaton
1751169689Skan	      || DECL_AUTOMATON (decl)->name);
1752117395Skan  return string_hash (DECL_AUTOMATON (decl)->name);
1753117395Skan}
1754117395Skan
1755117395Skan/* The function tests automaton declarations on equality of their
1756117395Skan   keys.  The function is used by abstract data `hashtab'.  The
1757117395Skan   function returns 1 if the declarations have the same key, 0
1758117395Skan   otherwise.  */
1759117395Skanstatic int
1760132718Skanautomaton_decl_eq_p (const void* automaton_decl_1,
1761132718Skan		     const void* automaton_decl_2)
1762117395Skan{
1763117395Skan  const decl_t decl1 = (decl_t) automaton_decl_1;
1764117395Skan  const decl_t decl2 = (decl_t) automaton_decl_2;
1765117395Skan
1766169689Skan  gcc_assert (decl1->mode == dm_automaton
1767169689Skan	      && DECL_AUTOMATON (decl1)->name
1768169689Skan	      && decl2->mode == dm_automaton
1769169689Skan	      && DECL_AUTOMATON (decl2)->name);
1770117395Skan  return strcmp (DECL_AUTOMATON (decl1)->name,
1771117395Skan		 DECL_AUTOMATON (decl2)->name) == 0;
1772117395Skan}
1773117395Skan
1774117395Skan/* The automaton declaration table itself is represented by the
1775117395Skan   following variable.  */
1776117395Skanstatic htab_t automaton_decl_table;
1777117395Skan
1778117395Skan/* The function inserts automaton declaration into the table.  The
1779117395Skan   function does nothing if an automaton declaration with the same key
1780117395Skan   exists already in the table.  The function returns automaton
1781117395Skan   declaration node in the table with the same key as given automaton
1782117395Skan   declaration node.  */
1783117395Skanstatic decl_t
1784132718Skaninsert_automaton_decl (decl_t automaton_decl)
1785117395Skan{
1786117395Skan  void **entry_ptr;
1787117395Skan
1788117395Skan  entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1789117395Skan  if (*entry_ptr == NULL)
1790117395Skan    *entry_ptr = (void *) automaton_decl;
1791117395Skan  return (decl_t) *entry_ptr;
1792117395Skan}
1793117395Skan
1794117395Skan/* The following variable value is node representing automaton
1795117395Skan   declaration.  The node used for searching automaton declaration
1796117395Skan   with given name.  */
1797117395Skanstatic struct decl work_automaton_decl;
1798117395Skan
1799117395Skan/* The function searches for automaton declaration in the table with
1800117395Skan   the same key as node representing name of the automaton
1801117395Skan   declaration.  The function returns node found in the table, NULL if
1802117395Skan   such node does not exist in the table.  */
1803117395Skanstatic decl_t
1804169689Skanfind_automaton_decl (const char *name)
1805117395Skan{
1806117395Skan  void *entry;
1807117395Skan
1808117395Skan  work_automaton_decl.mode = dm_automaton;
1809117395Skan  DECL_AUTOMATON (&work_automaton_decl)->name = name;
1810117395Skan  entry = htab_find (automaton_decl_table, &work_automaton_decl);
1811117395Skan  return (decl_t) entry;
1812117395Skan}
1813117395Skan
1814117395Skan/* The function creates empty automaton declaration table and node
1815117395Skan   representing automaton declaration and used for searching automaton
1816117395Skan   declaration with given name.  The function must be called only once
1817117395Skan   before any work with the automaton declaration table.  */
1818117395Skanstatic void
1819132718Skaninitiate_automaton_decl_table (void)
1820117395Skan{
1821117395Skan  work_automaton_decl.mode = dm_automaton;
1822117395Skan  automaton_decl_table = htab_create (10, automaton_decl_hash,
1823117395Skan				      automaton_decl_eq_p, (htab_del) 0);
1824117395Skan}
1825117395Skan
1826117395Skan/* The function deletes the automaton declaration table.  Only call of
1827117395Skan   function `initiate_automaton_decl_table' is possible immediately
1828117395Skan   after this function call.  */
1829117395Skanstatic void
1830132718Skanfinish_automaton_decl_table (void)
1831117395Skan{
1832117395Skan  htab_delete (automaton_decl_table);
1833117395Skan}
1834117395Skan
1835117395Skan
1836117395Skan
1837117395Skan/* This page contains abstract data `table of insn declarations'.
1838117395Skan   Elements of the table is nodes representing insn declarations.  Key
1839117395Skan   of the table elements is name of given insn (in corresponding
1840132718Skan   define_insn_reservation).  Remember that insn names have own
1841117395Skan   space.  */
1842117395Skan
1843117395Skan/* The function evaluates hash value of an insn declaration.  The
1844117395Skan   function is used by abstract data `hashtab'.  The function returns
1845117395Skan   hash value (0..UINT_MAX) of given insn declaration.  */
1846117395Skanstatic hashval_t
1847132718Skaninsn_decl_hash (const void *insn_decl)
1848117395Skan{
1849117395Skan  const decl_t decl = (decl_t) insn_decl;
1850117395Skan
1851169689Skan  gcc_assert (decl->mode == dm_insn_reserv
1852169689Skan	      && DECL_INSN_RESERV (decl)->name);
1853117395Skan  return string_hash (DECL_INSN_RESERV (decl)->name);
1854117395Skan}
1855117395Skan
1856117395Skan/* The function tests insn declarations on equality of their keys.
1857117395Skan   The function is used by abstract data `hashtab'.  The function
1858117395Skan   returns 1 if declarations have the same key, 0 otherwise.  */
1859117395Skanstatic int
1860132718Skaninsn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1861117395Skan{
1862117395Skan  const decl_t decl1 = (decl_t) insn_decl_1;
1863117395Skan  const decl_t decl2 = (decl_t) insn_decl_2;
1864117395Skan
1865169689Skan  gcc_assert (decl1->mode == dm_insn_reserv
1866169689Skan	      && DECL_INSN_RESERV (decl1)->name
1867169689Skan	      && decl2->mode == dm_insn_reserv
1868169689Skan	      && DECL_INSN_RESERV (decl2)->name);
1869117395Skan  return strcmp (DECL_INSN_RESERV (decl1)->name,
1870117395Skan                 DECL_INSN_RESERV (decl2)->name) == 0;
1871117395Skan}
1872117395Skan
1873117395Skan/* The insn declaration table itself is represented by the following
1874117395Skan   variable.  The table does not contain insn reservation
1875117395Skan   declarations.  */
1876117395Skanstatic htab_t insn_decl_table;
1877117395Skan
1878117395Skan/* The function inserts insn declaration into the table.  The function
1879117395Skan   does nothing if an insn declaration with the same key exists
1880117395Skan   already in the table.  The function returns insn declaration node
1881117395Skan   in the table with the same key as given insn declaration node.  */
1882117395Skanstatic decl_t
1883132718Skaninsert_insn_decl (decl_t insn_decl)
1884117395Skan{
1885117395Skan  void **entry_ptr;
1886117395Skan
1887117395Skan  entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1888117395Skan  if (*entry_ptr == NULL)
1889117395Skan    *entry_ptr = (void *) insn_decl;
1890117395Skan  return (decl_t) *entry_ptr;
1891117395Skan}
1892117395Skan
1893117395Skan/* The following variable value is node representing insn reservation
1894117395Skan   declaration.  The node used for searching insn reservation
1895117395Skan   declaration with given name.  */
1896117395Skanstatic struct decl work_insn_decl;
1897117395Skan
1898117395Skan/* The function searches for insn reservation declaration in the table
1899117395Skan   with the same key as node representing name of the insn reservation
1900117395Skan   declaration.  The function returns node found in the table, NULL if
1901117395Skan   such node does not exist in the table.  */
1902117395Skanstatic decl_t
1903169689Skanfind_insn_decl (const char *name)
1904117395Skan{
1905117395Skan  void *entry;
1906117395Skan
1907117395Skan  work_insn_decl.mode = dm_insn_reserv;
1908117395Skan  DECL_INSN_RESERV (&work_insn_decl)->name = name;
1909117395Skan  entry = htab_find (insn_decl_table, &work_insn_decl);
1910117395Skan  return (decl_t) entry;
1911117395Skan}
1912117395Skan
1913117395Skan/* The function creates empty insn declaration table and node
1914117395Skan   representing insn declaration and used for searching insn
1915117395Skan   declaration with given name.  The function must be called only once
1916117395Skan   before any work with the insn declaration table.  */
1917117395Skanstatic void
1918132718Skaninitiate_insn_decl_table (void)
1919117395Skan{
1920117395Skan  work_insn_decl.mode = dm_insn_reserv;
1921117395Skan  insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1922117395Skan				 (htab_del) 0);
1923117395Skan}
1924117395Skan
1925117395Skan/* The function deletes the insn declaration table.  Only call of
1926117395Skan   function `initiate_insn_decl_table' is possible immediately after
1927117395Skan   this function call.  */
1928117395Skanstatic void
1929132718Skanfinish_insn_decl_table (void)
1930117395Skan{
1931117395Skan  htab_delete (insn_decl_table);
1932117395Skan}
1933117395Skan
1934117395Skan
1935117395Skan
1936117395Skan/* This page contains abstract data `table of declarations'.  Elements
1937117395Skan   of the table is nodes representing declarations (of units and
1938117395Skan   reservations).  Key of the table elements is names of given
1939117395Skan   declarations.  */
1940117395Skan
1941117395Skan/* The function evaluates hash value of a declaration.  The function
1942117395Skan   is used by abstract data `hashtab'.  The function returns hash
1943117395Skan   value (0..UINT_MAX) of given declaration.  */
1944117395Skanstatic hashval_t
1945132718Skandecl_hash (const void *decl)
1946117395Skan{
1947117395Skan  const decl_t d = (const decl_t) decl;
1948117395Skan
1949169689Skan  gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1950169689Skan	      || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1951117395Skan  return string_hash (d->mode == dm_unit
1952117395Skan		      ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1953117395Skan}
1954117395Skan
1955117395Skan/* The function tests declarations on equality of their keys.  The
1956169689Skan   function is used by abstract data 'hashtab'.  The function
1957117395Skan   returns 1 if the declarations have the same key, 0 otherwise.  */
1958117395Skanstatic int
1959132718Skandecl_eq_p (const void *decl_1, const void *decl_2)
1960117395Skan{
1961117395Skan  const decl_t d1 = (const decl_t) decl_1;
1962117395Skan  const decl_t d2 = (const decl_t) decl_2;
1963117395Skan
1964169689Skan  gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1965169689Skan	      || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1966169689Skan  gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1967169689Skan	      || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1968117395Skan  return strcmp ((d1->mode == dm_unit
1969117395Skan                  ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1970117395Skan                 (d2->mode == dm_unit
1971117395Skan                  ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1972117395Skan}
1973117395Skan
1974117395Skan/* The declaration table itself is represented by the following
1975117395Skan   variable.  */
1976117395Skanstatic htab_t decl_table;
1977117395Skan
1978117395Skan/* The function inserts declaration into the table.  The function does
1979117395Skan   nothing if a declaration with the same key exists already in the
1980117395Skan   table.  The function returns declaration node in the table with the
1981117395Skan   same key as given declaration node.  */
1982117395Skan
1983117395Skanstatic decl_t
1984132718Skaninsert_decl (decl_t decl)
1985117395Skan{
1986117395Skan  void **entry_ptr;
1987117395Skan
1988117395Skan  entry_ptr = htab_find_slot (decl_table, decl, 1);
1989117395Skan  if (*entry_ptr == NULL)
1990117395Skan    *entry_ptr = (void *) decl;
1991117395Skan  return (decl_t) *entry_ptr;
1992117395Skan}
1993117395Skan
1994117395Skan/* The following variable value is node representing declaration.  The
1995117395Skan   node used for searching declaration with given name.  */
1996117395Skanstatic struct decl work_decl;
1997117395Skan
1998117395Skan/* The function searches for declaration in the table with the same
1999117395Skan   key as node representing name of the declaration.  The function
2000117395Skan   returns node found in the table, NULL if such node does not exist
2001117395Skan   in the table.  */
2002117395Skanstatic decl_t
2003169689Skanfind_decl (const char *name)
2004117395Skan{
2005117395Skan  void *entry;
2006117395Skan
2007117395Skan  work_decl.mode = dm_unit;
2008117395Skan  DECL_UNIT (&work_decl)->name = name;
2009117395Skan  entry = htab_find (decl_table, &work_decl);
2010117395Skan  return (decl_t) entry;
2011117395Skan}
2012117395Skan
2013117395Skan/* The function creates empty declaration table and node representing
2014117395Skan   declaration and used for searching declaration with given name.
2015117395Skan   The function must be called only once before any work with the
2016117395Skan   declaration table.  */
2017117395Skanstatic void
2018132718Skaninitiate_decl_table (void)
2019117395Skan{
2020117395Skan  work_decl.mode = dm_unit;
2021117395Skan  decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2022117395Skan}
2023117395Skan
2024117395Skan/* The function deletes the declaration table.  Only call of function
2025117395Skan   `initiate_declaration_table' is possible immediately after this
2026117395Skan   function call.  */
2027117395Skanstatic void
2028132718Skanfinish_decl_table (void)
2029117395Skan{
2030117395Skan  htab_delete (decl_table);
2031117395Skan}
2032117395Skan
2033117395Skan
2034117395Skan
2035117395Skan/* This page contains checker of pipeline hazard description.  */
2036117395Skan
2037117395Skan/* Checking NAMES in an exclusion clause vector and returning formed
2038117395Skan   unit_set_el_list.  */
2039117395Skanstatic unit_set_el_t
2040132718Skanprocess_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2041117395Skan{
2042117395Skan  unit_set_el_t el_list;
2043117395Skan  unit_set_el_t last_el;
2044117395Skan  unit_set_el_t new_el;
2045117395Skan  decl_t decl_in_table;
2046117395Skan  int i;
2047117395Skan
2048117395Skan  el_list = NULL;
2049117395Skan  last_el = NULL;
2050117395Skan  for (i = 0; i < num; i++)
2051117395Skan    {
2052117395Skan      decl_in_table = find_decl (names [i]);
2053117395Skan      if (decl_in_table == NULL)
2054117395Skan	error ("unit `%s' in exclusion is not declared", names [i]);
2055117395Skan      else if (decl_in_table->mode != dm_unit)
2056117395Skan	error ("`%s' in exclusion is not unit", names [i]);
2057117395Skan      else
2058117395Skan	{
2059117395Skan	  new_el = create_node (sizeof (struct unit_set_el));
2060117395Skan	  new_el->unit_decl = DECL_UNIT (decl_in_table);
2061117395Skan	  new_el->next_unit_set_el = NULL;
2062117395Skan	  if (last_el == NULL)
2063117395Skan	    el_list = last_el = new_el;
2064117395Skan	  else
2065117395Skan	    {
2066117395Skan	      last_el->next_unit_set_el = new_el;
2067117395Skan	      last_el = last_el->next_unit_set_el;
2068117395Skan	    }
2069117395Skan	}
2070117395Skan    }
2071117395Skan  return el_list;
2072117395Skan}
2073117395Skan
2074117395Skan/* The function adds each element from SOURCE_LIST to the exclusion
2075117395Skan   list of the each element from DEST_LIST.  Checking situation "unit
2076117395Skan   excludes itself".  */
2077117395Skanstatic void
2078132718Skanadd_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2079132718Skan	   pos_t excl_pos ATTRIBUTE_UNUSED)
2080117395Skan{
2081117395Skan  unit_set_el_t dst;
2082117395Skan  unit_set_el_t src;
2083117395Skan  unit_set_el_t curr_el;
2084117395Skan  unit_set_el_t prev_el;
2085117395Skan  unit_set_el_t copy;
2086117395Skan
2087117395Skan  for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2088117395Skan    for (src = source_list; src != NULL; src = src->next_unit_set_el)
2089117395Skan      {
2090117395Skan	if (dst->unit_decl == src->unit_decl)
2091117395Skan	  {
2092117395Skan	    error ("unit `%s' excludes itself", src->unit_decl->name);
2093117395Skan	    continue;
2094117395Skan	  }
2095117395Skan	if (dst->unit_decl->automaton_name != NULL
2096117395Skan	    && src->unit_decl->automaton_name != NULL
2097117395Skan	    && strcmp (dst->unit_decl->automaton_name,
2098117395Skan		       src->unit_decl->automaton_name) != 0)
2099117395Skan	  {
2100117395Skan	    error ("units `%s' and `%s' in exclusion set belong to different automata",
2101117395Skan		   src->unit_decl->name, dst->unit_decl->name);
2102117395Skan	    continue;
2103117395Skan	  }
2104117395Skan	for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2105117395Skan	     curr_el != NULL;
2106117395Skan	     prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2107117395Skan	  if (curr_el->unit_decl == src->unit_decl)
2108117395Skan	    break;
2109117395Skan	if (curr_el == NULL)
2110117395Skan	  {
2111117395Skan	    /* Element not found - insert.  */
2112117395Skan	    copy = copy_node (src, sizeof (*src));
2113117395Skan	    copy->next_unit_set_el = NULL;
2114117395Skan	    if (prev_el == NULL)
2115117395Skan	      dst->unit_decl->excl_list = copy;
2116117395Skan	    else
2117117395Skan	      prev_el->next_unit_set_el = copy;
2118117395Skan	}
2119117395Skan    }
2120117395Skan}
2121117395Skan
2122132718Skan/* Checking NAMES in presence/absence clause and returning the
2123132718Skan   formed unit_set_el_list.  The function is called only after
2124132718Skan   processing all exclusion sets.  */
2125117395Skanstatic unit_set_el_t
2126132718Skanprocess_presence_absence_names (char **names, int num,
2127132718Skan				pos_t req_pos ATTRIBUTE_UNUSED,
2128132718Skan				int presence_p, int final_p)
2129117395Skan{
2130117395Skan  unit_set_el_t el_list;
2131117395Skan  unit_set_el_t last_el;
2132117395Skan  unit_set_el_t new_el;
2133117395Skan  decl_t decl_in_table;
2134117395Skan  int i;
2135117395Skan
2136117395Skan  el_list = NULL;
2137117395Skan  last_el = NULL;
2138117395Skan  for (i = 0; i < num; i++)
2139117395Skan    {
2140117395Skan      decl_in_table = find_decl (names [i]);
2141117395Skan      if (decl_in_table == NULL)
2142117395Skan	error ((presence_p
2143132718Skan		? (final_p
2144132718Skan		   ? "unit `%s' in final presence set is not declared"
2145132718Skan		   : "unit `%s' in presence set is not declared")
2146132718Skan		: (final_p
2147132718Skan		   ? "unit `%s' in final absence set is not declared"
2148132718Skan		   : "unit `%s' in absence set is not declared")), names [i]);
2149117395Skan      else if (decl_in_table->mode != dm_unit)
2150117395Skan	error ((presence_p
2151132718Skan		? (final_p
2152132718Skan		   ? "`%s' in final presence set is not unit"
2153132718Skan		   : "`%s' in presence set is not unit")
2154132718Skan		: (final_p
2155132718Skan		   ? "`%s' in final absence set is not unit"
2156132718Skan		   : "`%s' in absence set is not unit")), names [i]);
2157117395Skan      else
2158117395Skan	{
2159117395Skan	  new_el = create_node (sizeof (struct unit_set_el));
2160117395Skan	  new_el->unit_decl = DECL_UNIT (decl_in_table);
2161117395Skan	  new_el->next_unit_set_el = NULL;
2162117395Skan	  if (last_el == NULL)
2163117395Skan	    el_list = last_el = new_el;
2164117395Skan	  else
2165117395Skan	    {
2166117395Skan	      last_el->next_unit_set_el = new_el;
2167117395Skan	      last_el = last_el->next_unit_set_el;
2168117395Skan	    }
2169117395Skan	}
2170117395Skan    }
2171117395Skan  return el_list;
2172117395Skan}
2173117395Skan
2174132718Skan/* Checking NAMES in patterns of a presence/absence clause and
2175132718Skan   returning the formed pattern_set_el_list.  The function is called
2176132718Skan   only after processing all exclusion sets.  */
2177132718Skanstatic pattern_set_el_t
2178132718Skanprocess_presence_absence_patterns (char ***patterns, int num,
2179132718Skan				   pos_t req_pos ATTRIBUTE_UNUSED,
2180132718Skan				   int presence_p, int final_p)
2181132718Skan{
2182132718Skan  pattern_set_el_t el_list;
2183132718Skan  pattern_set_el_t last_el;
2184132718Skan  pattern_set_el_t new_el;
2185132718Skan  decl_t decl_in_table;
2186132718Skan  int i, j;
2187132718Skan
2188132718Skan  el_list = NULL;
2189132718Skan  last_el = NULL;
2190132718Skan  for (i = 0; i < num; i++)
2191132718Skan    {
2192132718Skan      for (j = 0; patterns [i] [j] != NULL; j++)
2193132718Skan	;
2194132718Skan      new_el = create_node (sizeof (struct pattern_set_el)
2195132718Skan			    + sizeof (struct unit_decl *) * j);
2196132718Skan      new_el->unit_decls
2197132718Skan	= (struct unit_decl **) ((char *) new_el
2198132718Skan				 + sizeof (struct pattern_set_el));
2199132718Skan      new_el->next_pattern_set_el = NULL;
2200132718Skan      if (last_el == NULL)
2201132718Skan	el_list = last_el = new_el;
2202132718Skan      else
2203132718Skan	{
2204132718Skan	  last_el->next_pattern_set_el = new_el;
2205132718Skan	  last_el = last_el->next_pattern_set_el;
2206132718Skan	}
2207132718Skan      new_el->units_num = 0;
2208132718Skan      for (j = 0; patterns [i] [j] != NULL; j++)
2209132718Skan	{
2210132718Skan	  decl_in_table = find_decl (patterns [i] [j]);
2211132718Skan	  if (decl_in_table == NULL)
2212132718Skan	    error ((presence_p
2213132718Skan		    ? (final_p
2214132718Skan		       ? "unit `%s' in final presence set is not declared"
2215132718Skan		       : "unit `%s' in presence set is not declared")
2216132718Skan		    : (final_p
2217132718Skan		       ? "unit `%s' in final absence set is not declared"
2218132718Skan		       : "unit `%s' in absence set is not declared")),
2219132718Skan		   patterns [i] [j]);
2220132718Skan	  else if (decl_in_table->mode != dm_unit)
2221132718Skan	    error ((presence_p
2222132718Skan		    ? (final_p
2223132718Skan		       ? "`%s' in final presence set is not unit"
2224132718Skan		       : "`%s' in presence set is not unit")
2225132718Skan		    : (final_p
2226132718Skan		       ? "`%s' in final absence set is not unit"
2227132718Skan		       : "`%s' in absence set is not unit")),
2228132718Skan		   patterns [i] [j]);
2229132718Skan	  else
2230132718Skan	    {
2231132718Skan	      new_el->unit_decls [new_el->units_num]
2232132718Skan		= DECL_UNIT (decl_in_table);
2233132718Skan	      new_el->units_num++;
2234132718Skan	    }
2235132718Skan	}
2236132718Skan    }
2237132718Skan  return el_list;
2238132718Skan}
2239132718Skan
2240132718Skan/* The function adds each element from PATTERN_LIST to presence (if
2241117395Skan   PRESENCE_P) or absence list of the each element from DEST_LIST.
2242132718Skan   Checking situations "unit requires own absence", and "unit excludes
2243132718Skan   and requires presence of ...", "unit requires absence and presence
2244132718Skan   of ...", "units in (final) presence set belong to different
2245132718Skan   automata", and "units in (final) absence set belong to different
2246132718Skan   automata".  Remember that we process absence sets only after all
2247132718Skan   presence sets.  */
2248117395Skanstatic void
2249132718Skanadd_presence_absence (unit_set_el_t dest_list,
2250132718Skan		      pattern_set_el_t pattern_list,
2251132718Skan		      pos_t req_pos ATTRIBUTE_UNUSED,
2252132718Skan		      int presence_p, int final_p)
2253117395Skan{
2254117395Skan  unit_set_el_t dst;
2255132718Skan  pattern_set_el_t pat;
2256132718Skan  struct unit_decl *unit;
2257132718Skan  unit_set_el_t curr_excl_el;
2258132718Skan  pattern_set_el_t curr_pat_el;
2259132718Skan  pattern_set_el_t prev_el;
2260132718Skan  pattern_set_el_t copy;
2261132718Skan  int i;
2262132718Skan  int no_error_flag;
2263117395Skan
2264117395Skan  for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2265132718Skan    for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2266117395Skan      {
2267132718Skan	for (i = 0; i < pat->units_num; i++)
2268117395Skan	  {
2269132718Skan	    unit = pat->unit_decls [i];
2270132718Skan	    if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2271132718Skan	      {
2272132718Skan		error ("unit `%s' requires own absence", unit->name);
2273132718Skan		continue;
2274132718Skan	      }
2275132718Skan	    if (dst->unit_decl->automaton_name != NULL
2276132718Skan		&& unit->automaton_name != NULL
2277132718Skan		&& strcmp (dst->unit_decl->automaton_name,
2278132718Skan			   unit->automaton_name) != 0)
2279132718Skan	      {
2280132718Skan		error ((presence_p
2281132718Skan			? (final_p
2282132718Skan			   ? "units `%s' and `%s' in final presence set belong to different automata"
2283132718Skan			   : "units `%s' and `%s' in presence set belong to different automata")
2284132718Skan			: (final_p
2285132718Skan			   ? "units `%s' and `%s' in final absence set belong to different automata"
2286132718Skan			   : "units `%s' and `%s' in absence set belong to different automata")),
2287132718Skan		       unit->name, dst->unit_decl->name);
2288132718Skan		continue;
2289132718Skan	      }
2290132718Skan	    no_error_flag = 1;
2291117395Skan	    if (presence_p)
2292132718Skan	      for (curr_excl_el = dst->unit_decl->excl_list;
2293132718Skan		   curr_excl_el != NULL;
2294132718Skan		   curr_excl_el = curr_excl_el->next_unit_set_el)
2295117395Skan		{
2296132718Skan		  if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2297117395Skan		    {
2298117395Skan		      if (!w_flag)
2299117395Skan			{
2300132718Skan			  error ("unit `%s' excludes and requires presence of `%s'",
2301132718Skan				 dst->unit_decl->name, unit->name);
2302117395Skan			  no_error_flag = 0;
2303117395Skan			}
2304117395Skan		      else
2305117395Skan			warning
2306169689Skan			  (0, "unit `%s' excludes and requires presence of `%s'",
2307132718Skan			   dst->unit_decl->name, unit->name);
2308117395Skan		    }
2309117395Skan		}
2310132718Skan	    else if (pat->units_num == 1)
2311132718Skan	      for (curr_pat_el = dst->unit_decl->presence_list;
2312132718Skan		   curr_pat_el != NULL;
2313132718Skan		   curr_pat_el = curr_pat_el->next_pattern_set_el)
2314132718Skan		if (curr_pat_el->units_num == 1
2315132718Skan		    && unit == curr_pat_el->unit_decls [0])
2316132718Skan		  {
2317132718Skan		    if (!w_flag)
2318132718Skan		      {
2319132718Skan			error
2320117395Skan			  ("unit `%s' requires absence and presence of `%s'",
2321132718Skan			   dst->unit_decl->name, unit->name);
2322132718Skan			no_error_flag = 0;
2323132718Skan		      }
2324132718Skan		    else
2325132718Skan		      warning
2326169689Skan			(0, "unit `%s' requires absence and presence of `%s'",
2327132718Skan			 dst->unit_decl->name, unit->name);
2328132718Skan		  }
2329117395Skan	    if (no_error_flag)
2330117395Skan	      {
2331132718Skan		for (prev_el = (presence_p
2332132718Skan				? (final_p
2333132718Skan				   ? dst->unit_decl->final_presence_list
2334132718Skan				   : dst->unit_decl->final_presence_list)
2335132718Skan				: (final_p
2336132718Skan				   ? dst->unit_decl->final_absence_list
2337132718Skan				   : dst->unit_decl->absence_list));
2338132718Skan		     prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2339132718Skan		     prev_el = prev_el->next_pattern_set_el)
2340132718Skan		  ;
2341132718Skan		copy = copy_node (pat, sizeof (*pat));
2342132718Skan		copy->next_pattern_set_el = NULL;
2343117395Skan		if (prev_el == NULL)
2344117395Skan		  {
2345117395Skan		    if (presence_p)
2346132718Skan		      {
2347132718Skan			if (final_p)
2348132718Skan			  dst->unit_decl->final_presence_list = copy;
2349132718Skan			else
2350132718Skan			  dst->unit_decl->presence_list = copy;
2351132718Skan		      }
2352132718Skan		    else if (final_p)
2353132718Skan		      dst->unit_decl->final_absence_list = copy;
2354117395Skan		    else
2355117395Skan		      dst->unit_decl->absence_list = copy;
2356117395Skan		  }
2357117395Skan		else
2358132718Skan		  prev_el->next_pattern_set_el = copy;
2359117395Skan	      }
2360132718Skan	  }
2361132718Skan      }
2362117395Skan}
2363117395Skan
2364132718Skan
2365117395Skan/* The function searches for bypass with given IN_INSN_RESERV in given
2366117395Skan   BYPASS_LIST.  */
2367117395Skanstatic struct bypass_decl *
2368132718Skanfind_bypass (struct bypass_decl *bypass_list,
2369132718Skan	     struct insn_reserv_decl *in_insn_reserv)
2370117395Skan{
2371117395Skan  struct bypass_decl *bypass;
2372117395Skan
2373117395Skan  for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2374117395Skan    if (bypass->in_insn_reserv == in_insn_reserv)
2375117395Skan      break;
2376117395Skan  return bypass;
2377117395Skan}
2378117395Skan
2379117395Skan/* The function processes pipeline description declarations, checks
2380117395Skan   their correctness, and forms exclusion/presence/absence sets.  */
2381117395Skanstatic void
2382132718Skanprocess_decls (void)
2383117395Skan{
2384117395Skan  decl_t decl;
2385117395Skan  decl_t automaton_decl;
2386117395Skan  decl_t decl_in_table;
2387117395Skan  decl_t out_insn_reserv;
2388117395Skan  decl_t in_insn_reserv;
2389117395Skan  struct bypass_decl *bypass;
2390117395Skan  int automaton_presence;
2391117395Skan  int i;
2392117395Skan
2393117395Skan  /* Checking repeated automata declarations.  */
2394117395Skan  automaton_presence = 0;
2395117395Skan  for (i = 0; i < description->decls_num; i++)
2396117395Skan    {
2397117395Skan      decl = description->decls [i];
2398117395Skan      if (decl->mode == dm_automaton)
2399117395Skan	{
2400117395Skan	  automaton_presence = 1;
2401117395Skan	  decl_in_table = insert_automaton_decl (decl);
2402117395Skan	  if (decl_in_table != decl)
2403117395Skan	    {
2404117395Skan	      if (!w_flag)
2405117395Skan		error ("repeated declaration of automaton `%s'",
2406117395Skan		       DECL_AUTOMATON (decl)->name);
2407117395Skan	      else
2408169689Skan		warning (0, "repeated declaration of automaton `%s'",
2409117395Skan			 DECL_AUTOMATON (decl)->name);
2410117395Skan	    }
2411117395Skan	}
2412117395Skan    }
2413117395Skan  /* Checking undeclared automata, repeated declarations (except for
2414117395Skan     automata) and correctness of their attributes (insn latency times
2415117395Skan     etc.).  */
2416117395Skan  for (i = 0; i < description->decls_num; i++)
2417117395Skan    {
2418117395Skan      decl = description->decls [i];
2419117395Skan      if (decl->mode == dm_insn_reserv)
2420117395Skan	{
2421117395Skan	  if (DECL_INSN_RESERV (decl)->default_latency < 0)
2422117395Skan	    error ("define_insn_reservation `%s' has negative latency time",
2423117395Skan		   DECL_INSN_RESERV (decl)->name);
2424117395Skan	  DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2425117395Skan	  description->insns_num++;
2426117395Skan	  decl_in_table = insert_insn_decl (decl);
2427117395Skan	  if (decl_in_table != decl)
2428117395Skan	    error ("`%s' is already used as insn reservation name",
2429117395Skan		   DECL_INSN_RESERV (decl)->name);
2430117395Skan	}
2431117395Skan      else if (decl->mode == dm_bypass)
2432117395Skan	{
2433117395Skan	  if (DECL_BYPASS (decl)->latency < 0)
2434117395Skan	    error ("define_bypass `%s - %s' has negative latency time",
2435117395Skan		   DECL_BYPASS (decl)->out_insn_name,
2436117395Skan		   DECL_BYPASS (decl)->in_insn_name);
2437117395Skan	}
2438117395Skan      else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2439117395Skan	{
2440117395Skan	  if (decl->mode == dm_unit)
2441117395Skan	    {
2442117395Skan	      DECL_UNIT (decl)->automaton_decl = NULL;
2443117395Skan	      if (DECL_UNIT (decl)->automaton_name != NULL)
2444117395Skan		{
2445117395Skan		  automaton_decl
2446117395Skan                    = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2447117395Skan		  if (automaton_decl == NULL)
2448117395Skan		    error ("automaton `%s' is not declared",
2449117395Skan			   DECL_UNIT (decl)->automaton_name);
2450117395Skan		  else
2451117395Skan		    {
2452117395Skan		      DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2453117395Skan		      DECL_UNIT (decl)->automaton_decl
2454117395Skan			= DECL_AUTOMATON (automaton_decl);
2455117395Skan		    }
2456117395Skan		}
2457117395Skan	      else if (automaton_presence)
2458117395Skan		error ("define_unit `%s' without automaton when one defined",
2459117395Skan		       DECL_UNIT (decl)->name);
2460117395Skan	      DECL_UNIT (decl)->unit_num = description->units_num;
2461117395Skan	      description->units_num++;
2462117395Skan	      if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2463117395Skan		{
2464117395Skan		  error ("`%s' is declared as cpu unit", NOTHING_NAME);
2465117395Skan		  continue;
2466117395Skan		}
2467117395Skan	      decl_in_table = find_decl (DECL_UNIT (decl)->name);
2468117395Skan	    }
2469117395Skan	  else
2470117395Skan	    {
2471117395Skan	      if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2472117395Skan		{
2473117395Skan		  error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2474117395Skan		  continue;
2475117395Skan		}
2476117395Skan	      decl_in_table = find_decl (DECL_RESERV (decl)->name);
2477117395Skan	    }
2478117395Skan	  if (decl_in_table == NULL)
2479117395Skan	    decl_in_table = insert_decl (decl);
2480117395Skan	  else
2481117395Skan	    {
2482117395Skan	      if (decl->mode == dm_unit)
2483117395Skan		error ("repeated declaration of unit `%s'",
2484117395Skan		       DECL_UNIT (decl)->name);
2485117395Skan	      else
2486117395Skan		error ("repeated declaration of reservation `%s'",
2487117395Skan		       DECL_RESERV (decl)->name);
2488117395Skan	    }
2489117395Skan	}
2490117395Skan    }
2491117395Skan  /* Check bypasses and form list of bypasses for each (output)
2492117395Skan     insn.  */
2493117395Skan  for (i = 0; i < description->decls_num; i++)
2494117395Skan    {
2495117395Skan      decl = description->decls [i];
2496117395Skan      if (decl->mode == dm_bypass)
2497117395Skan	{
2498117395Skan	  out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2499117395Skan	  in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2500117395Skan	  if (out_insn_reserv == NULL)
2501117395Skan	    error ("there is no insn reservation `%s'",
2502117395Skan		   DECL_BYPASS (decl)->out_insn_name);
2503117395Skan	  else if (in_insn_reserv == NULL)
2504117395Skan	    error ("there is no insn reservation `%s'",
2505117395Skan		   DECL_BYPASS (decl)->in_insn_name);
2506117395Skan	  else
2507117395Skan	    {
2508117395Skan	      DECL_BYPASS (decl)->out_insn_reserv
2509117395Skan		= DECL_INSN_RESERV (out_insn_reserv);
2510117395Skan	      DECL_BYPASS (decl)->in_insn_reserv
2511117395Skan		= DECL_INSN_RESERV (in_insn_reserv);
2512117395Skan	      bypass
2513117395Skan		= find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2514117395Skan			       DECL_BYPASS (decl)->in_insn_reserv);
2515117395Skan	      if (bypass != NULL)
2516117395Skan		{
2517117395Skan		  if (DECL_BYPASS (decl)->latency == bypass->latency)
2518117395Skan		    {
2519117395Skan		      if (!w_flag)
2520117395Skan			error
2521117395Skan			  ("the same bypass `%s - %s' is already defined",
2522117395Skan			   DECL_BYPASS (decl)->out_insn_name,
2523117395Skan			   DECL_BYPASS (decl)->in_insn_name);
2524117395Skan		      else
2525117395Skan			warning
2526169689Skan			  (0, "the same bypass `%s - %s' is already defined",
2527117395Skan			   DECL_BYPASS (decl)->out_insn_name,
2528117395Skan			   DECL_BYPASS (decl)->in_insn_name);
2529117395Skan		    }
2530117395Skan		  else
2531117395Skan		    error ("bypass `%s - %s' is already defined",
2532117395Skan			   DECL_BYPASS (decl)->out_insn_name,
2533117395Skan			   DECL_BYPASS (decl)->in_insn_name);
2534117395Skan		}
2535117395Skan	      else
2536117395Skan		{
2537117395Skan		  DECL_BYPASS (decl)->next
2538117395Skan		    = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2539117395Skan		  DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2540117395Skan		    = DECL_BYPASS (decl);
2541117395Skan		}
2542117395Skan	    }
2543117395Skan	}
2544117395Skan    }
2545117395Skan
2546132718Skan  /* Check exclusion set declarations and form exclusion sets.  */
2547117395Skan  for (i = 0; i < description->decls_num; i++)
2548117395Skan    {
2549117395Skan      decl = description->decls [i];
2550117395Skan      if (decl->mode == dm_excl)
2551117395Skan	{
2552117395Skan	  unit_set_el_t unit_set_el_list;
2553117395Skan	  unit_set_el_t unit_set_el_list_2;
2554132718Skan
2555117395Skan	  unit_set_el_list
2556117395Skan            = process_excls (DECL_EXCL (decl)->names,
2557117395Skan			     DECL_EXCL (decl)->first_list_length, decl->pos);
2558117395Skan	  unit_set_el_list_2
2559117395Skan	    = process_excls (&DECL_EXCL (decl)->names
2560117395Skan			     [DECL_EXCL (decl)->first_list_length],
2561132718Skan                             DECL_EXCL (decl)->all_names_num
2562117395Skan                             - DECL_EXCL (decl)->first_list_length,
2563117395Skan                             decl->pos);
2564117395Skan	  add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2565117395Skan	  add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2566117395Skan	}
2567117395Skan    }
2568117395Skan
2569117395Skan  /* Check presence set declarations and form presence sets.  */
2570117395Skan  for (i = 0; i < description->decls_num; i++)
2571117395Skan    {
2572117395Skan      decl = description->decls [i];
2573117395Skan      if (decl->mode == dm_presence)
2574117395Skan	{
2575117395Skan	  unit_set_el_t unit_set_el_list;
2576132718Skan	  pattern_set_el_t pattern_set_el_list;
2577132718Skan
2578117395Skan	  unit_set_el_list
2579132718Skan            = process_presence_absence_names
2580132718Skan	      (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2581132718Skan	       decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2582132718Skan	  pattern_set_el_list
2583132718Skan	    = process_presence_absence_patterns
2584132718Skan	      (DECL_PRESENCE (decl)->patterns,
2585132718Skan	       DECL_PRESENCE (decl)->patterns_num,
2586132718Skan	       decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2587132718Skan	  add_presence_absence (unit_set_el_list, pattern_set_el_list,
2588132718Skan				decl->pos, TRUE,
2589132718Skan				DECL_PRESENCE (decl)->final_p);
2590117395Skan	}
2591117395Skan    }
2592117395Skan
2593117395Skan  /* Check absence set declarations and form absence sets.  */
2594117395Skan  for (i = 0; i < description->decls_num; i++)
2595117395Skan    {
2596117395Skan      decl = description->decls [i];
2597117395Skan      if (decl->mode == dm_absence)
2598117395Skan	{
2599117395Skan	  unit_set_el_t unit_set_el_list;
2600132718Skan	  pattern_set_el_t pattern_set_el_list;
2601132718Skan
2602117395Skan	  unit_set_el_list
2603132718Skan            = process_presence_absence_names
2604132718Skan	      (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2605132718Skan	       decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2606132718Skan	  pattern_set_el_list
2607132718Skan	    = process_presence_absence_patterns
2608132718Skan	      (DECL_ABSENCE (decl)->patterns,
2609132718Skan	       DECL_ABSENCE (decl)->patterns_num,
2610132718Skan	       decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2611132718Skan	  add_presence_absence (unit_set_el_list, pattern_set_el_list,
2612132718Skan				decl->pos, FALSE,
2613132718Skan				DECL_ABSENCE (decl)->final_p);
2614117395Skan	}
2615117395Skan    }
2616117395Skan}
2617117395Skan
2618117395Skan/* The following function checks that declared automaton is used.  If
2619117395Skan   the automaton is not used, the function fixes error/warning.  The
2620117395Skan   following function must be called only after `process_decls'.  */
2621117395Skanstatic void
2622132718Skancheck_automaton_usage (void)
2623117395Skan{
2624117395Skan  decl_t decl;
2625117395Skan  int i;
2626117395Skan
2627117395Skan  for (i = 0; i < description->decls_num; i++)
2628117395Skan    {
2629117395Skan      decl = description->decls [i];
2630117395Skan      if (decl->mode == dm_automaton
2631117395Skan	  && !DECL_AUTOMATON (decl)->automaton_is_used)
2632117395Skan	{
2633117395Skan	  if (!w_flag)
2634117395Skan	    error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2635117395Skan	  else
2636169689Skan	    warning (0, "automaton `%s' is not used",
2637117395Skan		     DECL_AUTOMATON (decl)->name);
2638117395Skan	}
2639117395Skan    }
2640117395Skan}
2641117395Skan
2642117395Skan/* The following recursive function processes all regexp in order to
2643117395Skan   fix usage of units or reservations and to fix errors of undeclared
2644117395Skan   name.  The function may change unit_regexp onto reserv_regexp.
2645117395Skan   Remember that reserv_regexp does not exist before the function
2646117395Skan   call.  */
2647117395Skanstatic regexp_t
2648132718Skanprocess_regexp (regexp_t regexp)
2649117395Skan{
2650117395Skan  decl_t decl_in_table;
2651117395Skan  regexp_t new_regexp;
2652117395Skan  int i;
2653132718Skan
2654169689Skan  switch (regexp->mode)
2655117395Skan    {
2656169689Skan    case rm_unit:
2657117395Skan      decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2658117395Skan      if (decl_in_table == NULL)
2659117395Skan        error ("undeclared unit or reservation `%s'",
2660117395Skan	       REGEXP_UNIT (regexp)->name);
2661169689Skan      else
2662169689Skan	switch (decl_in_table->mode)
2663169689Skan	  {
2664169689Skan	  case dm_unit:
2665169689Skan	    DECL_UNIT (decl_in_table)->unit_is_used = 1;
2666169689Skan	    REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2667169689Skan	    break;
2668169689Skan
2669169689Skan	  case dm_reserv:
2670169689Skan	    DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2671169689Skan	    new_regexp = create_node (sizeof (struct regexp));
2672169689Skan	    new_regexp->mode = rm_reserv;
2673169689Skan	    new_regexp->pos = regexp->pos;
2674169689Skan	    REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2675169689Skan	    REGEXP_RESERV (new_regexp)->reserv_decl
2676169689Skan	      = DECL_RESERV (decl_in_table);
2677169689Skan	    regexp = new_regexp;
2678169689Skan	    break;
2679169689Skan
2680169689Skan	  default:
2681169689Skan	    gcc_unreachable ();
2682117395Skan	}
2683169689Skan      break;
2684169689Skan    case rm_sequence:
2685169689Skan      for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2686169689Skan	REGEXP_SEQUENCE (regexp)->regexps [i]
2687169689Skan	  = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2688169689Skan      break;
2689169689Skan    case rm_allof:
2690169689Skan      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2691169689Skan	REGEXP_ALLOF (regexp)->regexps [i]
2692169689Skan	  = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2693169689Skan      break;
2694169689Skan    case rm_oneof:
2695169689Skan      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2696169689Skan	REGEXP_ONEOF (regexp)->regexps [i]
2697169689Skan	  = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2698169689Skan      break;
2699169689Skan    case rm_repeat:
2700169689Skan      REGEXP_REPEAT (regexp)->regexp
2701169689Skan	= process_regexp (REGEXP_REPEAT (regexp)->regexp);
2702169689Skan      break;
2703169689Skan    case rm_nothing:
2704169689Skan      break;
2705169689Skan    default:
2706169689Skan      gcc_unreachable ();
2707117395Skan    }
2708117395Skan  return regexp;
2709117395Skan}
2710117395Skan
2711117395Skan/* The following function processes regexp of define_reservation and
2712117395Skan   define_insn_reservation with the aid of function
2713117395Skan   `process_regexp'.  */
2714117395Skanstatic void
2715132718Skanprocess_regexp_decls (void)
2716117395Skan{
2717117395Skan  decl_t decl;
2718117395Skan  int i;
2719117395Skan
2720117395Skan  for (i = 0; i < description->decls_num; i++)
2721117395Skan    {
2722117395Skan      decl = description->decls [i];
2723117395Skan      if (decl->mode == dm_reserv)
2724117395Skan	DECL_RESERV (decl)->regexp
2725117395Skan	  = process_regexp (DECL_RESERV (decl)->regexp);
2726117395Skan      else if (decl->mode == dm_insn_reserv)
2727117395Skan	DECL_INSN_RESERV (decl)->regexp
2728117395Skan	  = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2729117395Skan    }
2730117395Skan}
2731117395Skan
2732117395Skan/* The following function checks that declared unit is used.  If the
2733117395Skan   unit is not used, the function fixes errors/warnings.  The
2734117395Skan   following function must be called only after `process_decls',
2735117395Skan   `process_regexp_decls'.  */
2736117395Skanstatic void
2737132718Skancheck_usage (void)
2738117395Skan{
2739117395Skan  decl_t decl;
2740117395Skan  int i;
2741117395Skan
2742117395Skan  for (i = 0; i < description->decls_num; i++)
2743117395Skan    {
2744117395Skan      decl = description->decls [i];
2745117395Skan      if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2746117395Skan	{
2747117395Skan	  if (!w_flag)
2748117395Skan	    error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2749117395Skan	  else
2750169689Skan	    warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2751117395Skan	}
2752117395Skan      else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2753117395Skan	{
2754117395Skan	  if (!w_flag)
2755117395Skan	    error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2756117395Skan	  else
2757169689Skan	    warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2758117395Skan	}
2759117395Skan    }
2760117395Skan}
2761117395Skan
2762117395Skan/* The following variable value is number of reservation being
2763117395Skan   processed on loop recognition.  */
2764117395Skanstatic int curr_loop_pass_num;
2765117395Skan
2766117395Skan/* The following recursive function returns nonzero value if REGEXP
2767117395Skan   contains given decl or reservations in given regexp refers for
2768117395Skan   given decl.  */
2769117395Skanstatic int
2770132718Skanloop_in_regexp (regexp_t regexp, decl_t start_decl)
2771117395Skan{
2772117395Skan  int i;
2773117395Skan
2774117395Skan  if (regexp == NULL)
2775117395Skan    return 0;
2776169689Skan  switch (regexp->mode)
2777117395Skan    {
2778169689Skan      case rm_unit:
2779169689Skan	return 0;
2780169689Skan
2781169689Skan    case rm_reserv:
2782117395Skan      if (start_decl->mode == dm_reserv
2783117395Skan          && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2784117395Skan        return 1;
2785117395Skan      else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2786117395Skan	       == curr_loop_pass_num)
2787117395Skan        /* declaration has been processed.  */
2788117395Skan        return 0;
2789117395Skan      else
2790117395Skan        {
2791117395Skan	  REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2792117395Skan            = curr_loop_pass_num;
2793117395Skan          return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2794117395Skan                                 start_decl);
2795117395Skan        }
2796169689Skan
2797169689Skan    case rm_sequence:
2798117395Skan      for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2799117395Skan	if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2800117395Skan	  return 1;
2801117395Skan      return 0;
2802169689Skan
2803169689Skan    case rm_allof:
2804117395Skan      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2805117395Skan	if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2806117395Skan	  return 1;
2807117395Skan      return 0;
2808169689Skan
2809169689Skan    case rm_oneof:
2810117395Skan      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2811117395Skan	if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2812117395Skan	  return 1;
2813117395Skan      return 0;
2814169689Skan
2815169689Skan    case rm_repeat:
2816169689Skan      return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2817169689Skan
2818169689Skan    case rm_nothing:
2819117395Skan      return 0;
2820169689Skan
2821169689Skan    default:
2822169689Skan      gcc_unreachable ();
2823117395Skan    }
2824117395Skan}
2825117395Skan
2826117395Skan/* The following function fixes errors "cycle in definition ...".  The
2827117395Skan   function uses function `loop_in_regexp' for that.  */
2828117395Skanstatic void
2829132718Skancheck_loops_in_regexps (void)
2830117395Skan{
2831117395Skan  decl_t decl;
2832117395Skan  int i;
2833117395Skan
2834117395Skan  for (i = 0; i < description->decls_num; i++)
2835117395Skan    {
2836117395Skan      decl = description->decls [i];
2837117395Skan      if (decl->mode == dm_reserv)
2838117395Skan	DECL_RESERV (decl)->loop_pass_num = 0;
2839117395Skan    }
2840117395Skan  for (i = 0; i < description->decls_num; i++)
2841117395Skan    {
2842117395Skan      decl = description->decls [i];
2843117395Skan      curr_loop_pass_num = i;
2844132718Skan
2845117395Skan      if (decl->mode == dm_reserv)
2846117395Skan	  {
2847117395Skan	    DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2848117395Skan	    if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2849117395Skan	      {
2850169689Skan		gcc_assert (DECL_RESERV (decl)->regexp);
2851117395Skan		error ("cycle in definition of reservation `%s'",
2852117395Skan		       DECL_RESERV (decl)->name);
2853117395Skan	      }
2854117395Skan	  }
2855117395Skan    }
2856117395Skan}
2857117395Skan
2858117395Skan/* The function recursively processes IR of reservation and defines
2859132718Skan   max and min cycle for reservation of unit.  */
2860132718Skanstatic void
2861132718Skanprocess_regexp_cycles (regexp_t regexp, int max_start_cycle,
2862132718Skan		       int min_start_cycle, int *max_finish_cycle,
2863132718Skan		       int *min_finish_cycle)
2864117395Skan{
2865117395Skan  int i;
2866117395Skan
2867169689Skan  switch (regexp->mode)
2868117395Skan    {
2869169689Skan    case rm_unit:
2870132718Skan      if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2871132718Skan	REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2872132718Skan      if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2873132718Skan	  || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2874132718Skan	REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2875132718Skan      *max_finish_cycle = max_start_cycle;
2876132718Skan      *min_finish_cycle = min_start_cycle;
2877169689Skan      break;
2878169689Skan
2879169689Skan    case rm_reserv:
2880169689Skan      process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2881169689Skan			     max_start_cycle, min_start_cycle,
2882169689Skan			     max_finish_cycle, min_finish_cycle);
2883169689Skan      break;
2884169689Skan
2885169689Skan    case rm_repeat:
2886117395Skan      for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2887132718Skan	{
2888132718Skan	  process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2889132718Skan				 max_start_cycle, min_start_cycle,
2890132718Skan				 max_finish_cycle, min_finish_cycle);
2891132718Skan	  max_start_cycle = *max_finish_cycle + 1;
2892132718Skan	  min_start_cycle = *min_finish_cycle + 1;
2893132718Skan	}
2894169689Skan      break;
2895169689Skan
2896169689Skan    case rm_sequence:
2897117395Skan      for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2898132718Skan	{
2899132718Skan	  process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2900132718Skan				 max_start_cycle, min_start_cycle,
2901132718Skan				 max_finish_cycle, min_finish_cycle);
2902132718Skan	  max_start_cycle = *max_finish_cycle + 1;
2903132718Skan	  min_start_cycle = *min_finish_cycle + 1;
2904132718Skan	}
2905169689Skan      break;
2906117395Skan
2907169689Skan    case rm_allof:
2908169689Skan      {
2909169689Skan	int max_cycle = 0;
2910169689Skan	int min_cycle = 0;
2911169689Skan
2912169689Skan	for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2913169689Skan	  {
2914169689Skan	    process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2915169689Skan				   max_start_cycle, min_start_cycle,
2916169689Skan				   max_finish_cycle, min_finish_cycle);
2917169689Skan	    if (max_cycle < *max_finish_cycle)
2918169689Skan	      max_cycle = *max_finish_cycle;
2919169689Skan	    if (i == 0 || min_cycle > *min_finish_cycle)
2920169689Skan	      min_cycle = *min_finish_cycle;
2921169689Skan	  }
2922169689Skan	*max_finish_cycle = max_cycle;
2923169689Skan	*min_finish_cycle = min_cycle;
2924169689Skan      }
2925169689Skan      break;
2926117395Skan
2927169689Skan    case rm_oneof:
2928169689Skan      {
2929169689Skan	int max_cycle = 0;
2930169689Skan	int min_cycle = 0;
2931169689Skan
2932169689Skan	for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2933169689Skan	  {
2934169689Skan	    process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2935169689Skan				   max_start_cycle, min_start_cycle,
2936169689Skan				   max_finish_cycle, min_finish_cycle);
2937169689Skan	    if (max_cycle < *max_finish_cycle)
2938169689Skan	      max_cycle = *max_finish_cycle;
2939169689Skan	    if (i == 0 || min_cycle > *min_finish_cycle)
2940169689Skan	      min_cycle = *min_finish_cycle;
2941169689Skan	  }
2942169689Skan	*max_finish_cycle = max_cycle;
2943169689Skan	*min_finish_cycle = min_cycle;
2944169689Skan      }
2945169689Skan      break;
2946169689Skan
2947169689Skan    case rm_nothing:
2948132718Skan      *max_finish_cycle = max_start_cycle;
2949132718Skan      *min_finish_cycle = min_start_cycle;
2950169689Skan      break;
2951169689Skan
2952169689Skan    default:
2953169689Skan      gcc_unreachable ();
2954117395Skan    }
2955117395Skan}
2956117395Skan
2957117395Skan/* The following function is called only for correct program.  The
2958117395Skan   function defines max reservation of insns in cycles.  */
2959117395Skanstatic void
2960132718Skanevaluate_max_reserv_cycles (void)
2961117395Skan{
2962117395Skan  int max_insn_cycles_num;
2963132718Skan  int min_insn_cycles_num;
2964117395Skan  decl_t decl;
2965117395Skan  int i;
2966117395Skan
2967117395Skan  description->max_insn_reserv_cycles = 0;
2968117395Skan  for (i = 0; i < description->decls_num; i++)
2969117395Skan    {
2970117395Skan      decl = description->decls [i];
2971117395Skan      if (decl->mode == dm_insn_reserv)
2972117395Skan      {
2973132718Skan        process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2974132718Skan			       &max_insn_cycles_num, &min_insn_cycles_num);
2975117395Skan        if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2976117395Skan	  description->max_insn_reserv_cycles = max_insn_cycles_num;
2977117395Skan      }
2978117395Skan    }
2979117395Skan  description->max_insn_reserv_cycles++;
2980117395Skan}
2981117395Skan
2982117395Skan/* The following function calls functions for checking all
2983117395Skan   description.  */
2984117395Skanstatic void
2985132718Skancheck_all_description (void)
2986117395Skan{
2987117395Skan  process_decls ();
2988117395Skan  check_automaton_usage ();
2989117395Skan  process_regexp_decls ();
2990117395Skan  check_usage ();
2991117395Skan  check_loops_in_regexps ();
2992117395Skan  if (!have_error)
2993117395Skan    evaluate_max_reserv_cycles ();
2994117395Skan}
2995117395Skan
2996117395Skan
2997117395Skan
2998117395Skan/* The page contains abstract data `ticker'.  This data is used to
2999117395Skan   report time of different phases of building automata.  It is
3000117395Skan   possibly to write a description for which automata will be built
3001117395Skan   during several minutes even on fast machine.  */
3002117395Skan
3003117395Skan/* The following function creates ticker and makes it active.  */
3004117395Skanstatic ticker_t
3005132718Skancreate_ticker (void)
3006117395Skan{
3007117395Skan  ticker_t ticker;
3008117395Skan
3009117395Skan  ticker.modified_creation_time = get_run_time ();
3010117395Skan  ticker.incremented_off_time = 0;
3011117395Skan  return ticker;
3012117395Skan}
3013117395Skan
3014117395Skan/* The following function switches off given ticker.  */
3015117395Skanstatic void
3016132718Skanticker_off (ticker_t *ticker)
3017117395Skan{
3018117395Skan  if (ticker->incremented_off_time == 0)
3019117395Skan    ticker->incremented_off_time = get_run_time () + 1;
3020117395Skan}
3021117395Skan
3022117395Skan/* The following function switches on given ticker.  */
3023117395Skanstatic void
3024132718Skanticker_on (ticker_t *ticker)
3025117395Skan{
3026117395Skan  if (ticker->incremented_off_time != 0)
3027117395Skan    {
3028117395Skan      ticker->modified_creation_time
3029117395Skan        += get_run_time () - ticker->incremented_off_time + 1;
3030117395Skan      ticker->incremented_off_time = 0;
3031117395Skan    }
3032117395Skan}
3033117395Skan
3034117395Skan/* The following function returns current time in milliseconds since
3035117395Skan   the moment when given ticker was created.  */
3036117395Skanstatic int
3037132718Skanactive_time (ticker_t ticker)
3038117395Skan{
3039117395Skan  if (ticker.incremented_off_time != 0)
3040117395Skan    return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3041117395Skan  else
3042117395Skan    return get_run_time () - ticker.modified_creation_time;
3043117395Skan}
3044117395Skan
3045117395Skan/* The following function returns string representation of active time
3046117395Skan   of given ticker.  The result is string representation of seconds
3047117395Skan   with accuracy of 1/100 second.  Only result of the last call of the
3048117395Skan   function exists.  Therefore the following code is not correct
3049117395Skan
3050117395Skan      printf ("parser time: %s\ngeneration time: %s\n",
3051117395Skan              active_time_string (parser_ticker),
3052117395Skan              active_time_string (generation_ticker));
3053117395Skan
3054117395Skan   Correct code has to be the following
3055117395Skan
3056117395Skan      printf ("parser time: %s\n", active_time_string (parser_ticker));
3057117395Skan      printf ("generation time: %s\n",
3058117395Skan              active_time_string (generation_ticker));
3059117395Skan
3060117395Skan*/
3061117395Skanstatic void
3062132718Skanprint_active_time (FILE *f, ticker_t ticker)
3063117395Skan{
3064117395Skan  int msecs;
3065117395Skan
3066117395Skan  msecs = active_time (ticker);
3067117395Skan  fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3068117395Skan}
3069117395Skan
3070117395Skan
3071117395Skan
3072117395Skan/* The following variable value is number of automaton which are
3073117395Skan   really being created.  This value is defined on the base of
3074117395Skan   argument of option `-split'.  If the variable has zero value the
3075117395Skan   number of automata is defined by the constructions `%automaton'.
3076132718Skan   This case occurs when option `-split' is absent or has zero
3077117395Skan   argument.  If constructions `define_automaton' is absent only one
3078117395Skan   automaton is created.  */
3079117395Skanstatic int automata_num;
3080117395Skan
3081117395Skan/* The following variable values are times of
3082117395Skan       o transformation of regular expressions
3083117395Skan       o building NDFA (DFA if !ndfa_flag)
3084117395Skan       o NDFA -> DFA   (simply the same automaton if !ndfa_flag)
3085117395Skan       o DFA minimization
3086117395Skan       o building insn equivalence classes
3087117395Skan       o all previous ones
3088117395Skan       o code output */
3089117395Skanstatic ticker_t transform_time;
3090117395Skanstatic ticker_t NDFA_time;
3091117395Skanstatic ticker_t NDFA_to_DFA_time;
3092117395Skanstatic ticker_t minimize_time;
3093117395Skanstatic ticker_t equiv_time;
3094117395Skanstatic ticker_t automaton_generation_time;
3095117395Skanstatic ticker_t output_time;
3096117395Skan
3097117395Skan/* The following variable values are times of
3098117395Skan       all checking
3099117395Skan       all generation
3100117395Skan       all pipeline hazard translator work */
3101117395Skanstatic ticker_t check_time;
3102117395Skanstatic ticker_t generation_time;
3103117395Skanstatic ticker_t all_time;
3104117395Skan
3105117395Skan
3106117395Skan
3107117395Skan/* Pseudo insn decl which denotes advancing cycle.  */
3108117395Skanstatic decl_t advance_cycle_insn_decl;
3109117395Skanstatic void
3110132718Skanadd_advance_cycle_insn_decl (void)
3111117395Skan{
3112117395Skan  advance_cycle_insn_decl = create_node (sizeof (struct decl));
3113117395Skan  advance_cycle_insn_decl->mode = dm_insn_reserv;
3114117395Skan  advance_cycle_insn_decl->pos = no_pos;
3115117395Skan  DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3116169689Skan  DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3117117395Skan  DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3118117395Skan    = description->insns_num;
3119117395Skan  description->decls [description->decls_num] = advance_cycle_insn_decl;
3120117395Skan  description->decls_num++;
3121117395Skan  description->insns_num++;
3122117395Skan}
3123117395Skan
3124117395Skan
3125132718Skan/* Abstract data `alternative states' which represents
3126117395Skan   nondeterministic nature of the description (see comments for
3127117395Skan   structures alt_state and state).  */
3128117395Skan
3129117395Skan/* List of free states.  */
3130117395Skanstatic alt_state_t first_free_alt_state;
3131117395Skan
3132117395Skan#ifndef NDEBUG
3133117395Skan/* The following variables is maximal number of allocated nodes
3134117395Skan   alt_state.  */
3135117395Skanstatic int allocated_alt_states_num = 0;
3136117395Skan#endif
3137117395Skan
3138117395Skan/* The following function returns free node alt_state.  It may be new
3139132718Skan   allocated node or node freed earlier.  */
3140132718Skanstatic alt_state_t
3141132718Skanget_free_alt_state (void)
3142117395Skan{
3143117395Skan  alt_state_t result;
3144117395Skan
3145117395Skan  if (first_free_alt_state != NULL)
3146117395Skan    {
3147117395Skan      result = first_free_alt_state;
3148117395Skan      first_free_alt_state = first_free_alt_state->next_alt_state;
3149117395Skan    }
3150117395Skan  else
3151117395Skan    {
3152117395Skan#ifndef NDEBUG
3153117395Skan      allocated_alt_states_num++;
3154117395Skan#endif
3155117395Skan      result = create_node (sizeof (struct alt_state));
3156117395Skan    }
3157117395Skan  result->state = NULL;
3158117395Skan  result->next_alt_state = NULL;
3159117395Skan  result->next_sorted_alt_state = NULL;
3160117395Skan  return result;
3161117395Skan}
3162117395Skan
3163117395Skan/* The function frees node ALT_STATE.  */
3164117395Skanstatic void
3165132718Skanfree_alt_state (alt_state_t alt_state)
3166117395Skan{
3167117395Skan  if (alt_state == NULL)
3168117395Skan    return;
3169117395Skan  alt_state->next_alt_state = first_free_alt_state;
3170117395Skan  first_free_alt_state = alt_state;
3171117395Skan}
3172117395Skan
3173117395Skan/* The function frees list started with node ALT_STATE_LIST.  */
3174117395Skanstatic void
3175132718Skanfree_alt_states (alt_state_t alt_states_list)
3176117395Skan{
3177117395Skan  alt_state_t curr_alt_state;
3178117395Skan  alt_state_t next_alt_state;
3179117395Skan
3180117395Skan  for (curr_alt_state = alt_states_list;
3181117395Skan       curr_alt_state != NULL;
3182117395Skan       curr_alt_state = next_alt_state)
3183117395Skan    {
3184117395Skan      next_alt_state = curr_alt_state->next_alt_state;
3185117395Skan      free_alt_state (curr_alt_state);
3186117395Skan    }
3187117395Skan}
3188117395Skan
3189117395Skan/* The function compares unique numbers of alt states.  */
3190117395Skanstatic int
3191132718Skanalt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3192117395Skan{
3193117395Skan  if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3194117395Skan      == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3195117395Skan    return 0;
3196117395Skan  else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3197117395Skan	   < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3198117395Skan    return -1;
3199117395Skan  else
3200117395Skan    return 1;
3201117395Skan}
3202117395Skan
3203117395Skan/* The function sorts ALT_STATES_LIST and removes duplicated alt
3204117395Skan   states from the list.  The comparison key is alt state unique
3205117395Skan   number.  */
3206169689Skan
3207132718Skanstatic alt_state_t
3208132718Skanuniq_sort_alt_states (alt_state_t alt_states_list)
3209117395Skan{
3210117395Skan  alt_state_t curr_alt_state;
3211169689Skan  VEC(alt_state_t,heap) *alt_states;
3212117395Skan  size_t i;
3213117395Skan  size_t prev_unique_state_ind;
3214117395Skan  alt_state_t result;
3215117395Skan
3216169689Skan  if (alt_states_list == 0)
3217169689Skan    return 0;
3218169689Skan  if (alt_states_list->next_alt_state == 0)
3219169689Skan    return alt_states_list;
3220169689Skan
3221169689Skan  alt_states = VEC_alloc (alt_state_t,heap, 150);
3222117395Skan  for (curr_alt_state = alt_states_list;
3223117395Skan       curr_alt_state != NULL;
3224117395Skan       curr_alt_state = curr_alt_state->next_alt_state)
3225169689Skan    VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3226169689Skan
3227169689Skan  qsort (VEC_address (alt_state_t, alt_states),
3228169689Skan	 VEC_length  (alt_state_t, alt_states),
3229117395Skan	 sizeof (alt_state_t), alt_state_cmp);
3230169689Skan
3231169689Skan  prev_unique_state_ind = 0;
3232169689Skan  for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3233169689Skan    if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3234169689Skan	!= VEC_index (alt_state_t, alt_states, i)->state)
3235169689Skan      {
3236169689Skan	prev_unique_state_ind++;
3237169689Skan	VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3238169689Skan		     VEC_index (alt_state_t, alt_states, i));
3239169689Skan      }
3240169689Skan  VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3241169689Skan
3242169689Skan  for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3243169689Skan    VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3244169689Skan      = VEC_index (alt_state_t, alt_states, i);
3245169689Skan  VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3246169689Skan
3247169689Skan  result = VEC_index (alt_state_t, alt_states, 0);
3248169689Skan
3249169689Skan  VEC_free (alt_state_t,heap, alt_states);
3250117395Skan  return result;
3251117395Skan}
3252117395Skan
3253117395Skan/* The function checks equality of alt state lists.  Remember that the
3254117395Skan   lists must be already sorted by the previous function.  */
3255117395Skanstatic int
3256132718Skanalt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3257117395Skan{
3258117395Skan  while (alt_states_1 != NULL && alt_states_2 != NULL
3259117395Skan         && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3260117395Skan    {
3261117395Skan      alt_states_1 = alt_states_1->next_sorted_alt_state;
3262117395Skan      alt_states_2 = alt_states_2->next_sorted_alt_state;
3263117395Skan    }
3264117395Skan  return alt_states_1 == alt_states_2;
3265117395Skan}
3266117395Skan
3267117395Skan/* Initialization of the abstract data.  */
3268117395Skanstatic void
3269132718Skaninitiate_alt_states (void)
3270117395Skan{
3271117395Skan  first_free_alt_state = NULL;
3272117395Skan}
3273117395Skan
3274117395Skan/* Finishing work with the abstract data.  */
3275117395Skanstatic void
3276132718Skanfinish_alt_states (void)
3277117395Skan{
3278117395Skan}
3279117395Skan
3280117395Skan
3281117395Skan
3282117395Skan/* The page contains macros for work with bits strings.  We could use
3283117395Skan   standard gcc bitmap or sbitmap but it would result in difficulties
3284117395Skan   of building canadian cross.  */
3285117395Skan
3286117395Skan/* Set bit number bitno in the bit string.  The macro is not side
3287117395Skan   effect proof.  */
3288117395Skan#define SET_BIT(bitstring, bitno)					  \
3289117395Skan  (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3290117395Skan
3291132718Skan#define CLEAR_BIT(bitstring, bitno)					  \
3292132718Skan  (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3293132718Skan
3294117395Skan/* Test if bit number bitno in the bitstring is set.  The macro is not
3295117395Skan   side effect proof.  */
3296117395Skan#define TEST_BIT(bitstring, bitno)                                        \
3297117395Skan  (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3298117395Skan
3299117395Skan
3300117395Skan
3301117395Skan/* This page contains abstract data `state'.  */
3302117395Skan
3303117395Skan/* Maximal length of reservations in cycles (>= 1).  */
3304117395Skanstatic int max_cycles_num;
3305117395Skan
3306117395Skan/* Number of set elements (see type set_el_t) needed for
3307117395Skan   representation of one cycle reservation.  It is depended on units
3308117395Skan   number.  */
3309117395Skanstatic int els_in_cycle_reserv;
3310117395Skan
3311117395Skan/* Number of set elements (see type set_el_t) needed for
3312117395Skan   representation of maximal length reservation.  Deterministic
3313117395Skan   reservation is stored as set (bit string) of length equal to the
3314117395Skan   variable value * number of bits in set_el_t.  */
3315117395Skanstatic int els_in_reservs;
3316117395Skan
3317169689Skan/* Array of pointers to unit declarations.  */
3318117395Skanstatic unit_decl_t *units_array;
3319117395Skan
3320132718Skan/* Temporary reservation of maximal length.  */
3321132718Skanstatic reserv_sets_t temp_reserv;
3322117395Skan
3323117395Skan/* The state table itself is represented by the following variable.  */
3324117395Skanstatic htab_t state_table;
3325117395Skan
3326169689Skan/* Linked list of free 'state' structures to be recycled.  The
3327169689Skan   next_equiv_class_state pointer is borrowed for a free list.  */
3328169689Skanstatic state_t first_free_state;
3329117395Skan
3330117395Skanstatic int curr_unique_state_num;
3331117395Skan
3332117395Skan#ifndef NDEBUG
3333117395Skan/* The following variables is maximal number of allocated nodes
3334117395Skan   `state'.  */
3335117395Skanstatic int allocated_states_num = 0;
3336117395Skan#endif
3337117395Skan
3338117395Skan/* Allocate new reservation set.  */
3339117395Skanstatic reserv_sets_t
3340132718Skanalloc_empty_reserv_sets (void)
3341117395Skan{
3342117395Skan  reserv_sets_t result;
3343117395Skan
3344117395Skan  obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3345117395Skan  result = (reserv_sets_t) obstack_base (&irp);
3346222097Sbenl  (void) obstack_finish (&irp);
3347117395Skan  memset (result, 0, els_in_reservs * sizeof (set_el_t));
3348117395Skan  return result;
3349117395Skan}
3350117395Skan
3351117395Skan/* Hash value of reservation set.  */
3352117395Skanstatic unsigned
3353132718Skanreserv_sets_hash_value (reserv_sets_t reservs)
3354117395Skan{
3355117395Skan  set_el_t hash_value;
3356117395Skan  unsigned result;
3357117395Skan  int reservs_num, i;
3358117395Skan  set_el_t *reserv_ptr;
3359117395Skan
3360117395Skan  hash_value = 0;
3361117395Skan  reservs_num = els_in_reservs;
3362117395Skan  reserv_ptr = reservs;
3363117395Skan  i = 0;
3364117395Skan  while (reservs_num != 0)
3365117395Skan    {
3366117395Skan      reservs_num--;
3367117395Skan      hash_value += ((*reserv_ptr >> i)
3368117395Skan		     | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3369117395Skan      i++;
3370117395Skan      if (i == sizeof (set_el_t) * CHAR_BIT)
3371117395Skan	i = 0;
3372117395Skan      reserv_ptr++;
3373117395Skan    }
3374117395Skan  if (sizeof (set_el_t) <= sizeof (unsigned))
3375117395Skan    return hash_value;
3376117395Skan  result = 0;
3377117395Skan  for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3378117395Skan    {
3379117395Skan      result += (unsigned) hash_value;
3380117395Skan      hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3381117395Skan    }
3382117395Skan  return result;
3383117395Skan}
3384117395Skan
3385117395Skan/* Comparison of given reservation sets.  */
3386117395Skanstatic int
3387132718Skanreserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3388117395Skan{
3389117395Skan  int reservs_num;
3390117395Skan  set_el_t *reserv_ptr_1;
3391117395Skan  set_el_t *reserv_ptr_2;
3392117395Skan
3393169689Skan  gcc_assert (reservs_1 && reservs_2);
3394117395Skan  reservs_num = els_in_reservs;
3395117395Skan  reserv_ptr_1 = reservs_1;
3396117395Skan  reserv_ptr_2 = reservs_2;
3397117395Skan  while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3398117395Skan    {
3399117395Skan      reservs_num--;
3400117395Skan      reserv_ptr_1++;
3401117395Skan      reserv_ptr_2++;
3402117395Skan    }
3403117395Skan  if (reservs_num == 0)
3404117395Skan    return 0;
3405117395Skan  else if (*reserv_ptr_1 < *reserv_ptr_2)
3406117395Skan    return -1;
3407117395Skan  else
3408117395Skan    return 1;
3409117395Skan}
3410117395Skan
3411117395Skan/* The function checks equality of the reservation sets.  */
3412117395Skanstatic int
3413132718Skanreserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3414117395Skan{
3415117395Skan  return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3416117395Skan}
3417117395Skan
3418117395Skan/* Set up in the reservation set that unit with UNIT_NUM is used on
3419117395Skan   CYCLE_NUM.  */
3420117395Skanstatic void
3421132718Skanset_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3422117395Skan{
3423169689Skan  gcc_assert (cycle_num < max_cycles_num);
3424117395Skan  SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3425117395Skan           * sizeof (set_el_t) * CHAR_BIT + unit_num);
3426117395Skan}
3427117395Skan
3428117395Skan/* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3429117395Skan   used on CYCLE_NUM.  */
3430117395Skanstatic int
3431132718Skantest_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3432117395Skan{
3433169689Skan  gcc_assert (cycle_num < max_cycles_num);
3434117395Skan  return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3435117395Skan		   * sizeof (set_el_t) * CHAR_BIT + unit_num);
3436117395Skan}
3437117395Skan
3438117395Skan/* The function checks that the reservation sets are intersected,
3439117395Skan   i.e. there is a unit reservation on a cycle in both reservation
3440117395Skan   sets.  */
3441117395Skanstatic int
3442132718Skanreserv_sets_are_intersected (reserv_sets_t operand_1,
3443132718Skan			     reserv_sets_t operand_2)
3444117395Skan{
3445117395Skan  set_el_t *el_ptr_1;
3446117395Skan  set_el_t *el_ptr_2;
3447117395Skan  set_el_t *cycle_ptr_1;
3448117395Skan  set_el_t *cycle_ptr_2;
3449117395Skan
3450169689Skan  gcc_assert (operand_1 && operand_2);
3451117395Skan  for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3452117395Skan       el_ptr_1 < operand_1 + els_in_reservs;
3453117395Skan       el_ptr_1++, el_ptr_2++)
3454117395Skan    if (*el_ptr_1 & *el_ptr_2)
3455117395Skan      return 1;
3456132718Skan  reserv_sets_or (temp_reserv, operand_1, operand_2);
3457117395Skan  for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3458117395Skan       cycle_ptr_1 < operand_1 + els_in_reservs;
3459117395Skan       cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3460117395Skan    {
3461117395Skan      for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3462117395Skan	   el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3463117395Skan	   el_ptr_1++, el_ptr_2++)
3464117395Skan	if (*el_ptr_1 & *el_ptr_2)
3465117395Skan	  return 1;
3466132718Skan      if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3467117395Skan	return 1;
3468132718Skan      if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3469132718Skan						       - operand_2),
3470132718Skan					cycle_ptr_2, TRUE))
3471132718Skan	return 1;
3472132718Skan      if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3473132718Skan	return 1;
3474132718Skan      if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3475132718Skan				       cycle_ptr_2, TRUE))
3476132718Skan	return 1;
3477117395Skan    }
3478117395Skan  return 0;
3479117395Skan}
3480117395Skan
3481117395Skan/* The function sets up RESULT bits by bits of OPERAND shifted on one
3482117395Skan   cpu cycle.  The remaining bits of OPERAND (representing the last
3483132718Skan   cycle unit reservations) are not changed.  */
3484117395Skanstatic void
3485132718Skanreserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3486117395Skan{
3487117395Skan  int i;
3488117395Skan
3489169689Skan  gcc_assert (result && operand && result != operand);
3490117395Skan  for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3491117395Skan    result [i - els_in_cycle_reserv] = operand [i];
3492117395Skan}
3493117395Skan
3494117395Skan/* OR of the reservation sets.  */
3495117395Skanstatic void
3496132718Skanreserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3497132718Skan		reserv_sets_t operand_2)
3498117395Skan{
3499117395Skan  set_el_t *el_ptr_1;
3500117395Skan  set_el_t *el_ptr_2;
3501117395Skan  set_el_t *result_set_el_ptr;
3502117395Skan
3503169689Skan  gcc_assert (result && operand_1 && operand_2);
3504117395Skan  for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3505117395Skan       el_ptr_1 < operand_1 + els_in_reservs;
3506117395Skan       el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3507117395Skan    *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3508117395Skan}
3509117395Skan
3510117395Skan/* AND of the reservation sets.  */
3511117395Skanstatic void
3512132718Skanreserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3513132718Skan		reserv_sets_t operand_2)
3514117395Skan{
3515117395Skan  set_el_t *el_ptr_1;
3516117395Skan  set_el_t *el_ptr_2;
3517117395Skan  set_el_t *result_set_el_ptr;
3518117395Skan
3519169689Skan  gcc_assert (result && operand_1 && operand_2);
3520117395Skan  for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3521117395Skan       el_ptr_1 < operand_1 + els_in_reservs;
3522117395Skan       el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3523117395Skan    *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3524117395Skan}
3525117395Skan
3526117395Skan/* The function outputs string representation of units reservation on
3527117395Skan   cycle START_CYCLE in the reservation set.  The function uses repeat
3528117395Skan   construction if REPETITION_NUM > 1.  */
3529117395Skanstatic void
3530132718Skanoutput_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3531132718Skan		      int repetition_num)
3532117395Skan{
3533117395Skan  int unit_num;
3534117395Skan  int reserved_units_num;
3535117395Skan
3536117395Skan  reserved_units_num = 0;
3537117395Skan  for (unit_num = 0; unit_num < description->units_num; unit_num++)
3538117395Skan    if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3539117395Skan                  * sizeof (set_el_t) * CHAR_BIT + unit_num))
3540117395Skan      reserved_units_num++;
3541169689Skan  gcc_assert (repetition_num > 0);
3542117395Skan  if (repetition_num != 1 && reserved_units_num > 1)
3543117395Skan    fprintf (f, "(");
3544117395Skan  reserved_units_num = 0;
3545117395Skan  for (unit_num = 0;
3546117395Skan       unit_num < description->units_num;
3547117395Skan       unit_num++)
3548117395Skan    if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3549117395Skan		  * sizeof (set_el_t) * CHAR_BIT + unit_num))
3550117395Skan      {
3551117395Skan        if (reserved_units_num != 0)
3552117395Skan          fprintf (f, "+");
3553117395Skan        reserved_units_num++;
3554117395Skan        fprintf (f, "%s", units_array [unit_num]->name);
3555117395Skan      }
3556117395Skan  if (reserved_units_num == 0)
3557117395Skan    fprintf (f, NOTHING_NAME);
3558169689Skan  gcc_assert (repetition_num > 0);
3559132718Skan  if (repetition_num != 1 && reserved_units_num > 1)
3560117395Skan    fprintf (f, ")");
3561117395Skan  if (repetition_num != 1)
3562117395Skan    fprintf (f, "*%d", repetition_num);
3563117395Skan}
3564117395Skan
3565117395Skan/* The function outputs string representation of units reservation in
3566117395Skan   the reservation set.  */
3567117395Skanstatic void
3568132718Skanoutput_reserv_sets (FILE *f, reserv_sets_t reservs)
3569117395Skan{
3570117395Skan  int start_cycle = 0;
3571117395Skan  int cycle;
3572117395Skan  int repetition_num;
3573117395Skan
3574117395Skan  repetition_num = 0;
3575117395Skan  for (cycle = 0; cycle < max_cycles_num; cycle++)
3576117395Skan    if (repetition_num == 0)
3577117395Skan      {
3578117395Skan        repetition_num++;
3579117395Skan        start_cycle = cycle;
3580117395Skan      }
3581117395Skan    else if (memcmp
3582117395Skan             ((char *) reservs + start_cycle * els_in_cycle_reserv
3583117395Skan	      * sizeof (set_el_t),
3584117395Skan              (char *) reservs + cycle * els_in_cycle_reserv
3585117395Skan	      * sizeof (set_el_t),
3586117395Skan	      els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3587117395Skan      repetition_num++;
3588117395Skan    else
3589117395Skan      {
3590117395Skan        if (start_cycle != 0)
3591117395Skan          fprintf (f, ", ");
3592117395Skan        output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3593117395Skan        repetition_num = 1;
3594117395Skan        start_cycle = cycle;
3595117395Skan      }
3596117395Skan  if (start_cycle < max_cycles_num)
3597117395Skan    {
3598117395Skan      if (start_cycle != 0)
3599117395Skan        fprintf (f, ", ");
3600117395Skan      output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3601117395Skan    }
3602117395Skan}
3603117395Skan
3604117395Skan/* The following function returns free node state for AUTOMATON.  It
3605132718Skan   may be new allocated node or node freed earlier.  The function also
3606117395Skan   allocates reservation set if WITH_RESERVS has nonzero value.  */
3607117395Skanstatic state_t
3608132718Skanget_free_state (int with_reservs, automaton_t automaton)
3609117395Skan{
3610117395Skan  state_t result;
3611117395Skan
3612169689Skan  gcc_assert (max_cycles_num > 0 && automaton);
3613169689Skan  if (first_free_state)
3614117395Skan    {
3615169689Skan      result = first_free_state;
3616169689Skan      first_free_state = result->next_equiv_class_state;
3617169689Skan
3618169689Skan      result->next_equiv_class_state = NULL;
3619117395Skan      result->automaton = automaton;
3620117395Skan      result->first_out_arc = NULL;
3621117395Skan      result->it_was_placed_in_stack_for_NDFA_forming = 0;
3622117395Skan      result->it_was_placed_in_stack_for_DFA_forming = 0;
3623117395Skan      result->component_states = NULL;
3624117395Skan      result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3625117395Skan    }
3626117395Skan  else
3627117395Skan    {
3628117395Skan#ifndef NDEBUG
3629117395Skan      allocated_states_num++;
3630117395Skan#endif
3631117395Skan      result = create_node (sizeof (struct state));
3632117395Skan      result->automaton = automaton;
3633117395Skan      result->first_out_arc = NULL;
3634117395Skan      result->unique_num = curr_unique_state_num;
3635117395Skan      result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3636117395Skan      curr_unique_state_num++;
3637117395Skan    }
3638117395Skan  if (with_reservs)
3639117395Skan    {
3640117395Skan      if (result->reservs == NULL)
3641117395Skan        result->reservs = alloc_empty_reserv_sets ();
3642117395Skan      else
3643117395Skan        memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3644117395Skan    }
3645117395Skan  return result;
3646117395Skan}
3647117395Skan
3648117395Skan/* The function frees node STATE.  */
3649117395Skanstatic void
3650132718Skanfree_state (state_t state)
3651117395Skan{
3652117395Skan  free_alt_states (state->component_states);
3653169689Skan  state->next_equiv_class_state = first_free_state;
3654169689Skan  first_free_state = state;
3655117395Skan}
3656117395Skan
3657117395Skan/* Hash value of STATE.  If STATE represents deterministic state it is
3658117395Skan   simply hash value of the corresponding reservation set.  Otherwise
3659117395Skan   it is formed from hash values of the component deterministic
3660117395Skan   states.  One more key is order number of state automaton.  */
3661117395Skanstatic hashval_t
3662132718Skanstate_hash (const void *state)
3663117395Skan{
3664117395Skan  unsigned int hash_value;
3665117395Skan  alt_state_t alt_state;
3666117395Skan
3667117395Skan  if (((state_t) state)->component_states == NULL)
3668117395Skan    hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3669117395Skan  else
3670117395Skan    {
3671117395Skan      hash_value = 0;
3672117395Skan      for (alt_state = ((state_t) state)->component_states;
3673117395Skan           alt_state != NULL;
3674117395Skan           alt_state = alt_state->next_sorted_alt_state)
3675117395Skan        hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3676117395Skan                       | (hash_value << CHAR_BIT))
3677117395Skan                      + alt_state->state->unique_num);
3678117395Skan    }
3679117395Skan  hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3680117395Skan                 | (hash_value << CHAR_BIT))
3681117395Skan                + ((state_t) state)->automaton->automaton_order_num);
3682117395Skan  return hash_value;
3683117395Skan}
3684117395Skan
3685117395Skan/* Return nonzero value if the states are the same.  */
3686117395Skanstatic int
3687132718Skanstate_eq_p (const void *state_1, const void *state_2)
3688117395Skan{
3689117395Skan  alt_state_t alt_state_1;
3690117395Skan  alt_state_t alt_state_2;
3691117395Skan
3692117395Skan  if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
3693117395Skan    return 0;
3694117395Skan  else if (((state_t) state_1)->component_states == NULL
3695117395Skan           && ((state_t) state_2)->component_states == NULL)
3696117395Skan    return reserv_sets_eq (((state_t) state_1)->reservs,
3697117395Skan			   ((state_t) state_2)->reservs);
3698117395Skan  else if (((state_t) state_1)->component_states != NULL
3699117395Skan           && ((state_t) state_2)->component_states != NULL)
3700117395Skan    {
3701117395Skan      for (alt_state_1 = ((state_t) state_1)->component_states,
3702117395Skan           alt_state_2 = ((state_t) state_2)->component_states;
3703117395Skan           alt_state_1 != NULL && alt_state_2 != NULL;
3704117395Skan           alt_state_1 = alt_state_1->next_sorted_alt_state,
3705117395Skan	   alt_state_2 = alt_state_2->next_sorted_alt_state)
3706117395Skan        /* All state in the list must be already in the hash table.
3707117395Skan           Also the lists must be sorted.  */
3708117395Skan        if (alt_state_1->state != alt_state_2->state)
3709117395Skan          return 0;
3710117395Skan      return alt_state_1 == alt_state_2;
3711117395Skan    }
3712117395Skan  else
3713117395Skan    return 0;
3714117395Skan}
3715117395Skan
3716117395Skan/* Insert STATE into the state table.  */
3717117395Skanstatic state_t
3718132718Skaninsert_state (state_t state)
3719117395Skan{
3720117395Skan  void **entry_ptr;
3721117395Skan
3722117395Skan  entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3723117395Skan  if (*entry_ptr == NULL)
3724117395Skan    *entry_ptr = (void *) state;
3725117395Skan  return (state_t) *entry_ptr;
3726117395Skan}
3727117395Skan
3728117395Skan/* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3729117395Skan   deterministic STATE.  */
3730117395Skanstatic void
3731132718Skanset_state_reserv (state_t state, int cycle_num, int unit_num)
3732117395Skan{
3733117395Skan  set_unit_reserv (state->reservs, cycle_num, unit_num);
3734117395Skan}
3735117395Skan
3736117395Skan/* Return nonzero value if the deterministic states contains a
3737117395Skan   reservation of the same cpu unit on the same cpu cycle.  */
3738117395Skanstatic int
3739132718Skanintersected_state_reservs_p (state_t state1, state_t state2)
3740117395Skan{
3741169689Skan  gcc_assert (state1->automaton == state2->automaton);
3742117395Skan  return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3743117395Skan}
3744117395Skan
3745117395Skan/* Return deterministic state (inserted into the table) which
3746132718Skan   representing the automaton state which is union of reservations of
3747132718Skan   the deterministic states masked by RESERVS.  */
3748117395Skanstatic state_t
3749132718Skanstates_union (state_t state1, state_t state2, reserv_sets_t reservs)
3750117395Skan{
3751117395Skan  state_t result;
3752117395Skan  state_t state_in_table;
3753117395Skan
3754169689Skan  gcc_assert (state1->automaton == state2->automaton);
3755117395Skan  result = get_free_state (1, state1->automaton);
3756117395Skan  reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3757132718Skan  reserv_sets_and (result->reservs, result->reservs, reservs);
3758117395Skan  state_in_table = insert_state (result);
3759117395Skan  if (result != state_in_table)
3760117395Skan    {
3761117395Skan      free_state (result);
3762117395Skan      result = state_in_table;
3763117395Skan    }
3764117395Skan  return result;
3765117395Skan}
3766117395Skan
3767117395Skan/* Return deterministic state (inserted into the table) which
3768117395Skan   represent the automaton state is obtained from deterministic STATE
3769132718Skan   by advancing cpu cycle and masking by RESERVS.  */
3770117395Skanstatic state_t
3771132718Skanstate_shift (state_t state, reserv_sets_t reservs)
3772117395Skan{
3773117395Skan  state_t result;
3774117395Skan  state_t state_in_table;
3775117395Skan
3776117395Skan  result = get_free_state (1, state->automaton);
3777117395Skan  reserv_sets_shift (result->reservs, state->reservs);
3778132718Skan  reserv_sets_and (result->reservs, result->reservs, reservs);
3779117395Skan  state_in_table = insert_state (result);
3780117395Skan  if (result != state_in_table)
3781117395Skan    {
3782117395Skan      free_state (result);
3783117395Skan      result = state_in_table;
3784117395Skan    }
3785117395Skan  return result;
3786117395Skan}
3787117395Skan
3788117395Skan/* Initialization of the abstract data.  */
3789117395Skanstatic void
3790132718Skaninitiate_states (void)
3791117395Skan{
3792117395Skan  decl_t decl;
3793117395Skan  int i;
3794117395Skan
3795169689Skan  if (description->units_num)
3796169689Skan    units_array = XNEWVEC (unit_decl_t, description->units_num);
3797169689Skan  else
3798169689Skan    units_array = 0;
3799169689Skan
3800117395Skan  for (i = 0; i < description->decls_num; i++)
3801117395Skan    {
3802117395Skan      decl = description->decls [i];
3803117395Skan      if (decl->mode == dm_unit)
3804117395Skan	units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3805117395Skan    }
3806117395Skan  max_cycles_num = description->max_insn_reserv_cycles;
3807117395Skan  els_in_cycle_reserv
3808117395Skan    = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3809117395Skan       / (sizeof (set_el_t) * CHAR_BIT));
3810117395Skan  els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3811117395Skan  curr_unique_state_num = 0;
3812117395Skan  initiate_alt_states ();
3813117395Skan  state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3814132718Skan  temp_reserv = alloc_empty_reserv_sets ();
3815117395Skan}
3816117395Skan
3817132718Skan/* Finishing work with the abstract data.  */
3818117395Skanstatic void
3819132718Skanfinish_states (void)
3820117395Skan{
3821169689Skan  free (units_array);
3822169689Skan  units_array = 0;
3823117395Skan  htab_delete (state_table);
3824169689Skan  first_free_state = NULL;
3825117395Skan  finish_alt_states ();
3826117395Skan}
3827117395Skan
3828117395Skan
3829117395Skan
3830117395Skan/* Abstract data `arcs'.  */
3831117395Skan
3832117395Skan/* List of free arcs.  */
3833117395Skanstatic arc_t first_free_arc;
3834117395Skan
3835117395Skan#ifndef NDEBUG
3836117395Skan/* The following variables is maximal number of allocated nodes
3837117395Skan   `arc'.  */
3838117395Skanstatic int allocated_arcs_num = 0;
3839117395Skan#endif
3840117395Skan
3841117395Skan/* The function frees node ARC.  */
3842117395Skanstatic void
3843132718Skanfree_arc (arc_t arc)
3844117395Skan{
3845117395Skan  arc->next_out_arc = first_free_arc;
3846117395Skan  first_free_arc = arc;
3847117395Skan}
3848117395Skan
3849117395Skan/* The function removes and frees ARC staring from FROM_STATE.  */
3850117395Skanstatic void
3851132718Skanremove_arc (state_t from_state, arc_t arc)
3852117395Skan{
3853117395Skan  arc_t prev_arc;
3854117395Skan  arc_t curr_arc;
3855117395Skan
3856169689Skan  gcc_assert (arc);
3857117395Skan  for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3858117395Skan       curr_arc != NULL;
3859117395Skan       prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3860117395Skan    if (curr_arc == arc)
3861117395Skan      break;
3862169689Skan  gcc_assert (curr_arc);
3863117395Skan  if (prev_arc == NULL)
3864117395Skan    from_state->first_out_arc = arc->next_out_arc;
3865117395Skan  else
3866117395Skan    prev_arc->next_out_arc = arc->next_out_arc;
3867169689Skan  from_state->num_out_arcs--;
3868117395Skan  free_arc (arc);
3869117395Skan}
3870117395Skan
3871117395Skan/* The functions returns arc with given characteristics (or NULL if
3872117395Skan   the arc does not exist).  */
3873117395Skanstatic arc_t
3874132718Skanfind_arc (state_t from_state, state_t to_state, ainsn_t insn)
3875117395Skan{
3876117395Skan  arc_t arc;
3877117395Skan
3878117395Skan  for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3879117395Skan    if (arc->to_state == to_state && arc->insn == insn)
3880117395Skan      return arc;
3881117395Skan  return NULL;
3882117395Skan}
3883117395Skan
3884169689Skan/* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3885169689Skan   The function returns added arc (or already existing arc).  */
3886117395Skanstatic arc_t
3887169689Skanadd_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3888117395Skan{
3889117395Skan  arc_t new_arc;
3890117395Skan
3891117395Skan  new_arc = find_arc (from_state, to_state, ainsn);
3892117395Skan  if (new_arc != NULL)
3893117395Skan    return new_arc;
3894117395Skan  if (first_free_arc == NULL)
3895117395Skan    {
3896117395Skan#ifndef NDEBUG
3897117395Skan      allocated_arcs_num++;
3898117395Skan#endif
3899117395Skan      new_arc = create_node (sizeof (struct arc));
3900117395Skan      new_arc->to_state = NULL;
3901117395Skan      new_arc->insn = NULL;
3902117395Skan      new_arc->next_out_arc = NULL;
3903117395Skan    }
3904117395Skan  else
3905117395Skan    {
3906117395Skan      new_arc = first_free_arc;
3907117395Skan      first_free_arc =  first_free_arc->next_out_arc;
3908117395Skan    }
3909117395Skan  new_arc->to_state = to_state;
3910117395Skan  new_arc->insn = ainsn;
3911117395Skan  ainsn->arc_exists_p = 1;
3912117395Skan  new_arc->next_out_arc = from_state->first_out_arc;
3913117395Skan  from_state->first_out_arc = new_arc;
3914169689Skan  from_state->num_out_arcs++;
3915117395Skan  new_arc->next_arc_marked_by_insn = NULL;
3916117395Skan  return new_arc;
3917117395Skan}
3918117395Skan
3919117395Skan/* The function returns the first arc starting from STATE.  */
3920117395Skanstatic arc_t
3921132718Skanfirst_out_arc (state_t state)
3922117395Skan{
3923117395Skan  return state->first_out_arc;
3924117395Skan}
3925117395Skan
3926117395Skan/* The function returns next out arc after ARC.  */
3927117395Skanstatic arc_t
3928132718Skannext_out_arc (arc_t arc)
3929117395Skan{
3930117395Skan  return arc->next_out_arc;
3931117395Skan}
3932117395Skan
3933117395Skan/* Initialization of the abstract data.  */
3934117395Skanstatic void
3935132718Skaninitiate_arcs (void)
3936117395Skan{
3937117395Skan  first_free_arc = NULL;
3938117395Skan}
3939117395Skan
3940117395Skan/* Finishing work with the abstract data.  */
3941117395Skanstatic void
3942132718Skanfinish_arcs (void)
3943117395Skan{
3944117395Skan}
3945117395Skan
3946117395Skan
3947117395Skan
3948117395Skan/* Abstract data `automata lists'.  */
3949117395Skan
3950117395Skan/* List of free states.  */
3951117395Skanstatic automata_list_el_t first_free_automata_list_el;
3952117395Skan
3953117395Skan/* The list being formed.  */
3954117395Skanstatic automata_list_el_t current_automata_list;
3955117395Skan
3956117395Skan/* Hash table of automata lists.  */
3957117395Skanstatic htab_t automata_list_table;
3958117395Skan
3959117395Skan/* The following function returns free automata list el.  It may be
3960117395Skan   new allocated node or node freed earlier.  */
3961132718Skanstatic automata_list_el_t
3962132718Skanget_free_automata_list_el (void)
3963117395Skan{
3964117395Skan  automata_list_el_t result;
3965117395Skan
3966117395Skan  if (first_free_automata_list_el != NULL)
3967117395Skan    {
3968117395Skan      result = first_free_automata_list_el;
3969117395Skan      first_free_automata_list_el
3970117395Skan	= first_free_automata_list_el->next_automata_list_el;
3971117395Skan    }
3972117395Skan  else
3973117395Skan    result = create_node (sizeof (struct automata_list_el));
3974117395Skan  result->automaton = NULL;
3975117395Skan  result->next_automata_list_el = NULL;
3976117395Skan  return result;
3977117395Skan}
3978117395Skan
3979117395Skan/* The function frees node AUTOMATA_LIST_EL.  */
3980117395Skanstatic void
3981132718Skanfree_automata_list_el (automata_list_el_t automata_list_el)
3982117395Skan{
3983117395Skan  if (automata_list_el == NULL)
3984117395Skan    return;
3985117395Skan  automata_list_el->next_automata_list_el = first_free_automata_list_el;
3986117395Skan  first_free_automata_list_el = automata_list_el;
3987117395Skan}
3988117395Skan
3989117395Skan/* The function frees list AUTOMATA_LIST.  */
3990117395Skanstatic void
3991132718Skanfree_automata_list (automata_list_el_t automata_list)
3992117395Skan{
3993117395Skan  automata_list_el_t curr_automata_list_el;
3994117395Skan  automata_list_el_t next_automata_list_el;
3995117395Skan
3996117395Skan  for (curr_automata_list_el = automata_list;
3997117395Skan       curr_automata_list_el != NULL;
3998117395Skan       curr_automata_list_el = next_automata_list_el)
3999117395Skan    {
4000117395Skan      next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4001117395Skan      free_automata_list_el (curr_automata_list_el);
4002117395Skan    }
4003117395Skan}
4004117395Skan
4005117395Skan/* Hash value of AUTOMATA_LIST.  */
4006117395Skanstatic hashval_t
4007132718Skanautomata_list_hash (const void *automata_list)
4008117395Skan{
4009117395Skan  unsigned int hash_value;
4010117395Skan  automata_list_el_t curr_automata_list_el;
4011117395Skan
4012117395Skan  hash_value = 0;
4013117395Skan  for (curr_automata_list_el = (automata_list_el_t) automata_list;
4014117395Skan       curr_automata_list_el != NULL;
4015117395Skan       curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4016117395Skan    hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4017117395Skan		   | (hash_value << CHAR_BIT))
4018117395Skan		  + curr_automata_list_el->automaton->automaton_order_num);
4019117395Skan  return hash_value;
4020117395Skan}
4021117395Skan
4022117395Skan/* Return nonzero value if the automata_lists are the same.  */
4023117395Skanstatic int
4024132718Skanautomata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4025117395Skan{
4026117395Skan  automata_list_el_t automata_list_el_1;
4027117395Skan  automata_list_el_t automata_list_el_2;
4028117395Skan
4029117395Skan  for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4030117395Skan	 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4031117395Skan       automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4032117395Skan       automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4033117395Skan	 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4034117395Skan    if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4035117395Skan      return 0;
4036117395Skan  return automata_list_el_1 == automata_list_el_2;
4037117395Skan}
4038117395Skan
4039117395Skan/* Initialization of the abstract data.  */
4040117395Skanstatic void
4041132718Skaninitiate_automata_lists (void)
4042117395Skan{
4043117395Skan  first_free_automata_list_el = NULL;
4044117395Skan  automata_list_table = htab_create (1500, automata_list_hash,
4045117395Skan				     automata_list_eq_p, (htab_del) 0);
4046117395Skan}
4047117395Skan
4048117395Skan/* The following function starts new automata list and makes it the
4049117395Skan   current one.  */
4050117395Skanstatic void
4051132718Skanautomata_list_start (void)
4052117395Skan{
4053117395Skan  current_automata_list = NULL;
4054117395Skan}
4055117395Skan
4056117395Skan/* The following function adds AUTOMATON to the current list.  */
4057117395Skanstatic void
4058132718Skanautomata_list_add (automaton_t automaton)
4059117395Skan{
4060117395Skan  automata_list_el_t el;
4061117395Skan
4062117395Skan  el = get_free_automata_list_el ();
4063117395Skan  el->automaton = automaton;
4064117395Skan  el->next_automata_list_el = current_automata_list;
4065117395Skan  current_automata_list = el;
4066117395Skan}
4067117395Skan
4068117395Skan/* The following function finishes forming the current list, inserts
4069117395Skan   it into the table and returns it.  */
4070117395Skanstatic automata_list_el_t
4071132718Skanautomata_list_finish (void)
4072117395Skan{
4073117395Skan  void **entry_ptr;
4074117395Skan
4075117395Skan  if (current_automata_list == NULL)
4076117395Skan    return NULL;
4077117395Skan  entry_ptr = htab_find_slot (automata_list_table,
4078117395Skan			      (void *) current_automata_list, 1);
4079117395Skan  if (*entry_ptr == NULL)
4080117395Skan    *entry_ptr = (void *) current_automata_list;
4081117395Skan  else
4082117395Skan    free_automata_list (current_automata_list);
4083117395Skan  current_automata_list = NULL;
4084117395Skan  return (automata_list_el_t) *entry_ptr;
4085117395Skan}
4086117395Skan
4087117395Skan/* Finishing work with the abstract data.  */
4088117395Skanstatic void
4089132718Skanfinish_automata_lists (void)
4090117395Skan{
4091117395Skan  htab_delete (automata_list_table);
4092117395Skan}
4093117395Skan
4094117395Skan
4095117395Skan
4096117395Skan/* The page contains abstract data for work with exclusion sets (see
4097117395Skan   exclusion_set in file rtl.def).  */
4098117395Skan
4099117395Skan/* The following variable refers to an exclusion set returned by
4100117395Skan   get_excl_set.  This is bit string of length equal to cpu units
4101117395Skan   number.  If exclusion set for given unit contains 1 for a unit,
4102117395Skan   then simultaneous reservation of the units is prohibited.  */
4103117395Skanstatic reserv_sets_t excl_set;
4104117395Skan
4105117395Skan/* The array contains exclusion sets for each unit.  */
4106117395Skanstatic reserv_sets_t *unit_excl_set_table;
4107117395Skan
4108117395Skan/* The following function forms the array containing exclusion sets
4109117395Skan   for each unit.  */
4110117395Skanstatic void
4111132718Skaninitiate_excl_sets (void)
4112117395Skan{
4113117395Skan  decl_t decl;
4114117395Skan  reserv_sets_t unit_excl_set;
4115117395Skan  unit_set_el_t el;
4116117395Skan  int i;
4117117395Skan
4118117395Skan  obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4119117395Skan  excl_set = (reserv_sets_t) obstack_base (&irp);
4120222097Sbenl  (void) obstack_finish (&irp);
4121117395Skan  obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4122117395Skan  unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4123222097Sbenl  (void) obstack_finish (&irp);
4124117395Skan  /* Evaluate unit exclusion sets.  */
4125117395Skan  for (i = 0; i < description->decls_num; i++)
4126117395Skan    {
4127117395Skan      decl = description->decls [i];
4128117395Skan      if (decl->mode == dm_unit)
4129117395Skan	{
4130117395Skan	  obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4131117395Skan	  unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4132222097Sbenl	  (void) obstack_finish (&irp);
4133117395Skan	  memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4134117395Skan	  for (el = DECL_UNIT (decl)->excl_list;
4135117395Skan	       el != NULL;
4136117395Skan	       el = el->next_unit_set_el)
4137132718Skan	    {
4138132718Skan	      SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4139132718Skan	      el->unit_decl->in_set_p = TRUE;
4140132718Skan	    }
4141117395Skan          unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4142117395Skan        }
4143117395Skan    }
4144117395Skan}
4145117395Skan
4146117395Skan/* The function sets up and return EXCL_SET which is union of
4147117395Skan   exclusion sets for each unit in IN_SET.  */
4148117395Skanstatic reserv_sets_t
4149132718Skanget_excl_set (reserv_sets_t in_set)
4150117395Skan{
4151117395Skan  int excl_char_num;
4152117395Skan  int chars_num;
4153117395Skan  int i;
4154117395Skan  int start_unit_num;
4155117395Skan  int unit_num;
4156117395Skan
4157117395Skan  chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4158117395Skan  memset (excl_set, 0, chars_num);
4159117395Skan  for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4160117395Skan    if (((unsigned char *) in_set) [excl_char_num])
4161117395Skan      for (i = CHAR_BIT - 1; i >= 0; i--)
4162117395Skan	if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4163117395Skan	  {
4164117395Skan	    start_unit_num = excl_char_num * CHAR_BIT + i;
4165117395Skan	    if (start_unit_num >= description->units_num)
4166117395Skan	      return excl_set;
4167117395Skan	    for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4168117395Skan	      {
4169117395Skan		excl_set [unit_num]
4170117395Skan		  |= unit_excl_set_table [start_unit_num] [unit_num];
4171117395Skan	      }
4172117395Skan	  }
4173117395Skan  return excl_set;
4174117395Skan}
4175117395Skan
4176117395Skan
4177117395Skan
4178132718Skan/* The page contains abstract data for work with presence/absence
4179132718Skan   pattern sets (see presence_set/absence_set in file rtl.def).  */
4180117395Skan
4181132718Skan/* The following arrays contain correspondingly presence, final
4182132718Skan   presence, absence, and final absence patterns for each unit.  */
4183132718Skanstatic pattern_reserv_t *unit_presence_set_table;
4184132718Skanstatic pattern_reserv_t *unit_final_presence_set_table;
4185132718Skanstatic pattern_reserv_t *unit_absence_set_table;
4186132718Skanstatic pattern_reserv_t *unit_final_absence_set_table;
4187117395Skan
4188132718Skan/* The following function forms list of reservation sets for given
4189132718Skan   PATTERN_LIST.  */
4190132718Skanstatic pattern_reserv_t
4191132718Skanform_reserv_sets_list (pattern_set_el_t pattern_list)
4192132718Skan{
4193132718Skan  pattern_set_el_t el;
4194132718Skan  pattern_reserv_t first, curr, prev;
4195132718Skan  int i;
4196117395Skan
4197132718Skan  prev = first = NULL;
4198132718Skan  for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4199132718Skan    {
4200132718Skan      curr = create_node (sizeof (struct pattern_reserv));
4201132718Skan      curr->reserv = alloc_empty_reserv_sets ();
4202132718Skan      curr->next_pattern_reserv = NULL;
4203132718Skan      for (i = 0; i < el->units_num; i++)
4204132718Skan	{
4205132718Skan	  SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4206132718Skan	  el->unit_decls [i]->in_set_p = TRUE;
4207132718Skan	}
4208132718Skan      if (prev != NULL)
4209132718Skan	prev->next_pattern_reserv = curr;
4210132718Skan      else
4211132718Skan	first = curr;
4212132718Skan      prev = curr;
4213132718Skan    }
4214132718Skan  return first;
4215132718Skan}
4216132718Skan
4217132718Skan /* The following function forms the array containing presence and
4218132718Skan   absence pattern sets for each unit.  */
4219117395Skanstatic void
4220132718Skaninitiate_presence_absence_pattern_sets (void)
4221117395Skan{
4222117395Skan  decl_t decl;
4223117395Skan  int i;
4224117395Skan
4225132718Skan  obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4226132718Skan  unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4227222097Sbenl  (void) obstack_finish (&irp);
4228132718Skan  obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4229132718Skan  unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4230222097Sbenl  (void) obstack_finish (&irp);
4231132718Skan  obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4232132718Skan  unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4233222097Sbenl  (void) obstack_finish (&irp);
4234132718Skan  obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4235132718Skan  unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4236222097Sbenl  (void) obstack_finish (&irp);
4237117395Skan  /* Evaluate unit presence/absence sets.  */
4238117395Skan  for (i = 0; i < description->decls_num; i++)
4239117395Skan    {
4240117395Skan      decl = description->decls [i];
4241117395Skan      if (decl->mode == dm_unit)
4242117395Skan	{
4243132718Skan          unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4244132718Skan	    = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4245132718Skan          unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4246132718Skan	    = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4247132718Skan          unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4248132718Skan	    = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4249132718Skan          unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4250132718Skan	    = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4251117395Skan        }
4252117395Skan    }
4253117395Skan}
4254117395Skan
4255132718Skan/* The function checks that CHECKED_SET satisfies all presence pattern
4256132718Skan   sets for units in ORIGIONAL_SET.  The function returns TRUE if it
4257132718Skan   is ok.  */
4258132718Skanstatic int
4259132718Skancheck_presence_pattern_sets (reserv_sets_t checked_set,
4260132718Skan			     reserv_sets_t origional_set,
4261132718Skan			     int final_p)
4262117395Skan{
4263117395Skan  int char_num;
4264117395Skan  int chars_num;
4265117395Skan  int i;
4266117395Skan  int start_unit_num;
4267117395Skan  int unit_num;
4268132718Skan  int presence_p;
4269132718Skan  pattern_reserv_t pat_reserv;
4270117395Skan
4271117395Skan  chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4272117395Skan  for (char_num = 0; char_num < chars_num; char_num++)
4273132718Skan    if (((unsigned char *) origional_set) [char_num])
4274117395Skan      for (i = CHAR_BIT - 1; i >= 0; i--)
4275132718Skan	if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4276117395Skan	  {
4277117395Skan	    start_unit_num = char_num * CHAR_BIT + i;
4278117395Skan	    if (start_unit_num >= description->units_num)
4279132718Skan	      break;
4280132718Skan	    if ((final_p
4281132718Skan		 && unit_final_presence_set_table [start_unit_num] == NULL)
4282132718Skan		|| (!final_p
4283132718Skan		    && unit_presence_set_table [start_unit_num] == NULL))
4284132718Skan	      continue;
4285132718Skan	    presence_p = FALSE;
4286132718Skan	    for (pat_reserv = (final_p
4287132718Skan			       ? unit_final_presence_set_table [start_unit_num]
4288132718Skan			       : unit_presence_set_table [start_unit_num]);
4289132718Skan		 pat_reserv != NULL;
4290132718Skan		 pat_reserv = pat_reserv->next_pattern_reserv)
4291132718Skan	      {
4292132718Skan		for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4293132718Skan		  if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4294132718Skan		      != pat_reserv->reserv [unit_num])
4295132718Skan		    break;
4296132718Skan		presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4297132718Skan	      }
4298132718Skan	    if (!presence_p)
4299132718Skan	      return FALSE;
4300117395Skan	  }
4301132718Skan  return TRUE;
4302117395Skan}
4303117395Skan
4304132718Skan/* The function checks that CHECKED_SET satisfies all absence pattern
4305132718Skan   sets for units in ORIGIONAL_SET.  The function returns TRUE if it
4306132718Skan   is ok.  */
4307132718Skanstatic int
4308132718Skancheck_absence_pattern_sets (reserv_sets_t checked_set,
4309132718Skan			    reserv_sets_t origional_set,
4310132718Skan			    int final_p)
4311132718Skan{
4312132718Skan  int char_num;
4313132718Skan  int chars_num;
4314132718Skan  int i;
4315132718Skan  int start_unit_num;
4316132718Skan  int unit_num;
4317132718Skan  pattern_reserv_t pat_reserv;
4318132718Skan
4319132718Skan  chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4320132718Skan  for (char_num = 0; char_num < chars_num; char_num++)
4321132718Skan    if (((unsigned char *) origional_set) [char_num])
4322132718Skan      for (i = CHAR_BIT - 1; i >= 0; i--)
4323132718Skan	if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4324132718Skan	  {
4325132718Skan	    start_unit_num = char_num * CHAR_BIT + i;
4326132718Skan	    if (start_unit_num >= description->units_num)
4327132718Skan	      break;
4328132718Skan	    for (pat_reserv = (final_p
4329132718Skan			       ? unit_final_absence_set_table [start_unit_num]
4330132718Skan			       : unit_absence_set_table [start_unit_num]);
4331132718Skan		 pat_reserv != NULL;
4332132718Skan		 pat_reserv = pat_reserv->next_pattern_reserv)
4333132718Skan	      {
4334132718Skan		for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4335132718Skan		  if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4336132718Skan		      != pat_reserv->reserv [unit_num]
4337132718Skan		      && pat_reserv->reserv [unit_num])
4338132718Skan		    break;
4339132718Skan		if (unit_num >= els_in_cycle_reserv)
4340132718Skan		  return FALSE;
4341132718Skan	      }
4342132718Skan	  }
4343132718Skan  return TRUE;
4344132718Skan}
4345132718Skan
4346117395Skan
4347117395Skan
4348117395Skan/* This page contains code for transformation of original reservations
4349117395Skan   described in .md file.  The main goal of transformations is
4350117395Skan   simplifying reservation and lifting up all `|' on the top of IR
4351117395Skan   reservation representation.  */
4352117395Skan
4353117395Skan
4354117395Skan/* The following function makes copy of IR representation of
4355117395Skan   reservation.  The function also substitutes all reservations
4356117395Skan   defined by define_reservation by corresponding value during making
4357117395Skan   the copy.  */
4358117395Skanstatic regexp_t
4359132718Skancopy_insn_regexp (regexp_t regexp)
4360117395Skan{
4361117395Skan  regexp_t  result;
4362117395Skan  int i;
4363117395Skan
4364169689Skan  switch (regexp->mode)
4365117395Skan    {
4366169689Skan    case rm_reserv:
4367169689Skan      result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4368169689Skan      break;
4369169689Skan
4370169689Skan    case rm_unit:
4371117395Skan      result = copy_node (regexp, sizeof (struct regexp));
4372169689Skan      break;
4373169689Skan
4374169689Skan    case rm_repeat:
4375169689Skan      result = copy_node (regexp, sizeof (struct regexp));
4376117395Skan      REGEXP_REPEAT (result)->regexp
4377117395Skan        = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4378169689Skan      break;
4379169689Skan
4380169689Skan    case rm_sequence:
4381117395Skan      result = copy_node (regexp,
4382117395Skan                          sizeof (struct regexp) + sizeof (regexp_t)
4383117395Skan			  * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4384117395Skan      for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4385117395Skan	REGEXP_SEQUENCE (result)->regexps [i]
4386117395Skan	  = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4387169689Skan      break;
4388169689Skan
4389169689Skan    case rm_allof:
4390117395Skan      result = copy_node (regexp,
4391117395Skan                          sizeof (struct regexp) + sizeof (regexp_t)
4392117395Skan			  * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4393117395Skan      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4394117395Skan	REGEXP_ALLOF (result)->regexps [i]
4395117395Skan	  = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4396169689Skan      break;
4397169689Skan
4398169689Skan    case rm_oneof:
4399117395Skan      result = copy_node (regexp,
4400117395Skan                          sizeof (struct regexp) + sizeof (regexp_t)
4401117395Skan			  * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4402117395Skan      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4403117395Skan	REGEXP_ONEOF (result)->regexps [i]
4404117395Skan	  = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4405169689Skan      break;
4406169689Skan
4407169689Skan    case rm_nothing:
4408117395Skan      result = copy_node (regexp, sizeof (struct regexp));
4409169689Skan      break;
4410169689Skan
4411169689Skan    default:
4412169689Skan      gcc_unreachable ();
4413117395Skan    }
4414117395Skan  return result;
4415117395Skan}
4416117395Skan
4417117395Skan/* The following variable is set up 1 if a transformation has been
4418117395Skan   applied.  */
4419117395Skanstatic int regexp_transformed_p;
4420117395Skan
4421117395Skan/* The function makes transformation
4422117395Skan   A*N -> A, A, ...  */
4423117395Skanstatic regexp_t
4424132718Skantransform_1 (regexp_t regexp)
4425117395Skan{
4426117395Skan  int i;
4427117395Skan  int repeat_num;
4428117395Skan  regexp_t operand;
4429117395Skan  pos_t pos;
4430117395Skan
4431117395Skan  if (regexp->mode == rm_repeat)
4432117395Skan    {
4433117395Skan      repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4434169689Skan      gcc_assert (repeat_num > 1);
4435117395Skan      operand = REGEXP_REPEAT (regexp)->regexp;
4436117395Skan      pos = regexp->mode;
4437117395Skan      regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4438117395Skan			    * (repeat_num - 1));
4439117395Skan      regexp->mode = rm_sequence;
4440117395Skan      regexp->pos = pos;
4441117395Skan      REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4442117395Skan      for (i = 0; i < repeat_num; i++)
4443117395Skan	REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4444117395Skan      regexp_transformed_p = 1;
4445117395Skan    }
4446117395Skan  return regexp;
4447117395Skan}
4448117395Skan
4449117395Skan/* The function makes transformations
4450117395Skan   ...,(A,B,...),C,... -> ...,A,B,...,C,...
4451117395Skan   ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4452117395Skan   ...|(A|B|...)|C|... -> ...|A|B|...|C|...  */
4453117395Skanstatic regexp_t
4454132718Skantransform_2 (regexp_t regexp)
4455117395Skan{
4456117395Skan  if (regexp->mode == rm_sequence)
4457117395Skan    {
4458117395Skan      regexp_t sequence = NULL;
4459117395Skan      regexp_t result;
4460117395Skan      int sequence_index = 0;
4461117395Skan      int i, j;
4462117395Skan
4463117395Skan      for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4464117395Skan	if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4465117395Skan	  {
4466117395Skan	    sequence_index = i;
4467117395Skan	    sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4468117395Skan	    break;
4469117395Skan	  }
4470117395Skan      if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4471117395Skan	{
4472169689Skan	  gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4473169689Skan		      && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4474117395Skan	  result = create_node (sizeof (struct regexp)
4475117395Skan                                + sizeof (regexp_t)
4476117395Skan				* (REGEXP_SEQUENCE (regexp)->regexps_num
4477117395Skan                                   + REGEXP_SEQUENCE (sequence)->regexps_num
4478117395Skan                                   - 2));
4479117395Skan	  result->mode = rm_sequence;
4480117395Skan	  result->pos = regexp->pos;
4481117395Skan	  REGEXP_SEQUENCE (result)->regexps_num
4482117395Skan            = (REGEXP_SEQUENCE (regexp)->regexps_num
4483117395Skan               + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4484117395Skan	  for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4485117395Skan            if (i < sequence_index)
4486117395Skan              REGEXP_SEQUENCE (result)->regexps [i]
4487117395Skan                = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4488117395Skan            else if (i > sequence_index)
4489117395Skan              REGEXP_SEQUENCE (result)->regexps
4490117395Skan                [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4491117395Skan                = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4492117395Skan            else
4493117395Skan              for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4494117395Skan                REGEXP_SEQUENCE (result)->regexps [i + j]
4495117395Skan                  = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4496117395Skan	  regexp_transformed_p = 1;
4497117395Skan	  regexp = result;
4498117395Skan	}
4499117395Skan    }
4500117395Skan  else if (regexp->mode == rm_allof)
4501117395Skan    {
4502117395Skan      regexp_t allof = NULL;
4503117395Skan      regexp_t result;
4504117395Skan      int allof_index = 0;
4505117395Skan      int i, j;
4506117395Skan
4507117395Skan      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4508117395Skan	if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4509117395Skan	  {
4510117395Skan	    allof_index = i;
4511117395Skan	    allof = REGEXP_ALLOF (regexp)->regexps [i];
4512117395Skan	    break;
4513117395Skan	  }
4514117395Skan      if (i < REGEXP_ALLOF (regexp)->regexps_num)
4515117395Skan	{
4516169689Skan	  gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4517169689Skan		      && REGEXP_ALLOF (regexp)->regexps_num > 1);
4518117395Skan	  result = create_node (sizeof (struct regexp)
4519117395Skan                                + sizeof (regexp_t)
4520117395Skan				* (REGEXP_ALLOF (regexp)->regexps_num
4521117395Skan                                   + REGEXP_ALLOF (allof)->regexps_num - 2));
4522117395Skan	  result->mode = rm_allof;
4523117395Skan	  result->pos = regexp->pos;
4524117395Skan	  REGEXP_ALLOF (result)->regexps_num
4525117395Skan            = (REGEXP_ALLOF (regexp)->regexps_num
4526117395Skan               + REGEXP_ALLOF (allof)->regexps_num - 1);
4527117395Skan	  for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4528117395Skan            if (i < allof_index)
4529117395Skan              REGEXP_ALLOF (result)->regexps [i]
4530117395Skan                = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4531117395Skan            else if (i > allof_index)
4532117395Skan              REGEXP_ALLOF (result)->regexps
4533117395Skan                [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4534117395Skan                = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4535117395Skan            else
4536117395Skan              for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4537117395Skan                REGEXP_ALLOF (result)->regexps [i + j]
4538117395Skan                  = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4539117395Skan	  regexp_transformed_p = 1;
4540117395Skan	  regexp = result;
4541117395Skan	}
4542117395Skan    }
4543117395Skan  else if (regexp->mode == rm_oneof)
4544117395Skan    {
4545117395Skan      regexp_t oneof = NULL;
4546117395Skan      regexp_t result;
4547117395Skan      int oneof_index = 0;
4548117395Skan      int i, j;
4549117395Skan
4550117395Skan      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4551117395Skan	if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4552117395Skan	  {
4553117395Skan	    oneof_index = i;
4554117395Skan	    oneof = REGEXP_ONEOF (regexp)->regexps [i];
4555117395Skan	    break;
4556117395Skan	  }
4557117395Skan      if (i < REGEXP_ONEOF (regexp)->regexps_num)
4558117395Skan	{
4559169689Skan	  gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4560169689Skan		      && REGEXP_ONEOF (regexp)->regexps_num > 1);
4561117395Skan	  result = create_node (sizeof (struct regexp)
4562117395Skan				+ sizeof (regexp_t)
4563117395Skan				* (REGEXP_ONEOF (regexp)->regexps_num
4564117395Skan                                   + REGEXP_ONEOF (oneof)->regexps_num - 2));
4565117395Skan	  result->mode = rm_oneof;
4566117395Skan	  result->pos = regexp->pos;
4567117395Skan	  REGEXP_ONEOF (result)->regexps_num
4568117395Skan	    = (REGEXP_ONEOF (regexp)->regexps_num
4569117395Skan               + REGEXP_ONEOF (oneof)->regexps_num - 1);
4570117395Skan	  for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4571117395Skan            if (i < oneof_index)
4572117395Skan              REGEXP_ONEOF (result)->regexps [i]
4573117395Skan                = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4574117395Skan            else if (i > oneof_index)
4575117395Skan              REGEXP_ONEOF (result)->regexps
4576117395Skan                [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4577117395Skan                = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4578117395Skan            else
4579117395Skan              for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4580117395Skan                REGEXP_ONEOF (result)->regexps [i + j]
4581117395Skan                  = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4582117395Skan	  regexp_transformed_p = 1;
4583117395Skan	  regexp = result;
4584117395Skan	}
4585117395Skan    }
4586117395Skan  return regexp;
4587117395Skan}
4588117395Skan
4589117395Skan/* The function makes transformations
4590117395Skan   ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4591117395Skan   ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4592117395Skan   ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4593117395Skan   ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),...  */
4594117395Skanstatic regexp_t
4595132718Skantransform_3 (regexp_t regexp)
4596117395Skan{
4597117395Skan  if (regexp->mode == rm_sequence)
4598117395Skan    {
4599117395Skan      regexp_t oneof = NULL;
4600117395Skan      int oneof_index = 0;
4601117395Skan      regexp_t result;
4602117395Skan      regexp_t sequence;
4603117395Skan      int i, j;
4604117395Skan
4605117395Skan      for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4606117395Skan	if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4607117395Skan	  {
4608117395Skan	    oneof_index = i;
4609117395Skan	    oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4610117395Skan	    break;
4611117395Skan	  }
4612117395Skan      if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4613117395Skan	{
4614169689Skan	  gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4615169689Skan		      && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4616117395Skan	  result = create_node (sizeof (struct regexp)
4617117395Skan				+ sizeof (regexp_t)
4618117395Skan				* (REGEXP_ONEOF (oneof)->regexps_num - 1));
4619117395Skan	  result->mode = rm_oneof;
4620117395Skan	  result->pos = regexp->pos;
4621117395Skan	  REGEXP_ONEOF (result)->regexps_num
4622117395Skan	    = REGEXP_ONEOF (oneof)->regexps_num;
4623117395Skan	  for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4624117395Skan	    {
4625117395Skan	      sequence
4626117395Skan                = create_node (sizeof (struct regexp)
4627117395Skan                               + sizeof (regexp_t)
4628117395Skan                               * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4629117395Skan	      sequence->mode = rm_sequence;
4630117395Skan	      sequence->pos = regexp->pos;
4631117395Skan	      REGEXP_SEQUENCE (sequence)->regexps_num
4632117395Skan                = REGEXP_SEQUENCE (regexp)->regexps_num;
4633117395Skan              REGEXP_ONEOF (result)->regexps [i] = sequence;
4634117395Skan	      for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4635117395Skan		if (j != oneof_index)
4636117395Skan		  REGEXP_SEQUENCE (sequence)->regexps [j]
4637117395Skan		    = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4638117395Skan		else
4639117395Skan		  REGEXP_SEQUENCE (sequence)->regexps [j]
4640117395Skan		    = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4641117395Skan	    }
4642117395Skan	  regexp_transformed_p = 1;
4643117395Skan	  regexp = result;
4644117395Skan	}
4645117395Skan    }
4646117395Skan  else if (regexp->mode == rm_allof)
4647117395Skan    {
4648132718Skan      regexp_t oneof = NULL;
4649132718Skan      regexp_t seq;
4650132718Skan      int oneof_index = 0;
4651132718Skan      int max_seq_length, allof_length;
4652117395Skan      regexp_t result;
4653132718Skan      regexp_t allof = NULL;
4654132718Skan      regexp_t allof_op = NULL;
4655117395Skan      int i, j;
4656117395Skan
4657117395Skan      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4658117395Skan	if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4659117395Skan	  {
4660117395Skan	    oneof_index = i;
4661117395Skan	    oneof = REGEXP_ALLOF (regexp)->regexps [i];
4662117395Skan	    break;
4663117395Skan	  }
4664117395Skan      if (i < REGEXP_ALLOF (regexp)->regexps_num)
4665117395Skan	{
4666169689Skan	  gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4667169689Skan		      && REGEXP_ALLOF (regexp)->regexps_num > 1);
4668117395Skan	  result = create_node (sizeof (struct regexp)
4669117395Skan				+ sizeof (regexp_t)
4670117395Skan				* (REGEXP_ONEOF (oneof)->regexps_num - 1));
4671117395Skan	  result->mode = rm_oneof;
4672117395Skan	  result->pos = regexp->pos;
4673117395Skan	  REGEXP_ONEOF (result)->regexps_num
4674117395Skan	    = REGEXP_ONEOF (oneof)->regexps_num;
4675117395Skan	  for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4676117395Skan	    {
4677117395Skan	      allof
4678117395Skan		= create_node (sizeof (struct regexp)
4679117395Skan                               + sizeof (regexp_t)
4680117395Skan			       * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4681117395Skan	      allof->mode = rm_allof;
4682117395Skan	      allof->pos = regexp->pos;
4683117395Skan	      REGEXP_ALLOF (allof)->regexps_num
4684117395Skan                = REGEXP_ALLOF (regexp)->regexps_num;
4685117395Skan              REGEXP_ONEOF (result)->regexps [i] = allof;
4686117395Skan	      for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4687117395Skan		if (j != oneof_index)
4688117395Skan		  REGEXP_ALLOF (allof)->regexps [j]
4689117395Skan		    = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4690117395Skan		else
4691117395Skan		  REGEXP_ALLOF (allof)->regexps [j]
4692117395Skan		    = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4693117395Skan	    }
4694117395Skan	  regexp_transformed_p = 1;
4695117395Skan	  regexp = result;
4696117395Skan	}
4697117395Skan      max_seq_length = 0;
4698117395Skan      if (regexp->mode == rm_allof)
4699117395Skan	for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4700117395Skan	  {
4701169689Skan	    switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4702117395Skan	      {
4703169689Skan	      case rm_sequence:
4704117395Skan		seq = REGEXP_ALLOF (regexp)->regexps [i];
4705117395Skan		if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4706117395Skan		  max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4707169689Skan		break;
4708169689Skan
4709169689Skan	      case rm_unit:
4710169689Skan	      case rm_nothing:
4711169689Skan		break;
4712169689Skan
4713169689Skan	      default:
4714117395Skan		max_seq_length = 0;
4715169689Skan		goto break_for;
4716117395Skan	      }
4717117395Skan	  }
4718169689Skan    break_for:
4719117395Skan      if (max_seq_length != 0)
4720117395Skan	{
4721169689Skan	  gcc_assert (max_seq_length != 1
4722169689Skan		      && REGEXP_ALLOF (regexp)->regexps_num > 1);
4723117395Skan	  result = create_node (sizeof (struct regexp)
4724117395Skan				+ sizeof (regexp_t) * (max_seq_length - 1));
4725117395Skan	  result->mode = rm_sequence;
4726117395Skan	  result->pos = regexp->pos;
4727117395Skan	  REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4728117395Skan	  for (i = 0; i < max_seq_length; i++)
4729117395Skan	    {
4730117395Skan	      allof_length = 0;
4731117395Skan	      for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4732169689Skan		switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4733117395Skan		  {
4734169689Skan		  case rm_sequence:
4735169689Skan		    if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4736169689Skan					      ->regexps [j])->regexps_num))
4737169689Skan		      {
4738169689Skan			allof_op
4739169689Skan			  = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4740169689Skan					      ->regexps [j])
4741169689Skan			     ->regexps [i]);
4742169689Skan			allof_length++;
4743169689Skan		      }
4744169689Skan		    break;
4745169689Skan		  case rm_unit:
4746169689Skan		  case rm_nothing:
4747169689Skan		    if (i == 0)
4748169689Skan		      {
4749169689Skan			allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4750169689Skan			allof_length++;
4751169689Skan		      }
4752169689Skan		    break;
4753169689Skan		  default:
4754169689Skan		    break;
4755117395Skan		  }
4756169689Skan
4757117395Skan	      if (allof_length == 1)
4758117395Skan		REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4759117395Skan	      else
4760117395Skan		{
4761117395Skan		  allof = create_node (sizeof (struct regexp)
4762117395Skan				       + sizeof (regexp_t)
4763117395Skan				       * (allof_length - 1));
4764117395Skan		  allof->mode = rm_allof;
4765117395Skan		  allof->pos = regexp->pos;
4766117395Skan		  REGEXP_ALLOF (allof)->regexps_num = allof_length;
4767117395Skan		  REGEXP_SEQUENCE (result)->regexps [i] = allof;
4768117395Skan		  allof_length = 0;
4769117395Skan		  for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4770117395Skan		    if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4771117395Skan			&& (i <
4772117395Skan			    (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4773117395Skan					      ->regexps [j])->regexps_num)))
4774117395Skan		      {
4775117395Skan			allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4776117395Skan						     ->regexps [j])
4777117395Skan				    ->regexps [i]);
4778117395Skan			REGEXP_ALLOF (allof)->regexps [allof_length]
4779117395Skan			  = allof_op;
4780117395Skan			allof_length++;
4781117395Skan		      }
4782117395Skan		    else if (i == 0
4783117395Skan			     && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4784132718Skan				 == rm_unit
4785132718Skan				 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4786132718Skan				     == rm_nothing)))
4787117395Skan		      {
4788117395Skan			allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4789117395Skan			REGEXP_ALLOF (allof)->regexps [allof_length]
4790117395Skan			  = allof_op;
4791117395Skan			allof_length++;
4792117395Skan		      }
4793117395Skan		}
4794117395Skan	    }
4795117395Skan	  regexp_transformed_p = 1;
4796117395Skan	  regexp = result;
4797117395Skan	}
4798117395Skan    }
4799117395Skan  return regexp;
4800117395Skan}
4801117395Skan
4802117395Skan/* The function traverses IR of reservation and applies transformations
4803117395Skan   implemented by FUNC.  */
4804117395Skanstatic regexp_t
4805132718Skanregexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4806117395Skan{
4807117395Skan  int i;
4808117395Skan
4809169689Skan  switch (regexp->mode)
4810169689Skan    {
4811169689Skan    case rm_sequence:
4812169689Skan      for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4813169689Skan	REGEXP_SEQUENCE (regexp)->regexps [i]
4814169689Skan	  = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4815169689Skan				   func);
4816169689Skan      break;
4817169689Skan
4818169689Skan    case rm_allof:
4819169689Skan      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4820169689Skan	REGEXP_ALLOF (regexp)->regexps [i]
4821169689Skan	  = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4822169689Skan      break;
4823169689Skan
4824169689Skan    case rm_oneof:
4825169689Skan      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4826169689Skan	REGEXP_ONEOF (regexp)->regexps [i]
4827169689Skan	  = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4828169689Skan      break;
4829169689Skan
4830169689Skan    case rm_repeat:
4831169689Skan      REGEXP_REPEAT (regexp)->regexp
4832169689Skan	= regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4833169689Skan      break;
4834169689Skan
4835169689Skan    case rm_nothing:
4836169689Skan    case rm_unit:
4837169689Skan      break;
4838169689Skan
4839169689Skan    default:
4840169689Skan      gcc_unreachable ();
4841169689Skan    }
4842117395Skan  return (*func) (regexp);
4843117395Skan}
4844117395Skan
4845117395Skan/* The function applies all transformations for IR representation of
4846117395Skan   reservation REGEXP.  */
4847117395Skanstatic regexp_t
4848132718Skantransform_regexp (regexp_t regexp)
4849117395Skan{
4850132718Skan  regexp = regexp_transform_func (regexp, transform_1);
4851117395Skan  do
4852117395Skan    {
4853117395Skan      regexp_transformed_p = 0;
4854117395Skan      regexp = regexp_transform_func (regexp, transform_2);
4855117395Skan      regexp = regexp_transform_func (regexp, transform_3);
4856117395Skan    }
4857117395Skan  while (regexp_transformed_p);
4858117395Skan  return regexp;
4859117395Skan}
4860117395Skan
4861132718Skan/* The function applies all transformations for reservations of all
4862117395Skan   insn declarations.  */
4863117395Skanstatic void
4864132718Skantransform_insn_regexps (void)
4865117395Skan{
4866117395Skan  decl_t decl;
4867117395Skan  int i;
4868117395Skan
4869117395Skan  transform_time = create_ticker ();
4870117395Skan  add_advance_cycle_insn_decl ();
4871132718Skan  if (progress_flag)
4872132718Skan    fprintf (stderr, "Reservation transformation...");
4873117395Skan  for (i = 0; i < description->decls_num; i++)
4874117395Skan    {
4875117395Skan      decl = description->decls [i];
4876117395Skan      if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4877117395Skan	DECL_INSN_RESERV (decl)->transformed_regexp
4878117395Skan	  = transform_regexp (copy_insn_regexp
4879117395Skan			      (DECL_INSN_RESERV (decl)->regexp));
4880117395Skan    }
4881132718Skan  if (progress_flag)
4882132718Skan    fprintf (stderr, "done\n");
4883117395Skan  ticker_off (&transform_time);
4884117395Skan}
4885117395Skan
4886117395Skan
4887117395Skan
4888132718Skan/* The following variable value is TRUE if the first annotated message
4889132718Skan   about units to automata distribution has been output.  */
4890132718Skanstatic int annotation_message_reported_p;
4891117395Skan
4892132718Skan/* The following structure describes usage of a unit in a reservation.  */
4893132718Skanstruct unit_usage
4894132718Skan{
4895132718Skan  unit_decl_t unit_decl;
4896132718Skan  /* The following forms a list of units used on the same cycle in the
4897132718Skan     same alternative.  */
4898132718Skan  struct unit_usage *next;
4899132718Skan};
4900169689Skantypedef struct unit_usage *unit_usage_t;
4901132718Skan
4902169689SkanDEF_VEC_P(unit_usage_t);
4903169689SkanDEF_VEC_ALLOC_P(unit_usage_t,heap);
4904169689Skan
4905132718Skan/* Obstack for unit_usage structures.  */
4906132718Skanstatic struct obstack unit_usages;
4907132718Skan
4908132718Skan/* VLA for representation of array of pointers to unit usage
4909132718Skan   structures.  There is an element for each combination of
4910132718Skan   (alternative number, cycle).  Unit usages on given cycle in
4911132718Skan   alternative with given number are referred through element with
4912132718Skan   index equals to the cycle * number of all alternatives in the regexp
4913132718Skan   + the alternative number.  */
4914169689Skanstatic VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4915132718Skan
4916132718Skan/* The following function creates the structure unit_usage for UNIT on
4917132718Skan   CYCLE in REGEXP alternative with ALT_NUM.  The structure is made
4918132718Skan   accessed through cycle_alt_unit_usages.  */
4919117395Skanstatic void
4920132718Skanstore_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4921132718Skan		      int alt_num)
4922117395Skan{
4923169689Skan  size_t length;
4924132718Skan  unit_decl_t unit_decl;
4925169689Skan  unit_usage_t unit_usage_ptr;
4926132718Skan  int index;
4927117395Skan
4928169689Skan  gcc_assert (regexp && regexp->mode == rm_oneof
4929169689Skan	      && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4930117395Skan  unit_decl = REGEXP_UNIT (unit)->unit_decl;
4931169689Skan
4932132718Skan  length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4933169689Skan  while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4934169689Skan    VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4935169689Skan
4936132718Skan  obstack_blank (&unit_usages, sizeof (struct unit_usage));
4937132718Skan  unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4938222097Sbenl  (void) obstack_finish (&unit_usages);
4939132718Skan  unit_usage_ptr->unit_decl = unit_decl;
4940132718Skan  index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4941169689Skan  unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4942169689Skan  VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4943132718Skan  unit_decl->last_distribution_check_cycle = -1; /* undefined */
4944117395Skan}
4945117395Skan
4946132718Skan/* The function processes given REGEXP to find units with the wrong
4947132718Skan   distribution.  */
4948117395Skanstatic void
4949132718Skancheck_regexp_units_distribution (const char *insn_reserv_name,
4950132718Skan				 regexp_t regexp)
4951117395Skan{
4952132718Skan  int i, j, k, cycle;
4953117395Skan  regexp_t seq, allof, unit;
4954132718Skan  struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4955117395Skan
4956117395Skan  if (regexp == NULL || regexp->mode != rm_oneof)
4957117395Skan    return;
4958132718Skan  /* Store all unit usages in the regexp:  */
4959132718Skan  obstack_init (&unit_usages);
4960169689Skan  cycle_alt_unit_usages = 0;
4961169689Skan
4962117395Skan  for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4963117395Skan    {
4964117395Skan      seq = REGEXP_ONEOF (regexp)->regexps [i];
4965169689Skan      switch (seq->mode)
4966169689Skan	{
4967169689Skan	case rm_sequence:
4968169689Skan	  for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4969169689Skan	    {
4970169689Skan	      allof = REGEXP_SEQUENCE (seq)->regexps [j];
4971169689Skan	      switch (allof->mode)
4972117395Skan		{
4973169689Skan		case rm_allof:
4974169689Skan		  for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4975169689Skan		    {
4976169689Skan		      unit = REGEXP_ALLOF (allof)->regexps [k];
4977169689Skan		      if (unit->mode == rm_unit)
4978169689Skan			store_alt_unit_usage (regexp, unit, j, i);
4979169689Skan		      else
4980169689Skan			gcc_assert (unit->mode == rm_nothing);
4981169689Skan		    }
4982169689Skan		  break;
4983169689Skan
4984169689Skan		case rm_unit:
4985169689Skan		  store_alt_unit_usage (regexp, allof, j, i);
4986169689Skan		  break;
4987169689Skan
4988169689Skan		case rm_nothing:
4989169689Skan		  break;
4990169689Skan
4991169689Skan		default:
4992169689Skan		  gcc_unreachable ();
4993117395Skan		}
4994169689Skan	    }
4995169689Skan	  break;
4996169689Skan
4997169689Skan	case rm_allof:
4998169689Skan	  for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
4999169689Skan	    {
5000169689Skan	      unit = REGEXP_ALLOF (seq)->regexps [k];
5001169689Skan	      switch (unit->mode)
5002169689Skan		{
5003169689Skan		case rm_unit:
5004169689Skan		  store_alt_unit_usage (regexp, unit, 0, i);
5005169689Skan		  break;
5006169689Skan
5007169689Skan		case rm_nothing:
5008169689Skan		  break;
5009169689Skan
5010169689Skan		default:
5011169689Skan		  gcc_unreachable ();
5012169689Skan		}
5013169689Skan	    }
5014169689Skan	  break;
5015169689Skan
5016169689Skan	case rm_unit:
5017169689Skan	  store_alt_unit_usage (regexp, seq, 0, i);
5018169689Skan	  break;
5019169689Skan
5020169689Skan	case rm_nothing:
5021169689Skan	  break;
5022169689Skan
5023169689Skan	default:
5024169689Skan	  gcc_unreachable ();
5025169689Skan	}
5026117395Skan    }
5027132718Skan  /* Check distribution:  */
5028169689Skan  for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5029117395Skan    {
5030132718Skan      cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5031169689Skan      for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5032132718Skan	   unit_usage_ptr != NULL;
5033132718Skan	   unit_usage_ptr = unit_usage_ptr->next)
5034132718Skan	if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5035132718Skan	  {
5036132718Skan	    unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5037132718Skan	    for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5038169689Skan		 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5039132718Skan		   && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5040132718Skan		 k++)
5041132718Skan	      {
5042169689Skan		for (other_unit_usage_ptr
5043169689Skan		       = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5044132718Skan		     other_unit_usage_ptr != NULL;
5045132718Skan		     other_unit_usage_ptr = other_unit_usage_ptr->next)
5046132718Skan		  if (unit_usage_ptr->unit_decl->automaton_decl
5047132718Skan		      == other_unit_usage_ptr->unit_decl->automaton_decl)
5048132718Skan		    break;
5049132718Skan		if (other_unit_usage_ptr == NULL
5050169689Skan		    && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5051169689Skan			!= NULL))
5052132718Skan		  break;
5053132718Skan	      }
5054169689Skan	    if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5055132718Skan		&& k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5056132718Skan	      {
5057132718Skan		if (!annotation_message_reported_p)
5058132718Skan		  {
5059132718Skan		    fprintf (stderr, "\n");
5060132718Skan		    error ("The following units do not satisfy units-automata distribution rule");
5061132718Skan		    error (" (A unit of given unit automaton should be on each reserv. altern.)");
5062132718Skan		    annotation_message_reported_p = TRUE;
5063132718Skan		  }
5064132718Skan		error ("Unit %s, reserv. %s, cycle %d",
5065132718Skan		       unit_usage_ptr->unit_decl->name, insn_reserv_name,
5066132718Skan		       cycle);
5067132718Skan	      }
5068132718Skan	  }
5069117395Skan    }
5070169689Skan  VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5071132718Skan  obstack_free (&unit_usages, NULL);
5072117395Skan}
5073117395Skan
5074132718Skan/* The function finds units which violates units to automata
5075132718Skan   distribution rule.  If the units exist, report about them.  */
5076117395Skanstatic void
5077132718Skancheck_unit_distributions_to_automata (void)
5078117395Skan{
5079117395Skan  decl_t decl;
5080117395Skan  int i;
5081117395Skan
5082132718Skan  if (progress_flag)
5083132718Skan    fprintf (stderr, "Check unit distributions to automata...");
5084132718Skan  annotation_message_reported_p = FALSE;
5085117395Skan  for (i = 0; i < description->decls_num; i++)
5086117395Skan    {
5087117395Skan      decl = description->decls [i];
5088132718Skan      if (decl->mode == dm_insn_reserv)
5089132718Skan	check_regexp_units_distribution
5090132718Skan	  (DECL_INSN_RESERV (decl)->name,
5091132718Skan	   DECL_INSN_RESERV (decl)->transformed_regexp);
5092117395Skan    }
5093132718Skan  if (progress_flag)
5094132718Skan    fprintf (stderr, "done\n");
5095117395Skan}
5096117395Skan
5097117395Skan
5098117395Skan
5099117395Skan/* The page contains code for building alt_states (see comments for
5100117395Skan   IR) describing all possible insns reservations of an automaton.  */
5101117395Skan
5102117395Skan/* Current state being formed for which the current alt_state
5103117395Skan   refers.  */
5104117395Skanstatic state_t state_being_formed;
5105117395Skan
5106117395Skan/* Current alt_state being formed.  */
5107117395Skanstatic alt_state_t alt_state_being_formed;
5108132718Skan
5109117395Skan/* This recursive function processes `,' and units in reservation
5110117395Skan   REGEXP for forming alt_states of AUTOMATON.  It is believed that
5111117395Skan   CURR_CYCLE is start cycle of all reservation REGEXP.  */
5112117395Skanstatic int
5113132718Skanprocess_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5114132718Skan				int curr_cycle)
5115117395Skan{
5116117395Skan  int i;
5117117395Skan
5118117395Skan  if (regexp == NULL)
5119117395Skan    return curr_cycle;
5120169689Skan
5121169689Skan  switch (regexp->mode)
5122117395Skan    {
5123169689Skan    case rm_unit:
5124117395Skan      if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5125117395Skan          == automaton->automaton_order_num)
5126117395Skan        set_state_reserv (state_being_formed, curr_cycle,
5127117395Skan                          REGEXP_UNIT (regexp)->unit_decl->unit_num);
5128117395Skan      return curr_cycle;
5129169689Skan
5130169689Skan    case rm_sequence:
5131117395Skan      for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5132117395Skan	curr_cycle
5133117395Skan	  = process_seq_for_forming_states
5134117395Skan	    (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5135117395Skan      return curr_cycle;
5136117395Skan
5137169689Skan    case rm_allof:
5138169689Skan      {
5139169689Skan	int finish_cycle = 0;
5140169689Skan	int cycle;
5141169689Skan
5142169689Skan	for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5143169689Skan	  {
5144169689Skan	    cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5145169689Skan						    ->regexps [i],
5146169689Skan						    automaton, curr_cycle);
5147169689Skan	    if (finish_cycle < cycle)
5148169689Skan	      finish_cycle = cycle;
5149169689Skan	  }
5150169689Skan	return finish_cycle;
5151169689Skan      }
5152169689Skan
5153169689Skan    case rm_nothing:
5154117395Skan      return curr_cycle;
5155169689Skan
5156169689Skan    default:
5157169689Skan      gcc_unreachable ();
5158117395Skan    }
5159117395Skan}
5160117395Skan
5161117395Skan/* This recursive function finishes forming ALT_STATE of AUTOMATON and
5162117395Skan   inserts alt_state into the table.  */
5163117395Skanstatic void
5164132718Skanfinish_forming_alt_state (alt_state_t alt_state,
5165132718Skan			  automaton_t automaton ATTRIBUTE_UNUSED)
5166117395Skan{
5167117395Skan  state_t state_in_table;
5168117395Skan  state_t corresponding_state;
5169117395Skan
5170117395Skan  corresponding_state = alt_state->state;
5171117395Skan  state_in_table = insert_state (corresponding_state);
5172117395Skan  if (state_in_table != corresponding_state)
5173117395Skan    {
5174117395Skan      free_state (corresponding_state);
5175117395Skan      alt_state->state = state_in_table;
5176117395Skan    }
5177117395Skan}
5178117395Skan
5179117395Skan/* The following variable value is current automaton insn for whose
5180117395Skan   reservation the alt states are created.  */
5181117395Skanstatic ainsn_t curr_ainsn;
5182117395Skan
5183117395Skan/* This recursive function processes `|' in reservation REGEXP for
5184117395Skan   forming alt_states of AUTOMATON.  List of the alt states should
5185117395Skan   have the same order as in the description.  */
5186117395Skanstatic void
5187132718Skanprocess_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5188132718Skan				 int inside_oneof_p)
5189117395Skan{
5190117395Skan  int i;
5191117395Skan
5192117395Skan  if (regexp->mode != rm_oneof)
5193117395Skan    {
5194117395Skan      alt_state_being_formed = get_free_alt_state ();
5195117395Skan      state_being_formed = get_free_state (1, automaton);
5196117395Skan      alt_state_being_formed->state = state_being_formed;
5197117395Skan      /* We inserts in reverse order but we process alternatives also
5198117395Skan         in reverse order.  So we have the same order of alternative
5199117395Skan         as in the description.  */
5200117395Skan      alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5201117395Skan      curr_ainsn->alt_states = alt_state_being_formed;
5202117395Skan      (void) process_seq_for_forming_states (regexp, automaton, 0);
5203117395Skan      finish_forming_alt_state (alt_state_being_formed, automaton);
5204117395Skan    }
5205117395Skan  else
5206117395Skan    {
5207169689Skan      gcc_assert (!inside_oneof_p);
5208117395Skan      /* We processes it in reverse order to get list with the same
5209117395Skan	 order as in the description.  See also the previous
5210117395Skan	 commentary.  */
5211117395Skan      for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5212117395Skan	process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5213117395Skan					 automaton, 1);
5214117395Skan    }
5215117395Skan}
5216117395Skan
5217117395Skan/* Create nodes alt_state for all AUTOMATON insns.  */
5218117395Skanstatic void
5219132718Skancreate_alt_states (automaton_t automaton)
5220117395Skan{
5221117395Skan  struct insn_reserv_decl *reserv_decl;
5222117395Skan
5223117395Skan  for (curr_ainsn = automaton->ainsn_list;
5224117395Skan       curr_ainsn != NULL;
5225117395Skan       curr_ainsn = curr_ainsn->next_ainsn)
5226117395Skan    {
5227117395Skan      reserv_decl = curr_ainsn->insn_reserv_decl;
5228117395Skan      if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5229117395Skan        {
5230117395Skan          curr_ainsn->alt_states = NULL;
5231117395Skan          process_alts_for_forming_states (reserv_decl->transformed_regexp,
5232117395Skan					   automaton, 0);
5233117395Skan          curr_ainsn->sorted_alt_states
5234117395Skan	    = uniq_sort_alt_states (curr_ainsn->alt_states);
5235117395Skan        }
5236117395Skan    }
5237117395Skan}
5238117395Skan
5239117395Skan
5240117395Skan
5241117395Skan/* The page contains major code for building DFA(s) for fast pipeline
5242117395Skan   hazards recognition.  */
5243117395Skan
5244117395Skan/* The function forms list of ainsns of AUTOMATON with the same
5245117395Skan   reservation.  */
5246169689Skan
5247117395Skanstatic void
5248132718Skanform_ainsn_with_same_reservs (automaton_t automaton)
5249117395Skan{
5250117395Skan  ainsn_t curr_ainsn;
5251117395Skan  size_t i;
5252169689Skan  VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5253117395Skan
5254117395Skan  for (curr_ainsn = automaton->ainsn_list;
5255117395Skan       curr_ainsn != NULL;
5256117395Skan       curr_ainsn = curr_ainsn->next_ainsn)
5257117395Skan    if (curr_ainsn->insn_reserv_decl
5258117395Skan	== DECL_INSN_RESERV (advance_cycle_insn_decl))
5259117395Skan      {
5260117395Skan        curr_ainsn->next_same_reservs_insn = NULL;
5261117395Skan        curr_ainsn->first_insn_with_same_reservs = 1;
5262117395Skan      }
5263117395Skan    else
5264117395Skan      {
5265169689Skan        for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5266117395Skan          if (alt_states_eq
5267117395Skan              (curr_ainsn->sorted_alt_states,
5268169689Skan               VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5269117395Skan            break;
5270117395Skan        curr_ainsn->next_same_reservs_insn = NULL;
5271169689Skan        if (i < VEC_length (ainsn_t, last_insns))
5272117395Skan          {
5273117395Skan            curr_ainsn->first_insn_with_same_reservs = 0;
5274169689Skan	    VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5275117395Skan	      = curr_ainsn;
5276169689Skan            VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5277117395Skan          }
5278117395Skan        else
5279117395Skan          {
5280169689Skan            VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5281117395Skan            curr_ainsn->first_insn_with_same_reservs = 1;
5282117395Skan          }
5283117395Skan      }
5284169689Skan  VEC_free (ainsn_t,heap, last_insns);
5285117395Skan}
5286117395Skan
5287132718Skan/* Forming unit reservations which can affect creating the automaton
5288132718Skan   states achieved from a given state.  It permits to build smaller
5289132718Skan   automata in many cases.  We would have the same automata after
5290132718Skan   the minimization without such optimization, but the automaton
5291132718Skan   right after the building could be huge.  So in other words, usage
5292132718Skan   of reservs_matter means some minimization during building the
5293132718Skan   automaton.  */
5294132718Skanstatic reserv_sets_t
5295132718Skanform_reservs_matter (automaton_t automaton)
5296132718Skan{
5297132718Skan  int cycle, unit;
5298132718Skan  reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5299132718Skan
5300132718Skan  for (cycle = 0; cycle < max_cycles_num; cycle++)
5301132718Skan    for (unit = 0; unit < description->units_num; unit++)
5302132718Skan      if (units_array [unit]->automaton_decl
5303132718Skan	  == automaton->corresponding_automaton_decl
5304132718Skan	  && (cycle >= units_array [unit]->min_occ_cycle_num
5305132718Skan	      /* We can not remove queried unit from reservations.  */
5306132718Skan	      || units_array [unit]->query_p
5307132718Skan	      /* We can not remove units which are used
5308132718Skan		 `exclusion_set', `presence_set',
5309132718Skan		 `final_presence_set', `absence_set', and
5310132718Skan		 `final_absence_set'.  */
5311132718Skan	      || units_array [unit]->in_set_p))
5312132718Skan	set_unit_reserv (reservs_matter, cycle, unit);
5313132718Skan  return reservs_matter;
5314132718Skan}
5315132718Skan
5316169689Skan/* The following function creates all states of nondeterministic AUTOMATON.  */
5317117395Skanstatic void
5318132718Skanmake_automaton (automaton_t automaton)
5319117395Skan{
5320117395Skan  ainsn_t ainsn;
5321117395Skan  struct insn_reserv_decl *insn_reserv_decl;
5322117395Skan  alt_state_t alt_state;
5323117395Skan  state_t state;
5324117395Skan  state_t start_state;
5325117395Skan  state_t state2;
5326117395Skan  ainsn_t advance_cycle_ainsn;
5327117395Skan  arc_t added_arc;
5328169689Skan  VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5329132718Skan  int states_n;
5330132718Skan  reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5331117395Skan
5332117395Skan  /* Create the start state (empty state).  */
5333117395Skan  start_state = insert_state (get_free_state (1, automaton));
5334117395Skan  automaton->start_state = start_state;
5335117395Skan  start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5336169689Skan  VEC_safe_push (state_t,heap, state_stack, start_state);
5337132718Skan  states_n = 1;
5338169689Skan  while (VEC_length (state_t, state_stack) != 0)
5339117395Skan    {
5340169689Skan      state = VEC_pop (state_t, state_stack);
5341117395Skan      advance_cycle_ainsn = NULL;
5342117395Skan      for (ainsn = automaton->ainsn_list;
5343117395Skan	   ainsn != NULL;
5344117395Skan	   ainsn = ainsn->next_ainsn)
5345117395Skan        if (ainsn->first_insn_with_same_reservs)
5346117395Skan          {
5347117395Skan            insn_reserv_decl = ainsn->insn_reserv_decl;
5348117395Skan            if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5349117395Skan              {
5350117395Skan		/* We process alt_states in the same order as they are
5351117395Skan                   present in the description.  */
5352117395Skan		added_arc = NULL;
5353117395Skan                for (alt_state = ainsn->alt_states;
5354117395Skan                     alt_state != NULL;
5355117395Skan                     alt_state = alt_state->next_alt_state)
5356117395Skan                  {
5357117395Skan                    state2 = alt_state->state;
5358117395Skan                    if (!intersected_state_reservs_p (state, state2))
5359117395Skan                      {
5360132718Skan                        state2 = states_union (state, state2, reservs_matter);
5361117395Skan                        if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5362117395Skan                          {
5363117395Skan                            state2->it_was_placed_in_stack_for_NDFA_forming
5364117395Skan			      = 1;
5365169689Skan                            VEC_safe_push (state_t,heap, state_stack, state2);
5366132718Skan			    states_n++;
5367132718Skan			    if (progress_flag && states_n % 100 == 0)
5368132718Skan			      fprintf (stderr, ".");
5369117395Skan                          }
5370169689Skan			added_arc = add_arc (state, state2, ainsn);
5371117395Skan			if (!ndfa_flag)
5372117395Skan			  break;
5373117395Skan                      }
5374117395Skan                  }
5375117395Skan		if (!ndfa_flag && added_arc != NULL)
5376117395Skan		  {
5377117395Skan		    for (alt_state = ainsn->alt_states;
5378117395Skan			 alt_state != NULL;
5379117395Skan			 alt_state = alt_state->next_alt_state)
5380169689Skan		      state2 = alt_state->state;
5381117395Skan		  }
5382117395Skan              }
5383117395Skan            else
5384117395Skan              advance_cycle_ainsn = ainsn;
5385117395Skan          }
5386117395Skan      /* Add transition to advance cycle.  */
5387132718Skan      state2 = state_shift (state, reservs_matter);
5388117395Skan      if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5389117395Skan        {
5390117395Skan          state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5391169689Skan          VEC_safe_push (state_t,heap, state_stack, state2);
5392132718Skan	  states_n++;
5393132718Skan	  if (progress_flag && states_n % 100 == 0)
5394132718Skan	    fprintf (stderr, ".");
5395117395Skan        }
5396169689Skan      gcc_assert (advance_cycle_ainsn);
5397169689Skan      add_arc (state, state2, advance_cycle_ainsn);
5398117395Skan    }
5399169689Skan  VEC_free (state_t,heap, state_stack);
5400117395Skan}
5401117395Skan
5402117395Skan/* Foms lists of all arcs of STATE marked by the same ainsn.  */
5403117395Skanstatic void
5404132718Skanform_arcs_marked_by_insn (state_t state)
5405117395Skan{
5406117395Skan  decl_t decl;
5407117395Skan  arc_t arc;
5408117395Skan  int i;
5409117395Skan
5410117395Skan  for (i = 0; i < description->decls_num; i++)
5411117395Skan    {
5412117395Skan      decl = description->decls [i];
5413117395Skan      if (decl->mode == dm_insn_reserv)
5414117395Skan	DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5415117395Skan    }
5416117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5417117395Skan    {
5418169689Skan      gcc_assert (arc->insn);
5419117395Skan      arc->next_arc_marked_by_insn
5420117395Skan	= arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5421117395Skan      arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5422117395Skan    }
5423117395Skan}
5424117395Skan
5425117395Skan/* The function creates composed state (see comments for IR) from
5426117395Skan   ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5427117395Skan   same insn.  If the composed state is not in STATE_STACK yet, it is
5428132718Skan   pushed into STATE_STACK.  */
5429169689Skan
5430132718Skanstatic int
5431132718Skancreate_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5432169689Skan		       VEC(state_t,heap) **state_stack)
5433117395Skan{
5434117395Skan  state_t state;
5435132718Skan  alt_state_t alt_state, curr_alt_state;
5436117395Skan  alt_state_t new_alt_state;
5437117395Skan  arc_t curr_arc;
5438117395Skan  arc_t next_arc;
5439117395Skan  state_t state_in_table;
5440117395Skan  state_t temp_state;
5441117395Skan  alt_state_t canonical_alt_states_list;
5442117395Skan  int alts_number;
5443132718Skan  int new_state_p = 0;
5444117395Skan
5445117395Skan  if (arcs_marked_by_insn == NULL)
5446132718Skan    return new_state_p;
5447117395Skan  if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5448117395Skan    state = arcs_marked_by_insn->to_state;
5449117395Skan  else
5450117395Skan    {
5451169689Skan      gcc_assert (ndfa_flag);
5452117395Skan      /* Create composed state.  */
5453117395Skan      state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5454117395Skan      curr_alt_state = NULL;
5455117395Skan      for (curr_arc = arcs_marked_by_insn;
5456117395Skan           curr_arc != NULL;
5457117395Skan           curr_arc = curr_arc->next_arc_marked_by_insn)
5458132718Skan	if (curr_arc->to_state->component_states == NULL)
5459132718Skan	  {
5460132718Skan	    new_alt_state = get_free_alt_state ();
5461132718Skan	    new_alt_state->next_alt_state = curr_alt_state;
5462132718Skan	    new_alt_state->state = curr_arc->to_state;
5463132718Skan	    curr_alt_state = new_alt_state;
5464132718Skan	  }
5465132718Skan	else
5466132718Skan	  for (alt_state = curr_arc->to_state->component_states;
5467132718Skan	       alt_state != NULL;
5468132718Skan	       alt_state = alt_state->next_sorted_alt_state)
5469132718Skan	    {
5470132718Skan	      new_alt_state = get_free_alt_state ();
5471132718Skan	      new_alt_state->next_alt_state = curr_alt_state;
5472132718Skan	      new_alt_state->state = alt_state->state;
5473169689Skan	      gcc_assert (!alt_state->state->component_states);
5474132718Skan	      curr_alt_state = new_alt_state;
5475132718Skan	    }
5476117395Skan      /* There are not identical sets in the alt state list.  */
5477117395Skan      canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5478117395Skan      if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5479117395Skan        {
5480117395Skan          temp_state = state;
5481117395Skan          state = canonical_alt_states_list->state;
5482117395Skan          free_state (temp_state);
5483117395Skan        }
5484117395Skan      else
5485117395Skan        {
5486117395Skan          state->component_states = canonical_alt_states_list;
5487117395Skan          state_in_table = insert_state (state);
5488117395Skan          if (state_in_table != state)
5489117395Skan            {
5490169689Skan              gcc_assert
5491169689Skan		(state_in_table->it_was_placed_in_stack_for_DFA_forming);
5492117395Skan              free_state (state);
5493117395Skan              state = state_in_table;
5494117395Skan            }
5495117395Skan          else
5496117395Skan            {
5497169689Skan              gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5498132718Skan	      new_state_p = 1;
5499117395Skan              for (curr_alt_state = state->component_states;
5500117395Skan                   curr_alt_state != NULL;
5501117395Skan                   curr_alt_state = curr_alt_state->next_sorted_alt_state)
5502117395Skan                for (curr_arc = first_out_arc (curr_alt_state->state);
5503117395Skan                     curr_arc != NULL;
5504117395Skan                     curr_arc = next_out_arc (curr_arc))
5505169689Skan		  add_arc (state, curr_arc->to_state, curr_arc->insn);
5506117395Skan            }
5507117395Skan          arcs_marked_by_insn->to_state = state;
5508117395Skan          for (alts_number = 0,
5509117395Skan	       curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5510117395Skan               curr_arc != NULL;
5511117395Skan               curr_arc = next_arc)
5512117395Skan            {
5513117395Skan              next_arc = curr_arc->next_arc_marked_by_insn;
5514117395Skan              remove_arc (original_state, curr_arc);
5515117395Skan	      alts_number++;
5516117395Skan            }
5517117395Skan        }
5518117395Skan    }
5519117395Skan  if (!state->it_was_placed_in_stack_for_DFA_forming)
5520117395Skan    {
5521117395Skan      state->it_was_placed_in_stack_for_DFA_forming = 1;
5522169689Skan      VEC_safe_push (state_t,heap, *state_stack, state);
5523117395Skan    }
5524132718Skan  return new_state_p;
5525117395Skan}
5526117395Skan
5527132718Skan/* The function transforms nondeterministic AUTOMATON into
5528117395Skan   deterministic.  */
5529169689Skan
5530117395Skanstatic void
5531132718SkanNDFA_to_DFA (automaton_t automaton)
5532117395Skan{
5533117395Skan  state_t start_state;
5534117395Skan  state_t state;
5535117395Skan  decl_t decl;
5536169689Skan  VEC(state_t,heap) *state_stack;
5537117395Skan  int i;
5538132718Skan  int states_n;
5539117395Skan
5540169689Skan  state_stack = VEC_alloc (state_t,heap, 0);
5541169689Skan
5542117395Skan  /* Create the start state (empty state).  */
5543117395Skan  start_state = automaton->start_state;
5544117395Skan  start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5545169689Skan  VEC_safe_push (state_t,heap, state_stack, start_state);
5546132718Skan  states_n = 1;
5547169689Skan  while (VEC_length (state_t, state_stack) != 0)
5548117395Skan    {
5549169689Skan      state = VEC_pop (state_t, state_stack);
5550117395Skan      form_arcs_marked_by_insn (state);
5551117395Skan      for (i = 0; i < description->decls_num; i++)
5552117395Skan	{
5553117395Skan	  decl = description->decls [i];
5554132718Skan	  if (decl->mode == dm_insn_reserv
5555132718Skan	      && create_composed_state
5556132718Skan	         (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5557132718Skan		  &state_stack))
5558132718Skan	    {
5559132718Skan	      states_n++;
5560132718Skan	      if (progress_flag && states_n % 100 == 0)
5561132718Skan		fprintf (stderr, ".");
5562132718Skan	    }
5563117395Skan	}
5564117395Skan    }
5565169689Skan  VEC_free (state_t,heap, state_stack);
5566117395Skan}
5567117395Skan
5568117395Skan/* The following variable value is current number (1, 2, ...) of passing
5569117395Skan   graph of states.  */
5570117395Skanstatic int curr_state_graph_pass_num;
5571117395Skan
5572117395Skan/* This recursive function passes all states achieved from START_STATE
5573117395Skan   and applies APPLIED_FUNC to them.  */
5574117395Skanstatic void
5575132718Skanpass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5576117395Skan{
5577117395Skan  arc_t arc;
5578117395Skan
5579117395Skan  if (start_state->pass_num == curr_state_graph_pass_num)
5580117395Skan    return;
5581117395Skan  start_state->pass_num = curr_state_graph_pass_num;
5582117395Skan  (*applied_func) (start_state);
5583117395Skan  for (arc = first_out_arc (start_state);
5584117395Skan       arc != NULL;
5585117395Skan       arc = next_out_arc (arc))
5586117395Skan    pass_state_graph (arc->to_state, applied_func);
5587117395Skan}
5588117395Skan
5589117395Skan/* This recursive function passes all states of AUTOMATON and applies
5590117395Skan   APPLIED_FUNC to them.  */
5591117395Skanstatic void
5592132718Skanpass_states (automaton_t automaton, void (*applied_func) (state_t state))
5593117395Skan{
5594117395Skan  curr_state_graph_pass_num++;
5595117395Skan  pass_state_graph (automaton->start_state, applied_func);
5596117395Skan}
5597117395Skan
5598117395Skan/* The function initializes code for passing of all states.  */
5599117395Skanstatic void
5600132718Skaninitiate_pass_states (void)
5601117395Skan{
5602117395Skan  curr_state_graph_pass_num = 0;
5603117395Skan}
5604117395Skan
5605117395Skan/* The following vla is used for storing pointers to all achieved
5606117395Skan   states.  */
5607169689Skanstatic VEC(state_t,heap) *all_achieved_states;
5608117395Skan
5609117395Skan/* This function is called by function pass_states to add an achieved
5610117395Skan   STATE.  */
5611117395Skanstatic void
5612132718Skanadd_achieved_state (state_t state)
5613117395Skan{
5614169689Skan  VEC_safe_push (state_t,heap, all_achieved_states, state);
5615117395Skan}
5616117395Skan
5617117395Skan/* The function sets up equivalence numbers of insns which mark all
5618117395Skan   out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5619117395Skan   nonzero value) or by equiv_class_num_2 of the destination state.
5620117395Skan   The function returns number of out arcs of STATE.  */
5621169689Skanstatic void
5622132718Skanset_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5623117395Skan{
5624117395Skan  arc_t arc;
5625117395Skan
5626117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5627117395Skan    {
5628169689Skan      gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5629117395Skan      arc->insn->insn_reserv_decl->equiv_class_num
5630117395Skan	= (odd_iteration_flag
5631117395Skan           ? arc->to_state->equiv_class_num_1
5632117395Skan	   : arc->to_state->equiv_class_num_2);
5633169689Skan      gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5634117395Skan    }
5635117395Skan}
5636117395Skan
5637117395Skan/* The function clears equivalence numbers and alt_states in all insns
5638117395Skan   which mark all out arcs of STATE.  */
5639117395Skanstatic void
5640132718Skanclear_arc_insns_equiv_num (state_t state)
5641117395Skan{
5642117395Skan  arc_t arc;
5643117395Skan
5644117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5645169689Skan    arc->insn->insn_reserv_decl->equiv_class_num = 0;
5646117395Skan}
5647117395Skan
5648117395Skan
5649132718Skan/* The following function returns TRUE if STATE reserves the unit with
5650132718Skan   UNIT_NUM on the first cycle.  */
5651132718Skanstatic int
5652132718Skanfirst_cycle_unit_presence (state_t state, int unit_num)
5653132718Skan{
5654169689Skan  alt_state_t alt_state;
5655132718Skan
5656132718Skan  if (state->component_states == NULL)
5657169689Skan    return test_unit_reserv (state->reservs, 0, unit_num);
5658132718Skan  else
5659169689Skan    {
5660169689Skan      for (alt_state = state->component_states;
5661169689Skan	   alt_state != NULL;
5662169689Skan	   alt_state = alt_state->next_sorted_alt_state)
5663169689Skan	if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5664169689Skan	  return true;
5665169689Skan    }
5666169689Skan  return false;
5667132718Skan}
5668132718Skan
5669169689Skan/* This fills in the presence_signature[] member of STATE.  */
5670169689Skanstatic void
5671169689Skancache_presence (state_t state)
5672169689Skan{
5673169689Skan  int i, num = 0;
5674169689Skan  unsigned int sz;
5675169689Skan  sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5676169689Skan        / (sizeof (int) * CHAR_BIT);
5677169689Skan
5678169689Skan  state->presence_signature = create_node (sz * sizeof (int));
5679169689Skan  for (i = 0; i < description->units_num; i++)
5680169689Skan    if (units_array [i]->query_p)
5681169689Skan      {
5682169689Skan	int presence1_p = first_cycle_unit_presence (state, i);
5683169689Skan	state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5684169689Skan	  |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5685169689Skan	num++;
5686169689Skan      }
5687169689Skan}
5688169689Skan
5689117395Skan/* The function returns nonzero value if STATE is not equivalent to
5690132718Skan   ANOTHER_STATE from the same current partition on equivalence
5691132718Skan   classes.  Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5692117395Skan   output arcs.  Iteration of making equivalence partition is defined
5693117395Skan   by ODD_ITERATION_FLAG.  */
5694117395Skanstatic int
5695132718Skanstate_is_differed (state_t state, state_t another_state,
5696169689Skan		   int odd_iteration_flag)
5697117395Skan{
5698117395Skan  arc_t arc;
5699169689Skan  unsigned int sz, si;
5700117395Skan
5701169689Skan  gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5702169689Skan
5703169689Skan  sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5704169689Skan	/ (sizeof (int) * CHAR_BIT);
5705169689Skan
5706169689Skan  for (si = 0; si < sz; si++)
5707169689Skan    gcc_assert (state->presence_signature[si]
5708169689Skan		== another_state->presence_signature[si]);
5709169689Skan
5710117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5711117395Skan    {
5712117395Skan      if ((odd_iteration_flag
5713117395Skan           ? arc->to_state->equiv_class_num_1
5714117395Skan	   : arc->to_state->equiv_class_num_2)
5715169689Skan          != arc->insn->insn_reserv_decl->equiv_class_num)
5716117395Skan        return 1;
5717117395Skan    }
5718169689Skan
5719169689Skan  return 0;
5720169689Skan}
5721169689Skan
5722169689Skan/* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5723169689Skan   and return -1, 0 or 1.  This function can be used as predicate for
5724169689Skan   qsort().  It requires the member presence_signature[] of both
5725169689Skan   states be filled.  */
5726169689Skanstatic int
5727169689Skancompare_states_for_equiv (const void *state_ptr_1,
5728169689Skan			  const void *state_ptr_2)
5729169689Skan{
5730169689Skan  state_t s1 = *(state_t *)state_ptr_1;
5731169689Skan  state_t s2 = *(state_t *)state_ptr_2;
5732169689Skan  unsigned int sz, si;
5733169689Skan  if (s1->num_out_arcs < s2->num_out_arcs)
5734169689Skan    return -1;
5735169689Skan  else if (s1->num_out_arcs > s2->num_out_arcs)
5736132718Skan    return 1;
5737169689Skan
5738169689Skan  sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5739169689Skan	/ (sizeof (int) * CHAR_BIT);
5740169689Skan
5741169689Skan  for (si = 0; si < sz; si++)
5742169689Skan    if (s1->presence_signature[si] < s2->presence_signature[si])
5743169689Skan      return -1;
5744169689Skan    else if (s1->presence_signature[si] > s2->presence_signature[si])
5745169689Skan      return 1;
5746132718Skan  return 0;
5747117395Skan}
5748117395Skan
5749117395Skan/* The function makes initial partition of STATES on equivalent
5750169689Skan   classes and saves it into *CLASSES.  This function requires the input
5751169689Skan   to be sorted via compare_states_for_equiv().  */
5752169689Skanstatic int
5753169689Skaninit_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5754117395Skan{
5755169689Skan  size_t i;
5756169689Skan  state_t prev = 0;
5757169689Skan  int class_num = 1;
5758117395Skan
5759169689Skan  *classes = VEC_alloc (state_t,heap, 150);
5760169689Skan  for (i = 0; i < VEC_length (state_t, states); i++)
5761117395Skan    {
5762169689Skan      state_t state = VEC_index (state_t, states, i);
5763169689Skan      if (prev)
5764169689Skan        {
5765169689Skan	  if (compare_states_for_equiv (&prev, &state) != 0)
5766169689Skan	    {
5767169689Skan	      VEC_safe_push (state_t,heap, *classes, prev);
5768169689Skan	      class_num++;
5769169689Skan	      prev = NULL;
5770169689Skan	    }
5771169689Skan        }
5772169689Skan      state->equiv_class_num_1 = class_num;
5773169689Skan      state->next_equiv_class_state = prev;
5774169689Skan      prev = state;
5775117395Skan    }
5776169689Skan  if (prev)
5777169689Skan    VEC_safe_push (state_t,heap, *classes, prev);
5778169689Skan  return class_num;
5779117395Skan}
5780117395Skan
5781169689Skan/* The function copies pointers to equivalent states from vla FROM
5782169689Skan   into vla TO.  */
5783169689Skanstatic void
5784169689Skancopy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5785169689Skan{
5786169689Skan  VEC_free (state_t,heap, *to);
5787169689Skan  *to = VEC_copy (state_t,heap, from);
5788169689Skan}
5789169689Skan
5790169689Skan/* The function processes equivalence class given by its first state,
5791169689Skan   FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG.  If there
5792132718Skan   are not equivalent states, the function partitions the class
5793117395Skan   removing nonequivalent states and placing them in
5794117395Skan   *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5795117395Skan   assigns it to the state equivalence number.  If the class has been
5796117395Skan   partitioned, the function returns nonzero value.  */
5797117395Skanstatic int
5798169689Skanpartition_equiv_class (state_t first_state, int odd_iteration_flag,
5799169689Skan		       VEC(state_t,heap) **next_iteration_classes,
5800132718Skan		       int *new_equiv_class_num_ptr)
5801117395Skan{
5802117395Skan  state_t new_equiv_class;
5803117395Skan  int partition_p;
5804117395Skan  state_t curr_state;
5805117395Skan  state_t prev_state;
5806117395Skan  state_t next_state;
5807117395Skan
5808117395Skan  partition_p = 0;
5809169689Skan
5810169689Skan  while (first_state != NULL)
5811117395Skan    {
5812117395Skan      new_equiv_class = NULL;
5813117395Skan      if (first_state->next_equiv_class_state != NULL)
5814117395Skan	{
5815117395Skan	  /* There are more one states in the class equivalence.  */
5816169689Skan	  set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5817117395Skan	  for (prev_state = first_state,
5818117395Skan		 curr_state = first_state->next_equiv_class_state;
5819117395Skan	       curr_state != NULL;
5820117395Skan	       curr_state = next_state)
5821117395Skan	    {
5822117395Skan	      next_state = curr_state->next_equiv_class_state;
5823169689Skan	      if (state_is_differed (curr_state, first_state,
5824117395Skan				     odd_iteration_flag))
5825117395Skan		{
5826117395Skan		  /* Remove curr state from the class equivalence.  */
5827117395Skan		  prev_state->next_equiv_class_state = next_state;
5828117395Skan		  /* Add curr state to the new class equivalence.  */
5829117395Skan		  curr_state->next_equiv_class_state = new_equiv_class;
5830117395Skan		  if (new_equiv_class == NULL)
5831117395Skan		    (*new_equiv_class_num_ptr)++;
5832117395Skan		  if (odd_iteration_flag)
5833117395Skan		    curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5834117395Skan		  else
5835117395Skan		    curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5836117395Skan		  new_equiv_class = curr_state;
5837117395Skan		  partition_p = 1;
5838117395Skan		}
5839117395Skan	      else
5840117395Skan		prev_state = curr_state;
5841117395Skan	    }
5842117395Skan	  clear_arc_insns_equiv_num (first_state);
5843117395Skan	}
5844117395Skan      if (new_equiv_class != NULL)
5845169689Skan	VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5846169689Skan      first_state = new_equiv_class;
5847117395Skan    }
5848117395Skan  return partition_p;
5849117395Skan}
5850117395Skan
5851117395Skan/* The function finds equivalent states of AUTOMATON.  */
5852117395Skanstatic void
5853169689Skanevaluate_equiv_classes (automaton_t automaton,
5854169689Skan			VEC(state_t,heap) **equiv_classes)
5855117395Skan{
5856117395Skan  int new_equiv_class_num;
5857117395Skan  int odd_iteration_flag;
5858117395Skan  int finish_flag;
5859169689Skan  VEC (state_t,heap) *next_iteration_classes;
5860169689Skan  size_t i;
5861132718Skan
5862169689Skan  all_achieved_states = VEC_alloc (state_t,heap, 1500);
5863117395Skan  pass_states (automaton, add_achieved_state);
5864169689Skan  pass_states (automaton, cache_presence);
5865169689Skan  qsort (VEC_address (state_t, all_achieved_states),
5866169689Skan	 VEC_length (state_t, all_achieved_states),
5867169689Skan         sizeof (state_t), compare_states_for_equiv);
5868169689Skan
5869117395Skan  odd_iteration_flag = 0;
5870169689Skan  new_equiv_class_num = init_equiv_class (all_achieved_states,
5871169689Skan  					  &next_iteration_classes);
5872169689Skan
5873117395Skan  do
5874117395Skan    {
5875117395Skan      odd_iteration_flag = !odd_iteration_flag;
5876117395Skan      finish_flag = 1;
5877169689Skan      copy_equiv_class (equiv_classes, next_iteration_classes);
5878169689Skan
5879117395Skan      /* Transfer equiv numbers for the next iteration.  */
5880169689Skan      for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5881117395Skan	if (odd_iteration_flag)
5882169689Skan	  VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5883169689Skan	    = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5884117395Skan	else
5885169689Skan	  VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5886169689Skan	    = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5887169689Skan
5888169689Skan      for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5889169689Skan	if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5890169689Skan				   odd_iteration_flag,
5891117395Skan				   &next_iteration_classes,
5892117395Skan				   &new_equiv_class_num))
5893117395Skan	  finish_flag = 0;
5894117395Skan    }
5895117395Skan  while (!finish_flag);
5896169689Skan  VEC_free (state_t,heap, next_iteration_classes);
5897169689Skan  VEC_free (state_t,heap, all_achieved_states);
5898117395Skan}
5899117395Skan
5900117395Skan/* The function merges equivalent states of AUTOMATON.  */
5901117395Skanstatic void
5902169689Skanmerge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5903117395Skan{
5904117395Skan  state_t curr_state;
5905117395Skan  state_t new_state;
5906117395Skan  state_t first_class_state;
5907117395Skan  alt_state_t alt_states;
5908132718Skan  alt_state_t alt_state, new_alt_state;
5909117395Skan  arc_t curr_arc;
5910117395Skan  arc_t next_arc;
5911169689Skan  size_t i;
5912117395Skan
5913117395Skan  /* Create states corresponding to equivalence classes containing two
5914117395Skan     or more states.  */
5915169689Skan  for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5916169689Skan    {
5917169689Skan      curr_state = VEC_index (state_t, equiv_classes, i);
5918169689Skan      if (curr_state->next_equiv_class_state != NULL)
5919169689Skan	{
5920169689Skan	  /* There are more one states in the class equivalence.  */
5921169689Skan	  /* Create new compound state.  */
5922169689Skan	  new_state = get_free_state (0, automaton);
5923169689Skan	  alt_states = NULL;
5924169689Skan	  first_class_state = curr_state;
5925169689Skan	  for (curr_state = first_class_state;
5926169689Skan	       curr_state != NULL;
5927169689Skan	       curr_state = curr_state->next_equiv_class_state)
5928169689Skan	    {
5929169689Skan	      curr_state->equiv_class_state = new_state;
5930169689Skan	      if (curr_state->component_states == NULL)
5931132718Skan		{
5932132718Skan		  new_alt_state = get_free_alt_state ();
5933169689Skan		  new_alt_state->state = curr_state;
5934132718Skan		  new_alt_state->next_alt_state = alt_states;
5935132718Skan		  alt_states = new_alt_state;
5936132718Skan		}
5937169689Skan	      else
5938169689Skan		for (alt_state = curr_state->component_states;
5939169689Skan		     alt_state != NULL;
5940169689Skan		     alt_state = alt_state->next_sorted_alt_state)
5941169689Skan		  {
5942169689Skan		    new_alt_state = get_free_alt_state ();
5943169689Skan		    new_alt_state->state = alt_state->state;
5944169689Skan		    new_alt_state->next_alt_state = alt_states;
5945169689Skan		    alt_states = new_alt_state;
5946169689Skan		  }
5947169689Skan	    }
5948169689Skan	  /* Its is important that alt states were sorted before and
5949169689Skan	     after merging to have the same querying results.  */
5950169689Skan	  new_state->component_states = uniq_sort_alt_states (alt_states);
5951169689Skan	}
5952169689Skan      else
5953169689Skan	curr_state->equiv_class_state = curr_state;
5954169689Skan    }
5955169689Skan
5956169689Skan  for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5957169689Skan    {
5958169689Skan      curr_state = VEC_index (state_t, equiv_classes, i);
5959169689Skan      if (curr_state->next_equiv_class_state != NULL)
5960169689Skan	{
5961169689Skan	  first_class_state = curr_state;
5962169689Skan	  /* Create new arcs output from the state corresponding to
5963169689Skan	     equiv class.  */
5964169689Skan	  for (curr_arc = first_out_arc (first_class_state);
5965169689Skan	       curr_arc != NULL;
5966169689Skan	       curr_arc = next_out_arc (curr_arc))
5967169689Skan	    add_arc (first_class_state->equiv_class_state,
5968169689Skan		     curr_arc->to_state->equiv_class_state,
5969169689Skan		     curr_arc->insn);
5970169689Skan	  /* Delete output arcs from states of given class equivalence.  */
5971169689Skan	  for (curr_state = first_class_state;
5972169689Skan	       curr_state != NULL;
5973169689Skan	       curr_state = curr_state->next_equiv_class_state)
5974169689Skan	    {
5975169689Skan	      if (automaton->start_state == curr_state)
5976169689Skan		automaton->start_state = curr_state->equiv_class_state;
5977169689Skan	      /* Delete the state and its output arcs.  */
5978169689Skan	      for (curr_arc = first_out_arc (curr_state);
5979169689Skan		   curr_arc != NULL;
5980169689Skan		   curr_arc = next_arc)
5981169689Skan		{
5982169689Skan		  next_arc = next_out_arc (curr_arc);
5983169689Skan		  free_arc (curr_arc);
5984169689Skan		}
5985169689Skan	    }
5986169689Skan	}
5987169689Skan      else
5988169689Skan	{
5989169689Skan	  /* Change `to_state' of arcs output from the state of given
5990169689Skan	     equivalence class.  */
5991169689Skan	  for (curr_arc = first_out_arc (curr_state);
5992169689Skan	       curr_arc != NULL;
5993169689Skan	       curr_arc = next_out_arc (curr_arc))
5994169689Skan	    curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5995169689Skan	}
5996169689Skan    }
5997117395Skan}
5998117395Skan
5999117395Skan/* The function sets up new_cycle_p for states if there is arc to the
6000117395Skan   state marked by advance_cycle_insn_decl.  */
6001117395Skanstatic void
6002132718Skanset_new_cycle_flags (state_t state)
6003117395Skan{
6004117395Skan  arc_t arc;
6005117395Skan
6006117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6007117395Skan    if (arc->insn->insn_reserv_decl
6008117395Skan	== DECL_INSN_RESERV (advance_cycle_insn_decl))
6009117395Skan      arc->to_state->new_cycle_p = 1;
6010117395Skan}
6011117395Skan
6012117395Skan/* The top level function for minimization of deterministic
6013117395Skan   AUTOMATON.  */
6014117395Skanstatic void
6015132718Skanminimize_DFA (automaton_t automaton)
6016117395Skan{
6017169689Skan  VEC(state_t,heap) *equiv_classes = 0;
6018117395Skan
6019117395Skan  evaluate_equiv_classes (automaton, &equiv_classes);
6020169689Skan  merge_states (automaton, equiv_classes);
6021117395Skan  pass_states (automaton, set_new_cycle_flags);
6022169689Skan
6023169689Skan  VEC_free (state_t,heap, equiv_classes);
6024117395Skan}
6025117395Skan
6026117395Skan/* Values of two variables are counted number of states and arcs in an
6027117395Skan   automaton.  */
6028117395Skanstatic int curr_counted_states_num;
6029117395Skanstatic int curr_counted_arcs_num;
6030117395Skan
6031117395Skan/* The function is called by function `pass_states' to count states
6032117395Skan   and arcs of an automaton.  */
6033117395Skanstatic void
6034132718Skanincr_states_and_arcs_nums (state_t state)
6035117395Skan{
6036117395Skan  arc_t arc;
6037117395Skan
6038117395Skan  curr_counted_states_num++;
6039117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6040117395Skan    curr_counted_arcs_num++;
6041117395Skan}
6042117395Skan
6043117395Skan/* The function counts states and arcs of AUTOMATON.  */
6044117395Skanstatic void
6045132718Skancount_states_and_arcs (automaton_t automaton, int *states_num,
6046132718Skan		       int *arcs_num)
6047117395Skan{
6048117395Skan  curr_counted_states_num = 0;
6049117395Skan  curr_counted_arcs_num = 0;
6050117395Skan  pass_states (automaton, incr_states_and_arcs_nums);
6051117395Skan  *states_num = curr_counted_states_num;
6052117395Skan  *arcs_num = curr_counted_arcs_num;
6053117395Skan}
6054117395Skan
6055117395Skan/* The function builds one DFA AUTOMATON for fast pipeline hazards
6056117395Skan   recognition after checking and simplifying IR of the
6057117395Skan   description.  */
6058117395Skanstatic void
6059132718Skanbuild_automaton (automaton_t automaton)
6060117395Skan{
6061117395Skan  int states_num;
6062117395Skan  int arcs_num;
6063117395Skan
6064117395Skan  ticker_on (&NDFA_time);
6065132718Skan  if (progress_flag)
6066132718Skan    {
6067132718Skan      if (automaton->corresponding_automaton_decl == NULL)
6068132718Skan	fprintf (stderr, "Create anonymous automaton");
6069132718Skan      else
6070132718Skan	fprintf (stderr, "Create automaton `%s'",
6071132718Skan		 automaton->corresponding_automaton_decl->name);
6072132718Skan      fprintf (stderr, " (1 dot is 100 new states):");
6073132718Skan    }
6074117395Skan  make_automaton (automaton);
6075132718Skan  if (progress_flag)
6076132718Skan    fprintf (stderr, " done\n");
6077117395Skan  ticker_off (&NDFA_time);
6078117395Skan  count_states_and_arcs (automaton, &states_num, &arcs_num);
6079117395Skan  automaton->NDFA_states_num = states_num;
6080117395Skan  automaton->NDFA_arcs_num = arcs_num;
6081117395Skan  ticker_on (&NDFA_to_DFA_time);
6082132718Skan  if (progress_flag)
6083132718Skan    {
6084132718Skan      if (automaton->corresponding_automaton_decl == NULL)
6085132718Skan	fprintf (stderr, "Make anonymous DFA");
6086132718Skan      else
6087132718Skan	fprintf (stderr, "Make DFA `%s'",
6088132718Skan		 automaton->corresponding_automaton_decl->name);
6089132718Skan      fprintf (stderr, " (1 dot is 100 new states):");
6090132718Skan    }
6091117395Skan  NDFA_to_DFA (automaton);
6092132718Skan  if (progress_flag)
6093132718Skan    fprintf (stderr, " done\n");
6094117395Skan  ticker_off (&NDFA_to_DFA_time);
6095117395Skan  count_states_and_arcs (automaton, &states_num, &arcs_num);
6096117395Skan  automaton->DFA_states_num = states_num;
6097117395Skan  automaton->DFA_arcs_num = arcs_num;
6098117395Skan  if (!no_minimization_flag)
6099117395Skan    {
6100117395Skan      ticker_on (&minimize_time);
6101132718Skan      if (progress_flag)
6102132718Skan	{
6103132718Skan	  if (automaton->corresponding_automaton_decl == NULL)
6104132718Skan	    fprintf (stderr, "Minimize anonymous DFA...");
6105132718Skan	  else
6106132718Skan	    fprintf (stderr, "Minimize DFA `%s'...",
6107132718Skan		     automaton->corresponding_automaton_decl->name);
6108132718Skan	}
6109117395Skan      minimize_DFA (automaton);
6110132718Skan      if (progress_flag)
6111132718Skan	fprintf (stderr, "done\n");
6112117395Skan      ticker_off (&minimize_time);
6113117395Skan      count_states_and_arcs (automaton, &states_num, &arcs_num);
6114117395Skan      automaton->minimal_DFA_states_num = states_num;
6115117395Skan      automaton->minimal_DFA_arcs_num = arcs_num;
6116117395Skan    }
6117117395Skan}
6118117395Skan
6119117395Skan
6120117395Skan
6121117395Skan/* The page contains code for enumeration  of all states of an automaton.  */
6122117395Skan
6123117395Skan/* Variable used for enumeration of all states of an automaton.  Its
6124117395Skan   value is current number of automaton states.  */
6125117395Skanstatic int curr_state_order_num;
6126117395Skan
6127117395Skan/* The function is called by function `pass_states' for enumerating
6128117395Skan   states.  */
6129117395Skanstatic void
6130132718Skanset_order_state_num (state_t state)
6131117395Skan{
6132117395Skan  state->order_state_num = curr_state_order_num;
6133117395Skan  curr_state_order_num++;
6134117395Skan}
6135117395Skan
6136117395Skan/* The function enumerates all states of AUTOMATON.  */
6137117395Skanstatic void
6138132718Skanenumerate_states (automaton_t automaton)
6139117395Skan{
6140117395Skan  curr_state_order_num = 0;
6141117395Skan  pass_states (automaton, set_order_state_num);
6142117395Skan  automaton->achieved_states_num = curr_state_order_num;
6143117395Skan}
6144117395Skan
6145117395Skan
6146117395Skan
6147117395Skan/* The page contains code for finding equivalent automaton insns
6148117395Skan   (ainsns).  */
6149117395Skan
6150117395Skan/* The function inserts AINSN into cyclic list
6151117395Skan   CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns.  */
6152117395Skanstatic ainsn_t
6153132718Skaninsert_ainsn_into_equiv_class (ainsn_t ainsn,
6154132718Skan			       ainsn_t cyclic_equiv_class_insn_list)
6155117395Skan{
6156117395Skan  if (cyclic_equiv_class_insn_list == NULL)
6157117395Skan    ainsn->next_equiv_class_insn = ainsn;
6158117395Skan  else
6159117395Skan    {
6160117395Skan      ainsn->next_equiv_class_insn
6161117395Skan        = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6162117395Skan      cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6163117395Skan    }
6164117395Skan  return ainsn;
6165117395Skan}
6166117395Skan
6167117395Skan/* The function deletes equiv_class_insn into cyclic list of
6168117395Skan   equivalent ainsns.  */
6169117395Skanstatic void
6170132718Skandelete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6171117395Skan{
6172117395Skan  ainsn_t curr_equiv_class_insn;
6173117395Skan  ainsn_t prev_equiv_class_insn;
6174117395Skan
6175117395Skan  prev_equiv_class_insn = equiv_class_insn;
6176117395Skan  for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6177117395Skan       curr_equiv_class_insn != equiv_class_insn;
6178117395Skan       curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6179117395Skan    prev_equiv_class_insn = curr_equiv_class_insn;
6180117395Skan  if (prev_equiv_class_insn != equiv_class_insn)
6181117395Skan    prev_equiv_class_insn->next_equiv_class_insn
6182117395Skan      = equiv_class_insn->next_equiv_class_insn;
6183117395Skan}
6184117395Skan
6185117395Skan/* The function processes AINSN of a state in order to find equivalent
6186117395Skan   ainsns.  INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6187117395Skan   state.  */
6188117395Skanstatic void
6189132718Skanprocess_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6190117395Skan{
6191117395Skan  ainsn_t next_insn;
6192117395Skan  ainsn_t curr_insn;
6193117395Skan  ainsn_t cyclic_insn_list;
6194117395Skan  arc_t arc;
6195117395Skan
6196169689Skan  gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6197117395Skan  curr_insn = ainsn;
6198117395Skan  /* New class of ainsns which are not equivalent to given ainsn.  */
6199117395Skan  cyclic_insn_list = NULL;
6200117395Skan  do
6201117395Skan    {
6202117395Skan      next_insn = curr_insn->next_equiv_class_insn;
6203117395Skan      arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6204117395Skan      if (arc == NULL
6205117395Skan          || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6206117395Skan              != arc->to_state))
6207117395Skan        {
6208117395Skan          delete_ainsn_from_equiv_class (curr_insn);
6209117395Skan          cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6210117395Skan							    cyclic_insn_list);
6211117395Skan        }
6212117395Skan      curr_insn = next_insn;
6213117395Skan    }
6214117395Skan  while (curr_insn != ainsn);
6215117395Skan}
6216117395Skan
6217117395Skan/* The function processes STATE in order to find equivalent ainsns.  */
6218117395Skanstatic void
6219132718Skanprocess_state_for_insn_equiv_partition (state_t state)
6220117395Skan{
6221117395Skan  arc_t arc;
6222169689Skan  arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6223117395Skan
6224117395Skan  /* Process insns of the arcs.  */
6225117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6226117395Skan    insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6227117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6228117395Skan    process_insn_equiv_class (arc->insn, insn_arcs_array);
6229169689Skan
6230169689Skan  free (insn_arcs_array);
6231117395Skan}
6232117395Skan
6233117395Skan/* The function searches for equivalent ainsns of AUTOMATON.  */
6234117395Skanstatic void
6235132718Skanset_insn_equiv_classes (automaton_t automaton)
6236117395Skan{
6237117395Skan  ainsn_t ainsn;
6238117395Skan  ainsn_t first_insn;
6239117395Skan  ainsn_t curr_insn;
6240117395Skan  ainsn_t cyclic_insn_list;
6241117395Skan  ainsn_t insn_with_same_reservs;
6242117395Skan  int equiv_classes_num;
6243117395Skan
6244117395Skan  /* All insns are included in one equivalence class.  */
6245117395Skan  cyclic_insn_list = NULL;
6246117395Skan  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6247117395Skan    if (ainsn->first_insn_with_same_reservs)
6248117395Skan      cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6249117395Skan							cyclic_insn_list);
6250117395Skan  /* Process insns in order to make equivalence partition.  */
6251117395Skan  pass_states (automaton, process_state_for_insn_equiv_partition);
6252117395Skan  /* Enumerate equiv classes.  */
6253117395Skan  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6254117395Skan    /* Set undefined value.  */
6255117395Skan    ainsn->insn_equiv_class_num = -1;
6256117395Skan  equiv_classes_num = 0;
6257117395Skan  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6258117395Skan    if (ainsn->insn_equiv_class_num < 0)
6259117395Skan      {
6260117395Skan        first_insn = ainsn;
6261169689Skan        gcc_assert (first_insn->first_insn_with_same_reservs);
6262169689Skan        first_insn->first_ainsn_with_given_equivalence_num = 1;
6263117395Skan        curr_insn = first_insn;
6264117395Skan        do
6265117395Skan          {
6266117395Skan            for (insn_with_same_reservs = curr_insn;
6267117395Skan                 insn_with_same_reservs != NULL;
6268117395Skan                 insn_with_same_reservs
6269117395Skan		   = insn_with_same_reservs->next_same_reservs_insn)
6270117395Skan              insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6271117395Skan            curr_insn = curr_insn->next_equiv_class_insn;
6272117395Skan          }
6273117395Skan        while (curr_insn != first_insn);
6274117395Skan        equiv_classes_num++;
6275117395Skan      }
6276117395Skan  automaton->insn_equiv_classes_num = equiv_classes_num;
6277117395Skan}
6278117395Skan
6279117395Skan
6280117395Skan
6281117395Skan/* This page contains code for creating DFA(s) and calls functions
6282117395Skan   building them.  */
6283117395Skan
6284117395Skan
6285117395Skan/* The following value is used to prevent floating point overflow for
6286117395Skan   estimating an automaton bound.  The value should be less DBL_MAX on
6287117395Skan   the host machine.  We use here approximate minimum of maximal
6288117395Skan   double floating point value required by ANSI C standard.  It
6289117395Skan   will work for non ANSI sun compiler too.  */
6290117395Skan
6291117395Skan#define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND  1.0E37
6292117395Skan
6293117395Skan/* The function estimate size of the single DFA used by PHR (pipeline
6294117395Skan   hazards recognizer).  */
6295117395Skanstatic double
6296132718Skanestimate_one_automaton_bound (void)
6297117395Skan{
6298117395Skan  decl_t decl;
6299117395Skan  double one_automaton_estimation_bound;
6300117395Skan  double root_value;
6301117395Skan  int i;
6302117395Skan
6303117395Skan  one_automaton_estimation_bound = 1.0;
6304117395Skan  for (i = 0; i < description->decls_num; i++)
6305117395Skan    {
6306117395Skan      decl = description->decls [i];
6307117395Skan      if (decl->mode == dm_unit)
6308117395Skan	{
6309132718Skan	  root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6310132718Skan				 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6311117395Skan                            / automata_num);
6312117395Skan	  if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6313117395Skan	      > one_automaton_estimation_bound)
6314117395Skan	    one_automaton_estimation_bound *= root_value;
6315117395Skan	}
6316117395Skan    }
6317117395Skan  return one_automaton_estimation_bound;
6318117395Skan}
6319117395Skan
6320132718Skan/* The function compares unit declarations according to their maximal
6321117395Skan   cycle in reservations.  */
6322117395Skanstatic int
6323132718Skancompare_max_occ_cycle_nums (const void *unit_decl_1,
6324132718Skan			    const void *unit_decl_2)
6325117395Skan{
6326117395Skan  if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6327117395Skan      < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6328117395Skan    return 1;
6329117395Skan  else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6330117395Skan	   == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6331117395Skan    return 0;
6332117395Skan  else
6333117395Skan    return -1;
6334117395Skan}
6335117395Skan
6336117395Skan/* The function makes heuristic assigning automata to units.  Actually
6337117395Skan   efficacy of the algorithm has been checked yet??? */
6338169689Skan
6339117395Skanstatic void
6340132718Skanunits_to_automata_heuristic_distr (void)
6341117395Skan{
6342117395Skan  double estimation_bound;
6343117395Skan  int automaton_num;
6344117395Skan  int rest_units_num;
6345117395Skan  double bound_value;
6346169689Skan  unit_decl_t *unit_decls;
6347169689Skan  int i, j;
6348117395Skan
6349117395Skan  if (description->units_num == 0)
6350117395Skan    return;
6351117395Skan  estimation_bound = estimate_one_automaton_bound ();
6352169689Skan  unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6353169689Skan
6354169689Skan  for (i = 0, j = 0; i < description->decls_num; i++)
6355169689Skan    if (description->decls[i]->mode == dm_unit)
6356169689Skan      unit_decls[j++] = DECL_UNIT (description->decls[i]);
6357169689Skan  gcc_assert (j == description->units_num);
6358169689Skan
6359169689Skan  qsort (unit_decls, description->units_num,
6360169689Skan         sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6361169689Skan
6362117395Skan  automaton_num = 0;
6363169689Skan  bound_value = unit_decls[0]->max_occ_cycle_num;
6364169689Skan  unit_decls[0]->corresponding_automaton_num = automaton_num;
6365169689Skan
6366169689Skan  for (i = 1; i < description->units_num; i++)
6367117395Skan    {
6368169689Skan      rest_units_num = description->units_num - i + 1;
6369169689Skan      gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6370117395Skan      if (automaton_num < automata_num - 1
6371117395Skan          && ((automata_num - automaton_num - 1 == rest_units_num)
6372117395Skan              || (bound_value
6373117395Skan                  > (estimation_bound
6374169689Skan		     / unit_decls[i]->max_occ_cycle_num))))
6375117395Skan        {
6376169689Skan          bound_value = unit_decls[i]->max_occ_cycle_num;
6377117395Skan          automaton_num++;
6378117395Skan        }
6379117395Skan      else
6380169689Skan        bound_value *= unit_decls[i]->max_occ_cycle_num;
6381169689Skan      unit_decls[i]->corresponding_automaton_num = automaton_num;
6382117395Skan    }
6383169689Skan  gcc_assert (automaton_num == automata_num - 1);
6384169689Skan  free (unit_decls);
6385117395Skan}
6386117395Skan
6387117395Skan/* The functions creates automaton insns for each automata.  Automaton
6388117395Skan   insn is simply insn for given automaton which makes reservation
6389117395Skan   only of units of the automaton.  */
6390117395Skanstatic ainsn_t
6391132718Skancreate_ainsns (void)
6392117395Skan{
6393117395Skan  decl_t decl;
6394117395Skan  ainsn_t first_ainsn;
6395117395Skan  ainsn_t curr_ainsn;
6396117395Skan  ainsn_t prev_ainsn;
6397117395Skan  int i;
6398117395Skan
6399117395Skan  first_ainsn = NULL;
6400117395Skan  prev_ainsn = NULL;
6401117395Skan  for (i = 0; i < description->decls_num; i++)
6402117395Skan    {
6403117395Skan      decl = description->decls [i];
6404117395Skan      if (decl->mode == dm_insn_reserv)
6405117395Skan	{
6406117395Skan	  curr_ainsn = create_node (sizeof (struct ainsn));
6407117395Skan	  curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6408117395Skan	  curr_ainsn->important_p = FALSE;
6409117395Skan	  curr_ainsn->next_ainsn = NULL;
6410117395Skan	  if (prev_ainsn == NULL)
6411117395Skan	    first_ainsn = curr_ainsn;
6412117395Skan	  else
6413117395Skan	    prev_ainsn->next_ainsn = curr_ainsn;
6414117395Skan	  prev_ainsn = curr_ainsn;
6415117395Skan	}
6416117395Skan    }
6417117395Skan  return first_ainsn;
6418117395Skan}
6419117395Skan
6420117395Skan/* The function assigns automata to units according to constructions
6421117395Skan   `define_automaton' in the description.  */
6422117395Skanstatic void
6423132718Skanunits_to_automata_distr (void)
6424117395Skan{
6425117395Skan  decl_t decl;
6426117395Skan  int i;
6427132718Skan
6428117395Skan  for (i = 0; i < description->decls_num; i++)
6429117395Skan    {
6430117395Skan      decl = description->decls [i];
6431117395Skan      if (decl->mode == dm_unit)
6432117395Skan	{
6433117395Skan	  if (DECL_UNIT (decl)->automaton_decl == NULL
6434117395Skan	      || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6435117395Skan		  == NULL))
6436117395Skan	    /* Distribute to the first automaton.  */
6437117395Skan	    DECL_UNIT (decl)->corresponding_automaton_num = 0;
6438117395Skan	  else
6439117395Skan	    DECL_UNIT (decl)->corresponding_automaton_num
6440117395Skan	      = (DECL_UNIT (decl)->automaton_decl
6441117395Skan                 ->corresponding_automaton->automaton_order_num);
6442117395Skan	}
6443117395Skan    }
6444117395Skan}
6445117395Skan
6446117395Skan/* The function creates DFA(s) for fast pipeline hazards recognition
6447117395Skan   after checking and simplifying IR of the description.  */
6448117395Skanstatic void
6449132718Skancreate_automata (void)
6450117395Skan{
6451117395Skan  automaton_t curr_automaton;
6452117395Skan  automaton_t prev_automaton;
6453117395Skan  decl_t decl;
6454117395Skan  int curr_automaton_num;
6455117395Skan  int i;
6456117395Skan
6457117395Skan  if (automata_num != 0)
6458117395Skan    {
6459117395Skan      units_to_automata_heuristic_distr ();
6460117395Skan      for (prev_automaton = NULL, curr_automaton_num = 0;
6461117395Skan           curr_automaton_num < automata_num;
6462117395Skan           curr_automaton_num++, prev_automaton = curr_automaton)
6463117395Skan        {
6464117395Skan	  curr_automaton = create_node (sizeof (struct automaton));
6465117395Skan	  curr_automaton->ainsn_list = create_ainsns ();
6466117395Skan	  curr_automaton->corresponding_automaton_decl = NULL;
6467117395Skan	  curr_automaton->next_automaton = NULL;
6468117395Skan          curr_automaton->automaton_order_num = curr_automaton_num;
6469117395Skan          if (prev_automaton == NULL)
6470117395Skan            description->first_automaton = curr_automaton;
6471117395Skan          else
6472117395Skan            prev_automaton->next_automaton = curr_automaton;
6473117395Skan        }
6474117395Skan    }
6475117395Skan  else
6476117395Skan    {
6477117395Skan      curr_automaton_num = 0;
6478117395Skan      prev_automaton = NULL;
6479117395Skan      for (i = 0; i < description->decls_num; i++)
6480117395Skan	{
6481117395Skan	  decl = description->decls [i];
6482117395Skan	  if (decl->mode == dm_automaton
6483117395Skan	      && DECL_AUTOMATON (decl)->automaton_is_used)
6484117395Skan	    {
6485117395Skan	      curr_automaton = create_node (sizeof (struct automaton));
6486117395Skan	      curr_automaton->ainsn_list = create_ainsns ();
6487117395Skan	      curr_automaton->corresponding_automaton_decl
6488117395Skan		= DECL_AUTOMATON (decl);
6489117395Skan	      curr_automaton->next_automaton = NULL;
6490117395Skan	      DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6491117395Skan	      curr_automaton->automaton_order_num = curr_automaton_num;
6492117395Skan	      if (prev_automaton == NULL)
6493117395Skan		description->first_automaton = curr_automaton;
6494117395Skan	      else
6495117395Skan		prev_automaton->next_automaton = curr_automaton;
6496117395Skan	      curr_automaton_num++;
6497117395Skan	      prev_automaton = curr_automaton;
6498117395Skan	    }
6499117395Skan	}
6500117395Skan      if (curr_automaton_num == 0)
6501117395Skan	{
6502117395Skan	  curr_automaton = create_node (sizeof (struct automaton));
6503117395Skan	  curr_automaton->ainsn_list = create_ainsns ();
6504117395Skan	  curr_automaton->corresponding_automaton_decl = NULL;
6505117395Skan	  curr_automaton->next_automaton = NULL;
6506117395Skan	  description->first_automaton = curr_automaton;
6507117395Skan	}
6508117395Skan      units_to_automata_distr ();
6509117395Skan    }
6510117395Skan  NDFA_time = create_ticker ();
6511117395Skan  ticker_off (&NDFA_time);
6512117395Skan  NDFA_to_DFA_time = create_ticker ();
6513117395Skan  ticker_off (&NDFA_to_DFA_time);
6514117395Skan  minimize_time = create_ticker ();
6515117395Skan  ticker_off (&minimize_time);
6516117395Skan  equiv_time = create_ticker ();
6517117395Skan  ticker_off (&equiv_time);
6518117395Skan  for (curr_automaton = description->first_automaton;
6519117395Skan       curr_automaton != NULL;
6520117395Skan       curr_automaton = curr_automaton->next_automaton)
6521117395Skan    {
6522132718Skan      if (progress_flag)
6523132718Skan	{
6524132718Skan	  if (curr_automaton->corresponding_automaton_decl == NULL)
6525132718Skan	    fprintf (stderr, "Prepare anonymous automaton creation ... ");
6526132718Skan	  else
6527132718Skan	    fprintf (stderr, "Prepare automaton `%s' creation...",
6528132718Skan		     curr_automaton->corresponding_automaton_decl->name);
6529132718Skan	}
6530117395Skan      create_alt_states (curr_automaton);
6531117395Skan      form_ainsn_with_same_reservs (curr_automaton);
6532132718Skan      if (progress_flag)
6533132718Skan	fprintf (stderr, "done\n");
6534117395Skan      build_automaton (curr_automaton);
6535117395Skan      enumerate_states (curr_automaton);
6536117395Skan      ticker_on (&equiv_time);
6537117395Skan      set_insn_equiv_classes (curr_automaton);
6538117395Skan      ticker_off (&equiv_time);
6539117395Skan    }
6540117395Skan}
6541117395Skan
6542117395Skan
6543117395Skan
6544117395Skan/* This page contains code for forming string representation of
6545117395Skan   regexp.  The representation is formed on IR obstack.  So you should
6546117395Skan   not work with IR obstack between regexp_representation and
6547117395Skan   finish_regexp_representation calls.  */
6548117395Skan
6549117395Skan/* This recursive function forms string representation of regexp
6550117395Skan   (without tailing '\0').  */
6551117395Skanstatic void
6552132718Skanform_regexp (regexp_t regexp)
6553117395Skan{
6554117395Skan  int i;
6555132718Skan
6556169689Skan  switch (regexp->mode)
6557117395Skan    {
6558169689Skan    case rm_unit: case rm_reserv:
6559117395Skan      {
6560169689Skan	const char *name = (regexp->mode == rm_unit
6561169689Skan			    ? REGEXP_UNIT (regexp)->name
6562169689Skan			    : REGEXP_RESERV (regexp)->name);
6563169689Skan
6564169689Skan	obstack_grow (&irp, name, strlen (name));
6565169689Skan	break;
6566117395Skan      }
6567169689Skan
6568169689Skan    case rm_sequence:
6569169689Skan      for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6570169689Skan	{
6571169689Skan	  if (i != 0)
6572169689Skan	    obstack_1grow (&irp, ',');
6573169689Skan	  form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6574169689Skan	}
6575169689Skan      break;
6576169689Skan
6577169689Skan    case rm_allof:
6578117395Skan      obstack_1grow (&irp, '(');
6579117395Skan      for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6580117395Skan	{
6581117395Skan	  if (i != 0)
6582117395Skan            obstack_1grow (&irp, '+');
6583117395Skan	  if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6584117395Skan              || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6585117395Skan            obstack_1grow (&irp, '(');
6586117395Skan	  form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6587117395Skan	  if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6588117395Skan              || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6589117395Skan            obstack_1grow (&irp, ')');
6590117395Skan        }
6591117395Skan      obstack_1grow (&irp, ')');
6592169689Skan      break;
6593169689Skan
6594169689Skan    case rm_oneof:
6595169689Skan      for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6596169689Skan	{
6597169689Skan	  if (i != 0)
6598169689Skan	    obstack_1grow (&irp, '|');
6599169689Skan	  if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6600169689Skan	    obstack_1grow (&irp, '(');
6601169689Skan	  form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6602169689Skan	  if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6603169689Skan          obstack_1grow (&irp, ')');
6604169689Skan	}
6605169689Skan      break;
6606169689Skan
6607169689Skan    case rm_repeat:
6608117395Skan      {
6609169689Skan	char digits [30];
6610169689Skan
6611169689Skan	if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6612169689Skan	    || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6613169689Skan	    || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6614169689Skan	  obstack_1grow (&irp, '(');
6615169689Skan	form_regexp (REGEXP_REPEAT (regexp)->regexp);
6616169689Skan	if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6617169689Skan	    || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6618169689Skan	    || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6619169689Skan	  obstack_1grow (&irp, ')');
6620169689Skan	sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6621169689Skan	obstack_grow (&irp, digits, strlen (digits));
6622169689Skan	break;
6623117395Skan      }
6624117395Skan
6625169689Skan    case rm_nothing:
6626169689Skan      obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6627169689Skan      break;
6628169689Skan
6629169689Skan    default:
6630169689Skan      gcc_unreachable ();
6631117395Skan    }
6632117395Skan}
6633117395Skan
6634117395Skan/* The function returns string representation of REGEXP on IR
6635117395Skan   obstack.  */
6636117395Skanstatic const char *
6637132718Skanregexp_representation (regexp_t regexp)
6638117395Skan{
6639117395Skan  form_regexp (regexp);
6640117395Skan  obstack_1grow (&irp, '\0');
6641117395Skan  return obstack_base (&irp);
6642117395Skan}
6643117395Skan
6644117395Skan/* The function frees memory allocated for last formed string
6645117395Skan   representation of regexp.  */
6646117395Skanstatic void
6647132718Skanfinish_regexp_representation (void)
6648117395Skan{
6649117395Skan  int length = obstack_object_size (&irp);
6650132718Skan
6651117395Skan  obstack_blank_fast (&irp, -length);
6652117395Skan}
6653117395Skan
6654117395Skan
6655117395Skan
6656117395Skan/* This page contains code for output PHR (pipeline hazards recognizer).  */
6657117395Skan
6658117395Skan/* The function outputs minimal C type which is sufficient for
6659117395Skan   representation numbers in range min_range_value and
6660117395Skan   max_range_value.  Because host machine and build machine may be
6661117395Skan   different, we use here minimal values required by ANSI C standard
6662117395Skan   instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc.  This is a good
6663117395Skan   approximation.  */
6664117395Skan
6665117395Skanstatic void
6666132718Skanoutput_range_type (FILE *f, long int min_range_value,
6667132718Skan		   long int max_range_value)
6668117395Skan{
6669117395Skan  if (min_range_value >= 0 && max_range_value <= 255)
6670117395Skan    fprintf (f, "unsigned char");
6671117395Skan  else if (min_range_value >= -127 && max_range_value <= 127)
6672117395Skan    fprintf (f, "signed char");
6673117395Skan  else if (min_range_value >= 0 && max_range_value <= 65535)
6674117395Skan    fprintf (f, "unsigned short");
6675117395Skan  else if (min_range_value >= -32767 && max_range_value <= 32767)
6676117395Skan    fprintf (f, "short");
6677117395Skan  else
6678117395Skan    fprintf (f, "int");
6679117395Skan}
6680117395Skan
6681117395Skan/* The following macro value is used as value of member
6682117395Skan   `longest_path_length' of state when we are processing path and the
6683117395Skan   state on the path.  */
6684117395Skan
6685117395Skan#define ON_THE_PATH -2
6686117395Skan
6687117395Skan/* The following recursive function searches for the length of the
6688117395Skan   longest path starting from STATE which does not contain cycles and
6689117395Skan   `cycle advance' arcs.  */
6690117395Skan
6691117395Skanstatic int
6692132718Skanlongest_path_length (state_t state)
6693117395Skan{
6694117395Skan  arc_t arc;
6695117395Skan  int length, result;
6696132718Skan
6697169689Skan  if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6698169689Skan    {
6699169689Skan      /* We don't expect the path cycle here.  Our graph may contain
6700169689Skan      	 only cycles with one state on the path not containing `cycle
6701169689Skan      	 advance' arcs -- see comment below.  */
6702169689Skan      gcc_assert (state->longest_path_length != ON_THE_PATH);
6703169689Skan
6704169689Skan      /* We already visited the state.  */
6705169689Skan      return state->longest_path_length;
6706169689Skan    }
6707117395Skan
6708117395Skan  result = 0;
6709117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6710117395Skan    /* Ignore cycles containing one state and `cycle advance' arcs.  */
6711117395Skan    if (arc->to_state != state
6712117395Skan	&& (arc->insn->insn_reserv_decl
6713117395Skan	    != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6714117395Skan    {
6715117395Skan      length = longest_path_length (arc->to_state);
6716117395Skan      if (length > result)
6717117395Skan	result = length;
6718117395Skan    }
6719117395Skan  state->longest_path_length = result + 1;
6720117395Skan  return result;
6721117395Skan}
6722117395Skan
6723169689Skan/* The function outputs all initialization values of VECT.  */
6724117395Skanstatic void
6725169689Skanoutput_vect (vla_hwint_t vect)
6726117395Skan{
6727117395Skan  int els_on_line;
6728169689Skan  size_t vect_length = VEC_length (vect_el_t, vect);
6729169689Skan  size_t i;
6730117395Skan
6731117395Skan  els_on_line = 1;
6732117395Skan  if (vect_length == 0)
6733169689Skan    fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6734117395Skan  else
6735169689Skan    for (i = 0; i < vect_length; i++)
6736169689Skan      {
6737169689Skan	fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6738169689Skan	if (els_on_line == 10)
6739169689Skan	  {
6740169689Skan	    els_on_line = 0;
6741169689Skan	    fputs (",\n", output_file);
6742169689Skan	  }
6743169689Skan	else if (i < vect_length-1)
6744169689Skan	  fputs (", ", output_file);
6745169689Skan	els_on_line++;
6746169689Skan      }
6747117395Skan}
6748117395Skan
6749117395Skan/* The following is name of the structure which represents DFA(s) for
6750117395Skan   PHR.  */
6751117395Skan#define CHIP_NAME "DFA_chip"
6752117395Skan
6753117395Skan/* The following is name of member which represents state of a DFA for
6754117395Skan   PHR.  */
6755117395Skanstatic void
6756132718Skanoutput_chip_member_name (FILE *f, automaton_t automaton)
6757117395Skan{
6758117395Skan  if (automaton->corresponding_automaton_decl == NULL)
6759117395Skan    fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6760117395Skan  else
6761117395Skan    fprintf (f, "%s_automaton_state",
6762117395Skan             automaton->corresponding_automaton_decl->name);
6763117395Skan}
6764117395Skan
6765117395Skan/* The following is name of temporary variable which stores state of a
6766117395Skan   DFA for PHR.  */
6767117395Skanstatic void
6768132718Skanoutput_temp_chip_member_name (FILE *f, automaton_t automaton)
6769117395Skan{
6770117395Skan  fprintf (f, "_");
6771117395Skan  output_chip_member_name (f, automaton);
6772117395Skan}
6773117395Skan
6774117395Skan/* This is name of macro value which is code of pseudo_insn
6775117395Skan   representing advancing cpu cycle.  Its value is used as internal
6776117395Skan   code unknown insn.  */
6777117395Skan#define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6778117395Skan
6779117395Skan/* Output name of translate vector for given automaton.  */
6780117395Skanstatic void
6781132718Skanoutput_translate_vect_name (FILE *f, automaton_t automaton)
6782117395Skan{
6783117395Skan  if (automaton->corresponding_automaton_decl == NULL)
6784117395Skan    fprintf (f, "translate_%d", automaton->automaton_order_num);
6785117395Skan  else
6786117395Skan    fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6787117395Skan}
6788117395Skan
6789117395Skan/* Output name for simple transition table representation.  */
6790117395Skanstatic void
6791132718Skanoutput_trans_full_vect_name (FILE *f, automaton_t automaton)
6792117395Skan{
6793117395Skan  if (automaton->corresponding_automaton_decl == NULL)
6794117395Skan    fprintf (f, "transitions_%d", automaton->automaton_order_num);
6795117395Skan  else
6796117395Skan    fprintf (f, "%s_transitions",
6797117395Skan	     automaton->corresponding_automaton_decl->name);
6798117395Skan}
6799117395Skan
6800117395Skan/* Output name of comb vector of the transition table for given
6801117395Skan   automaton.  */
6802117395Skanstatic void
6803132718Skanoutput_trans_comb_vect_name (FILE *f, automaton_t automaton)
6804117395Skan{
6805117395Skan  if (automaton->corresponding_automaton_decl == NULL)
6806117395Skan    fprintf (f, "transitions_%d", automaton->automaton_order_num);
6807117395Skan  else
6808117395Skan    fprintf (f, "%s_transitions",
6809117395Skan             automaton->corresponding_automaton_decl->name);
6810117395Skan}
6811117395Skan
6812117395Skan/* Output name of check vector of the transition table for given
6813117395Skan   automaton.  */
6814117395Skanstatic void
6815132718Skanoutput_trans_check_vect_name (FILE *f, automaton_t automaton)
6816117395Skan{
6817117395Skan  if (automaton->corresponding_automaton_decl == NULL)
6818117395Skan    fprintf (f, "check_%d", automaton->automaton_order_num);
6819117395Skan  else
6820117395Skan    fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6821117395Skan}
6822117395Skan
6823117395Skan/* Output name of base vector of the transition table for given
6824117395Skan   automaton.  */
6825117395Skanstatic void
6826132718Skanoutput_trans_base_vect_name (FILE *f, automaton_t automaton)
6827117395Skan{
6828117395Skan  if (automaton->corresponding_automaton_decl == NULL)
6829117395Skan    fprintf (f, "base_%d", automaton->automaton_order_num);
6830117395Skan  else
6831117395Skan    fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6832117395Skan}
6833117395Skan
6834117395Skan/* Output name of simple min issue delay table representation.  */
6835117395Skanstatic void
6836132718Skanoutput_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6837117395Skan{
6838117395Skan  if (automaton->corresponding_automaton_decl == NULL)
6839117395Skan    fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6840117395Skan  else
6841117395Skan    fprintf (f, "%s_min_issue_delay",
6842117395Skan             automaton->corresponding_automaton_decl->name);
6843117395Skan}
6844117395Skan
6845117395Skan/* Output name of deadlock vector for given automaton.  */
6846117395Skanstatic void
6847132718Skanoutput_dead_lock_vect_name (FILE *f, automaton_t automaton)
6848117395Skan{
6849117395Skan  if (automaton->corresponding_automaton_decl == NULL)
6850117395Skan    fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6851117395Skan  else
6852117395Skan    fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6853117395Skan}
6854117395Skan
6855117395Skan/* Output name of reserved units table for AUTOMATON into file F.  */
6856117395Skanstatic void
6857132718Skanoutput_reserved_units_table_name (FILE *f, automaton_t automaton)
6858117395Skan{
6859117395Skan  if (automaton->corresponding_automaton_decl == NULL)
6860117395Skan    fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6861117395Skan  else
6862117395Skan    fprintf (f, "%s_reserved_units",
6863117395Skan	     automaton->corresponding_automaton_decl->name);
6864117395Skan}
6865117395Skan
6866117395Skan/* Name of the PHR interface macro.  */
6867117395Skan#define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6868117395Skan
6869117395Skan/* Names of an internal functions: */
6870117395Skan#define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6871117395Skan
6872117395Skan/* This is external type of DFA(s) state.  */
6873117395Skan#define STATE_TYPE_NAME "state_t"
6874117395Skan
6875117395Skan#define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6876117395Skan
6877117395Skan#define INTERNAL_RESET_FUNC_NAME "internal_reset"
6878117395Skan
6879117395Skan#define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6880117395Skan
6881117395Skan#define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6882117395Skan
6883117395Skan/* Name of cache of insn dfa codes.  */
6884117395Skan#define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6885117395Skan
6886117395Skan/* Name of length of cache of insn dfa codes.  */
6887117395Skan#define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6888117395Skan
6889117395Skan/* Names of the PHR interface functions: */
6890117395Skan#define SIZE_FUNC_NAME "state_size"
6891117395Skan
6892117395Skan#define TRANSITION_FUNC_NAME "state_transition"
6893117395Skan
6894117395Skan#define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6895117395Skan
6896117395Skan#define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6897117395Skan
6898117395Skan#define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6899117395Skan
6900117395Skan#define RESET_FUNC_NAME "state_reset"
6901117395Skan
6902117395Skan#define INSN_LATENCY_FUNC_NAME "insn_latency"
6903117395Skan
6904117395Skan#define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6905117395Skan
6906117395Skan#define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6907117395Skan
6908117395Skan#define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6909117395Skan
6910132718Skan#define DFA_CLEAN_INSN_CACHE_FUNC_NAME  "dfa_clean_insn_cache"
6911132718Skan
6912169689Skan#define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6913169689Skan
6914117395Skan#define DFA_START_FUNC_NAME  "dfa_start"
6915117395Skan
6916117395Skan#define DFA_FINISH_FUNC_NAME "dfa_finish"
6917117395Skan
6918117395Skan/* Names of parameters of the PHR interface functions.  */
6919117395Skan#define STATE_NAME "state"
6920117395Skan
6921117395Skan#define INSN_PARAMETER_NAME "insn"
6922117395Skan
6923117395Skan#define INSN2_PARAMETER_NAME "insn2"
6924117395Skan
6925117395Skan#define CHIP_PARAMETER_NAME "chip"
6926117395Skan
6927117395Skan#define FILE_PARAMETER_NAME "f"
6928117395Skan
6929117395Skan#define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6930117395Skan
6931117395Skan#define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6932117395Skan
6933117395Skan/* Names of the variables whose values are internal insn code of rtx
6934117395Skan   insn.  */
6935117395Skan#define INTERNAL_INSN_CODE_NAME "insn_code"
6936117395Skan
6937117395Skan#define INTERNAL_INSN2_CODE_NAME "insn2_code"
6938117395Skan
6939117395Skan/* Names of temporary variables in some functions.  */
6940117395Skan#define TEMPORARY_VARIABLE_NAME "temp"
6941117395Skan
6942117395Skan#define I_VARIABLE_NAME "i"
6943117395Skan
6944117395Skan/* Name of result variable in some functions.  */
6945117395Skan#define RESULT_VARIABLE_NAME "res"
6946117395Skan
6947117395Skan/* Name of function (attribute) to translate insn into internal insn
6948117395Skan   code.  */
6949117395Skan#define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6950117395Skan
6951117395Skan/* Name of function (attribute) to translate insn into internal insn
6952117395Skan   code with caching.  */
6953117395Skan#define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6954117395Skan
6955117395Skan/* Output C type which is used for representation of codes of states
6956117395Skan   of AUTOMATON.  */
6957117395Skanstatic void
6958132718Skanoutput_state_member_type (FILE *f, automaton_t automaton)
6959117395Skan{
6960117395Skan  output_range_type (f, 0, automaton->achieved_states_num);
6961117395Skan}
6962117395Skan
6963117395Skan/* Output definition of the structure representing current DFA(s)
6964117395Skan   state(s).  */
6965117395Skanstatic void
6966132718Skanoutput_chip_definitions (void)
6967117395Skan{
6968117395Skan  automaton_t automaton;
6969117395Skan
6970117395Skan  fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6971117395Skan  for (automaton = description->first_automaton;
6972117395Skan       automaton != NULL;
6973117395Skan       automaton = automaton->next_automaton)
6974117395Skan    {
6975117395Skan      fprintf (output_file, "  ");
6976117395Skan      output_state_member_type (output_file, automaton);
6977117395Skan      fprintf (output_file, " ");
6978117395Skan      output_chip_member_name (output_file, automaton);
6979117395Skan      fprintf (output_file, ";\n");
6980117395Skan    }
6981117395Skan  fprintf (output_file, "};\n\n");
6982117395Skan#if 0
6983117395Skan  fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6984117395Skan#endif
6985117395Skan}
6986117395Skan
6987117395Skan
6988117395Skan/* The function outputs translate vector of internal insn code into
6989117395Skan   insn equivalence class number.  The equivalence class number is
6990132718Skan   used to access to table and vectors representing DFA(s).  */
6991117395Skanstatic void
6992132718Skanoutput_translate_vect (automaton_t automaton)
6993117395Skan{
6994117395Skan  ainsn_t ainsn;
6995117395Skan  int insn_value;
6996117395Skan  vla_hwint_t translate_vect;
6997117395Skan
6998169689Skan  translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6999169689Skan
7000132718Skan  for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7001117395Skan    /* Undefined value */
7002169689Skan    VEC_quick_push (vect_el_t, translate_vect,
7003169689Skan		    automaton->insn_equiv_classes_num);
7004169689Skan
7005117395Skan  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7006169689Skan    VEC_replace (vect_el_t, translate_vect,
7007169689Skan		 ainsn->insn_reserv_decl->insn_num,
7008169689Skan		 ainsn->insn_equiv_class_num);
7009169689Skan
7010117395Skan  fprintf (output_file,
7011117395Skan           "/* Vector translating external insn codes to internal ones.*/\n");
7012117395Skan  fprintf (output_file, "static const ");
7013117395Skan  output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7014117395Skan  fprintf (output_file, " ");
7015117395Skan  output_translate_vect_name (output_file, automaton);
7016117395Skan  fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7017169689Skan  output_vect (translate_vect);
7018117395Skan  fprintf (output_file, "};\n\n");
7019169689Skan  VEC_free (vect_el_t,heap, translate_vect);
7020117395Skan}
7021117395Skan
7022117395Skan/* The value in a table state x ainsn -> something which represents
7023117395Skan   undefined value.  */
7024117395Skanstatic int undefined_vect_el_value;
7025117395Skan
7026117395Skan/* The following function returns nonzero value if the best
7027117395Skan   representation of the table is comb vector.  */
7028117395Skanstatic int
7029132718Skancomb_vect_p (state_ainsn_table_t tab)
7030117395Skan{
7031169689Skan  return  (2 * VEC_length (vect_el_t, tab->full_vect)
7032169689Skan           > 5 * VEC_length (vect_el_t, tab->comb_vect));
7033117395Skan}
7034117395Skan
7035117395Skan/* The following function creates new table for AUTOMATON.  */
7036117395Skanstatic state_ainsn_table_t
7037132718Skancreate_state_ainsn_table (automaton_t automaton)
7038117395Skan{
7039117395Skan  state_ainsn_table_t tab;
7040117395Skan  int full_vect_length;
7041117395Skan  int i;
7042117395Skan
7043117395Skan  tab = create_node (sizeof (struct state_ainsn_table));
7044117395Skan  tab->automaton = automaton;
7045169689Skan
7046169689Skan  tab->comb_vect  = VEC_alloc (vect_el_t,heap, 10000);
7047169689Skan  tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7048169689Skan
7049169689Skan  tab->base_vect  = 0;
7050169689Skan  VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7051169689Skan		 automaton->achieved_states_num);
7052169689Skan
7053117395Skan  full_vect_length = (automaton->insn_equiv_classes_num
7054117395Skan                      * automaton->achieved_states_num);
7055169689Skan  tab->full_vect  = VEC_alloc (vect_el_t,heap, full_vect_length);
7056117395Skan  for (i = 0; i < full_vect_length; i++)
7057169689Skan    VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7058169689Skan
7059117395Skan  tab->min_base_vect_el_value = 0;
7060117395Skan  tab->max_base_vect_el_value = 0;
7061117395Skan  tab->min_comb_vect_el_value = 0;
7062117395Skan  tab->max_comb_vect_el_value = 0;
7063117395Skan  return tab;
7064117395Skan}
7065117395Skan
7066117395Skan/* The following function outputs the best C representation of the
7067117395Skan   table TAB of given TABLE_NAME.  */
7068117395Skanstatic void
7069169689Skanoutput_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7070132718Skan			  void (*output_full_vect_name_func) (FILE *, automaton_t),
7071132718Skan			  void (*output_comb_vect_name_func) (FILE *, automaton_t),
7072132718Skan			  void (*output_check_vect_name_func) (FILE *, automaton_t),
7073132718Skan			  void (*output_base_vect_name_func) (FILE *, automaton_t))
7074117395Skan{
7075117395Skan  if (!comb_vect_p (tab))
7076117395Skan    {
7077117395Skan      fprintf (output_file, "/* Vector for %s.  */\n", table_name);
7078117395Skan      fprintf (output_file, "static const ");
7079117395Skan      output_range_type (output_file, tab->min_comb_vect_el_value,
7080117395Skan                         tab->max_comb_vect_el_value);
7081117395Skan      fprintf (output_file, " ");
7082117395Skan      (*output_full_vect_name_func) (output_file, tab->automaton);
7083117395Skan      fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7084169689Skan      output_vect (tab->full_vect);
7085117395Skan      fprintf (output_file, "};\n\n");
7086117395Skan    }
7087117395Skan  else
7088117395Skan    {
7089117395Skan      fprintf (output_file, "/* Comb vector for %s.  */\n", table_name);
7090117395Skan      fprintf (output_file, "static const ");
7091117395Skan      output_range_type (output_file, tab->min_comb_vect_el_value,
7092117395Skan                         tab->max_comb_vect_el_value);
7093117395Skan      fprintf (output_file, " ");
7094117395Skan      (*output_comb_vect_name_func) (output_file, tab->automaton);
7095117395Skan      fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7096169689Skan      output_vect (tab->comb_vect);
7097117395Skan      fprintf (output_file, "};\n\n");
7098117395Skan      fprintf (output_file, "/* Check vector for %s.  */\n", table_name);
7099117395Skan      fprintf (output_file, "static const ");
7100117395Skan      output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7101117395Skan      fprintf (output_file, " ");
7102117395Skan      (*output_check_vect_name_func) (output_file, tab->automaton);
7103117395Skan      fprintf (output_file, "[] = {\n");
7104169689Skan      output_vect (tab->check_vect);
7105117395Skan      fprintf (output_file, "};\n\n");
7106117395Skan      fprintf (output_file, "/* Base vector for %s.  */\n", table_name);
7107117395Skan      fprintf (output_file, "static const ");
7108117395Skan      output_range_type (output_file, tab->min_base_vect_el_value,
7109117395Skan                         tab->max_base_vect_el_value);
7110117395Skan      fprintf (output_file, " ");
7111117395Skan      (*output_base_vect_name_func) (output_file, tab->automaton);
7112117395Skan      fprintf (output_file, "[] = {\n");
7113169689Skan      output_vect (tab->base_vect);
7114117395Skan      fprintf (output_file, "};\n\n");
7115117395Skan    }
7116117395Skan}
7117117395Skan
7118169689Skan/* The following function adds vector VECT to table TAB as its line
7119169689Skan   with number VECT_NUM.  */
7120117395Skanstatic void
7121169689Skanadd_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7122117395Skan{
7123169689Skan  int vect_length;
7124169689Skan  size_t real_vect_length;
7125117395Skan  int comb_vect_index;
7126117395Skan  int comb_vect_els_num;
7127117395Skan  int vect_index;
7128117395Skan  int first_unempty_vect_index;
7129117395Skan  int additional_els_num;
7130117395Skan  int no_state_value;
7131117395Skan  vect_el_t vect_el;
7132117395Skan  int i;
7133169689Skan  unsigned long vect_mask, comb_vect_mask;
7134117395Skan
7135169689Skan  vect_length = VEC_length (vect_el_t, vect);
7136169689Skan  gcc_assert (vect_length);
7137169689Skan  gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7138117395Skan  real_vect_length = tab->automaton->insn_equiv_classes_num;
7139117395Skan  /* Form full vector in the table: */
7140169689Skan  {
7141169689Skan    size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7142169689Skan    if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7143169689Skan      VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7144169689Skan		     full_base + vect_length);
7145169689Skan    for (i = 0; i < vect_length; i++)
7146169689Skan      VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7147169689Skan		   VEC_index (vect_el_t, vect, i));
7148169689Skan  }
7149117395Skan  /* Form comb vector in the table: */
7150169689Skan  gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7151169689Skan	      == VEC_length (vect_el_t, tab->check_vect));
7152169689Skan
7153169689Skan  comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7154117395Skan  for (first_unempty_vect_index = 0;
7155117395Skan       first_unempty_vect_index < vect_length;
7156117395Skan       first_unempty_vect_index++)
7157169689Skan    if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7158169689Skan	!= undefined_vect_el_value)
7159117395Skan      break;
7160169689Skan
7161117395Skan  /* Search for the place in comb vect for the inserted vect.  */
7162169689Skan
7163169689Skan  /* Slow case.  */
7164169689Skan  if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7165117395Skan    {
7166169689Skan      for (comb_vect_index = 0;
7167169689Skan           comb_vect_index < comb_vect_els_num;
7168169689Skan           comb_vect_index++)
7169169689Skan        {
7170169689Skan          for (vect_index = first_unempty_vect_index;
7171169689Skan               vect_index < vect_length
7172169689Skan               && vect_index + comb_vect_index < comb_vect_els_num;
7173169689Skan               vect_index++)
7174169689Skan            if (VEC_index (vect_el_t, vect, vect_index)
7175169689Skan		!= undefined_vect_el_value
7176169689Skan                && (VEC_index (vect_el_t, tab->comb_vect,
7177169689Skan			       vect_index + comb_vect_index)
7178169689Skan		    != undefined_vect_el_value))
7179169689Skan              break;
7180169689Skan          if (vect_index >= vect_length
7181169689Skan              || vect_index + comb_vect_index >= comb_vect_els_num)
7182169689Skan            break;
7183169689Skan        }
7184169689Skan      goto found;
7185117395Skan    }
7186169689Skan
7187169689Skan  /* Fast case.  */
7188169689Skan  vect_mask = 0;
7189169689Skan  for (vect_index = first_unempty_vect_index;
7190169689Skan       vect_index < vect_length;
7191169689Skan       vect_index++)
7192169689Skan    {
7193169689Skan      vect_mask = vect_mask << 1;
7194169689Skan      if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7195169689Skan	vect_mask |= 1;
7196169689Skan    }
7197169689Skan
7198169689Skan  /* Search for the place in comb vect for the inserted vect.  */
7199169689Skan  comb_vect_index = 0;
7200169689Skan  if (comb_vect_els_num == 0)
7201169689Skan    goto found;
7202169689Skan
7203169689Skan  comb_vect_mask = 0;
7204169689Skan  for (vect_index = first_unempty_vect_index;
7205169689Skan       vect_index < vect_length && vect_index < comb_vect_els_num;
7206169689Skan       vect_index++)
7207169689Skan    {
7208169689Skan      comb_vect_mask <<= 1;
7209169689Skan      if (vect_index + comb_vect_index < comb_vect_els_num
7210169689Skan	  && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7211169689Skan	     != undefined_vect_el_value)
7212169689Skan	comb_vect_mask |= 1;
7213169689Skan    }
7214169689Skan  if ((vect_mask & comb_vect_mask) == 0)
7215169689Skan    goto found;
7216169689Skan
7217169689Skan  for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7218169689Skan       comb_vect_index++, i++)
7219169689Skan    {
7220169689Skan      comb_vect_mask = (comb_vect_mask << 1) | 1;
7221169689Skan      comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7222169689Skan			 == undefined_vect_el_value);
7223169689Skan      if ((vect_mask & comb_vect_mask) == 0)
7224169689Skan	goto found;
7225169689Skan    }
7226169689Skan  for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7227169689Skan    {
7228169689Skan      comb_vect_mask <<= 1;
7229169689Skan      if ((vect_mask & comb_vect_mask) == 0)
7230169689Skan	goto found;
7231169689Skan    }
7232169689Skan
7233169689Skan found:
7234117395Skan  /* Slot was found.  */
7235117395Skan  additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7236117395Skan  if (additional_els_num < 0)
7237117395Skan    additional_els_num = 0;
7238117395Skan  /* Expand comb and check vectors.  */
7239117395Skan  vect_el = undefined_vect_el_value;
7240117395Skan  no_state_value = tab->automaton->achieved_states_num;
7241117395Skan  while (additional_els_num > 0)
7242117395Skan    {
7243169689Skan      VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7244169689Skan      VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7245117395Skan      additional_els_num--;
7246117395Skan    }
7247169689Skan  gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7248169689Skan	      >= comb_vect_index + real_vect_length);
7249117395Skan  /* Fill comb and check vectors.  */
7250117395Skan  for (vect_index = 0; vect_index < vect_length; vect_index++)
7251169689Skan    if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7252117395Skan      {
7253169689Skan	vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7254169689Skan        gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7255169689Skan			       comb_vect_index + vect_index)
7256169689Skan		    == undefined_vect_el_value);
7257169689Skan        gcc_assert (x >= 0);
7258169689Skan        if (tab->max_comb_vect_el_value < x)
7259169689Skan          tab->max_comb_vect_el_value = x;
7260169689Skan        if (tab->min_comb_vect_el_value > x)
7261169689Skan          tab->min_comb_vect_el_value = x;
7262169689Skan	VEC_replace (vect_el_t, tab->comb_vect,
7263169689Skan		     comb_vect_index + vect_index, x);
7264169689Skan	VEC_replace (vect_el_t, tab->check_vect,
7265169689Skan		     comb_vect_index + vect_index, vect_num);
7266117395Skan      }
7267132718Skan  if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7268132718Skan    tab->max_comb_vect_el_value = undefined_vect_el_value;
7269132718Skan  if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7270132718Skan    tab->min_comb_vect_el_value = undefined_vect_el_value;
7271117395Skan  if (tab->max_base_vect_el_value < comb_vect_index)
7272117395Skan    tab->max_base_vect_el_value = comb_vect_index;
7273117395Skan  if (tab->min_base_vect_el_value > comb_vect_index)
7274117395Skan    tab->min_base_vect_el_value = comb_vect_index;
7275169689Skan
7276169689Skan  VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7277117395Skan}
7278117395Skan
7279117395Skan/* Return number of out arcs of STATE.  */
7280117395Skanstatic int
7281132718Skanout_state_arcs_num (state_t state)
7282117395Skan{
7283117395Skan  int result;
7284117395Skan  arc_t arc;
7285117395Skan
7286117395Skan  result = 0;
7287117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7288117395Skan    {
7289169689Skan      gcc_assert (arc->insn);
7290169689Skan      if (arc->insn->first_ainsn_with_given_equivalence_num)
7291117395Skan        result++;
7292117395Skan    }
7293117395Skan  return result;
7294117395Skan}
7295117395Skan
7296117395Skan/* Compare number of possible transitions from the states.  */
7297117395Skanstatic int
7298132718Skancompare_transition_els_num (const void *state_ptr_1,
7299132718Skan			    const void *state_ptr_2)
7300117395Skan{
7301117395Skan  int transition_els_num_1;
7302117395Skan  int transition_els_num_2;
7303117395Skan
7304117395Skan  transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7305117395Skan  transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7306117395Skan  if (transition_els_num_1 < transition_els_num_2)
7307117395Skan    return 1;
7308117395Skan  else if (transition_els_num_1 == transition_els_num_2)
7309117395Skan    return 0;
7310117395Skan  else
7311117395Skan    return -1;
7312117395Skan}
7313117395Skan
7314117395Skan/* The function adds element EL_VALUE to vector VECT for a table state
7315117395Skan   x AINSN.  */
7316117395Skanstatic void
7317132718Skanadd_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7318117395Skan{
7319117395Skan  int equiv_class_num;
7320117395Skan  int vect_index;
7321117395Skan
7322169689Skan  gcc_assert (ainsn);
7323117395Skan  equiv_class_num = ainsn->insn_equiv_class_num;
7324169689Skan  for (vect_index = VEC_length (vect_el_t, *vect);
7325117395Skan       vect_index <= equiv_class_num;
7326117395Skan       vect_index++)
7327169689Skan    VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7328169689Skan  VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7329117395Skan}
7330117395Skan
7331117395Skan/* This is for forming vector of states of an automaton.  */
7332169689Skanstatic VEC(state_t,heap) *output_states_vect;
7333117395Skan
7334117395Skan/* The function is called by function pass_states.  The function adds
7335117395Skan   STATE to `output_states_vect'.  */
7336117395Skanstatic void
7337132718Skanadd_states_vect_el (state_t state)
7338117395Skan{
7339169689Skan  VEC_safe_push (state_t,heap, output_states_vect, state);
7340117395Skan}
7341117395Skan
7342117395Skan/* Form and output vectors (comb, check, base or full vector)
7343117395Skan   representing transition table of AUTOMATON.  */
7344117395Skanstatic void
7345132718Skanoutput_trans_table (automaton_t automaton)
7346117395Skan{
7347169689Skan  size_t i;
7348117395Skan  arc_t arc;
7349169689Skan  vla_hwint_t transition_vect = 0;
7350117395Skan
7351117395Skan  undefined_vect_el_value = automaton->achieved_states_num;
7352117395Skan  automaton->trans_table = create_state_ainsn_table (automaton);
7353117395Skan  /* Create vect of pointers to states ordered by num of transitions
7354117395Skan     from the state (state with the maximum num is the first).  */
7355169689Skan  output_states_vect = 0;
7356117395Skan  pass_states (automaton, add_states_vect_el);
7357169689Skan  qsort (VEC_address (state_t, output_states_vect),
7358169689Skan	 VEC_length (state_t, output_states_vect),
7359117395Skan         sizeof (state_t), compare_transition_els_num);
7360169689Skan
7361169689Skan  for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7362117395Skan    {
7363169689Skan      VEC_truncate (vect_el_t, transition_vect, 0);
7364169689Skan      for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7365117395Skan	   arc != NULL;
7366117395Skan	   arc = next_out_arc (arc))
7367117395Skan        {
7368169689Skan          gcc_assert (arc->insn);
7369169689Skan          if (arc->insn->first_ainsn_with_given_equivalence_num)
7370117395Skan            add_vect_el (&transition_vect, arc->insn,
7371117395Skan                         arc->to_state->order_state_num);
7372117395Skan        }
7373169689Skan      add_vect (automaton->trans_table,
7374169689Skan		VEC_index (state_t, output_states_vect, i)->order_state_num,
7375169689Skan		transition_vect);
7376117395Skan    }
7377117395Skan  output_state_ainsn_table
7378169689Skan    (automaton->trans_table, "state transitions",
7379117395Skan     output_trans_full_vect_name, output_trans_comb_vect_name,
7380117395Skan     output_trans_check_vect_name, output_trans_base_vect_name);
7381117395Skan
7382169689Skan  VEC_free (state_t,heap, output_states_vect);
7383169689Skan  VEC_free (vect_el_t,heap, transition_vect);
7384117395Skan}
7385117395Skan
7386117395Skan/* The current number of passing states to find minimal issue delay
7387117395Skan   value for an ainsn and state.  */
7388117395Skanstatic int curr_state_pass_num;
7389117395Skan
7390117395Skan/* This recursive function passes states to find minimal issue delay
7391117395Skan   value for AINSN.  The state being visited is STATE.  The function
7392117395Skan   returns minimal issue delay value for AINSN in STATE or -1 if we
7393117395Skan   enter into a loop.  */
7394117395Skanstatic int
7395132718Skanmin_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7396117395Skan{
7397117395Skan  arc_t arc;
7398117395Skan  int min_insn_issue_delay, insn_issue_delay;
7399117395Skan
7400117395Skan  if (state->state_pass_num == curr_state_pass_num
7401117395Skan      || state->min_insn_issue_delay != -1)
7402117395Skan    /* We've entered into a loop or already have the correct value for
7403117395Skan       given state and ainsn.  */
7404117395Skan    return state->min_insn_issue_delay;
7405117395Skan  state->state_pass_num = curr_state_pass_num;
7406117395Skan  min_insn_issue_delay = -1;
7407117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7408117395Skan    if (arc->insn == ainsn)
7409117395Skan      {
7410117395Skan	min_insn_issue_delay = 0;
7411117395Skan	break;
7412117395Skan      }
7413117395Skan    else
7414117395Skan      {
7415117395Skan        insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7416117395Skan	if (insn_issue_delay != -1)
7417117395Skan	  {
7418117395Skan	    if (arc->insn->insn_reserv_decl
7419117395Skan		== DECL_INSN_RESERV (advance_cycle_insn_decl))
7420117395Skan	      insn_issue_delay++;
7421117395Skan	    if (min_insn_issue_delay == -1
7422117395Skan		|| min_insn_issue_delay > insn_issue_delay)
7423117395Skan	      {
7424117395Skan		min_insn_issue_delay = insn_issue_delay;
7425117395Skan		if (insn_issue_delay == 0)
7426117395Skan		  break;
7427117395Skan	      }
7428117395Skan	  }
7429117395Skan      }
7430117395Skan  return min_insn_issue_delay;
7431117395Skan}
7432117395Skan
7433117395Skan/* The function searches minimal issue delay value for AINSN in STATE.
7434117395Skan   The function can return negative value if we can not issue AINSN.  We
7435117395Skan   will report about it later.  */
7436117395Skanstatic int
7437132718Skanmin_issue_delay (state_t state, ainsn_t ainsn)
7438117395Skan{
7439117395Skan  curr_state_pass_num++;
7440117395Skan  state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7441117395Skan  return state->min_insn_issue_delay;
7442117395Skan}
7443117395Skan
7444117395Skan/* The function initiates code for finding minimal issue delay values.
7445117395Skan   It should be called only once.  */
7446117395Skanstatic void
7447132718Skaninitiate_min_issue_delay_pass_states (void)
7448117395Skan{
7449117395Skan  curr_state_pass_num = 0;
7450117395Skan}
7451117395Skan
7452117395Skan/* Form and output vectors representing minimal issue delay table of
7453117395Skan   AUTOMATON.  The table is state x ainsn -> minimal issue delay of
7454117395Skan   the ainsn.  */
7455117395Skanstatic void
7456132718Skanoutput_min_issue_delay_table (automaton_t automaton)
7457117395Skan{
7458117395Skan  vla_hwint_t min_issue_delay_vect;
7459117395Skan  vla_hwint_t compressed_min_issue_delay_vect;
7460117395Skan  vect_el_t min_delay;
7461117395Skan  ainsn_t ainsn;
7462169689Skan  size_t i, min_issue_delay_len;
7463169689Skan  size_t compressed_min_issue_delay_len;
7464169689Skan  size_t cfactor;
7465117395Skan
7466117395Skan  /* Create vect of pointers to states ordered by num of transitions
7467117395Skan     from the state (state with the maximum num is the first).  */
7468169689Skan  output_states_vect = 0;
7469117395Skan  pass_states (automaton, add_states_vect_el);
7470169689Skan
7471169689Skan  min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7472169689Skan			 * automaton->insn_equiv_classes_num);
7473169689Skan  min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7474169689Skan  for (i = 0; i < min_issue_delay_len; i++)
7475169689Skan    VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7476169689Skan
7477117395Skan  automaton->max_min_delay = 0;
7478117395Skan  for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7479169689Skan    if (ainsn->first_ainsn_with_given_equivalence_num)
7480117395Skan      {
7481169689Skan	for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7482169689Skan	  VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7483169689Skan	for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7484117395Skan	  {
7485169689Skan	    state_t s = VEC_index (state_t, output_states_vect, i);
7486169689Skan            min_delay = min_issue_delay (s, ainsn);
7487117395Skan	    if (automaton->max_min_delay < min_delay)
7488117395Skan	      automaton->max_min_delay = min_delay;
7489169689Skan	    VEC_replace (vect_el_t, min_issue_delay_vect,
7490169689Skan			 s->order_state_num
7491169689Skan			 * automaton->insn_equiv_classes_num
7492169689Skan			 + ainsn->insn_equiv_class_num,
7493169689Skan			 min_delay);
7494117395Skan	  }
7495117395Skan      }
7496132718Skan  fprintf (output_file, "/* Vector of min issue delay of insns.  */\n");
7497117395Skan  fprintf (output_file, "static const ");
7498117395Skan  output_range_type (output_file, 0, automaton->max_min_delay);
7499117395Skan  fprintf (output_file, " ");
7500117395Skan  output_min_issue_delay_vect_name (output_file, automaton);
7501117395Skan  fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7502132718Skan  /* Compress the vector.  */
7503117395Skan  if (automaton->max_min_delay < 2)
7504169689Skan    cfactor = 8;
7505117395Skan  else if (automaton->max_min_delay < 4)
7506169689Skan    cfactor = 4;
7507117395Skan  else if (automaton->max_min_delay < 16)
7508169689Skan    cfactor = 2;
7509117395Skan  else
7510169689Skan    cfactor = 1;
7511169689Skan  automaton->min_issue_delay_table_compression_factor = cfactor;
7512169689Skan
7513169689Skan  compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7514169689Skan  compressed_min_issue_delay_vect
7515169689Skan    = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7516169689Skan
7517169689Skan  for (i = 0; i < compressed_min_issue_delay_len; i++)
7518169689Skan    VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7519169689Skan
7520169689Skan  for (i = 0; i < min_issue_delay_len; i++)
7521169689Skan    {
7522169689Skan      size_t ci = i / cfactor;
7523169689Skan      vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7524169689Skan      vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7525169689Skan
7526169689Skan      cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7527169689Skan      VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7528169689Skan    }
7529169689Skan  output_vect (compressed_min_issue_delay_vect);
7530117395Skan  fprintf (output_file, "};\n\n");
7531169689Skan  VEC_free (state_t,heap, output_states_vect);
7532169689Skan  VEC_free (vect_el_t,heap, min_issue_delay_vect);
7533169689Skan  VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7534117395Skan}
7535117395Skan
7536117395Skan/* Form and output vector representing the locked states of
7537117395Skan   AUTOMATON.  */
7538117395Skanstatic void
7539132718Skanoutput_dead_lock_vect (automaton_t automaton)
7540117395Skan{
7541169689Skan  size_t i;
7542117395Skan  arc_t arc;
7543169689Skan  vla_hwint_t dead_lock_vect = 0;
7544117395Skan
7545117395Skan  /* Create vect of pointers to states ordered by num of
7546117395Skan     transitions from the state (state with the maximum num is the
7547117395Skan     first).  */
7548169689Skan  automaton->locked_states = 0;
7549169689Skan  output_states_vect = 0;
7550117395Skan  pass_states (automaton, add_states_vect_el);
7551169689Skan
7552169689Skan  VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7553169689Skan		 VEC_length (state_t, output_states_vect));
7554169689Skan  for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7555117395Skan    {
7556169689Skan      state_t s = VEC_index (state_t, output_states_vect, i);
7557169689Skan      arc = first_out_arc (s);
7558169689Skan      gcc_assert (arc);
7559169689Skan      if (next_out_arc (arc) == NULL
7560169689Skan	  && (arc->insn->insn_reserv_decl
7561169689Skan	      == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7562169689Skan	{
7563169689Skan	  VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7564169689Skan	  automaton->locked_states++;
7565169689Skan	}
7566169689Skan      else
7567169689Skan	VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7568117395Skan    }
7569169689Skan  if (automaton->locked_states == 0)
7570169689Skan    return;
7571169689Skan
7572117395Skan  fprintf (output_file, "/* Vector for locked state flags.  */\n");
7573117395Skan  fprintf (output_file, "static const ");
7574117395Skan  output_range_type (output_file, 0, 1);
7575117395Skan  fprintf (output_file, " ");
7576117395Skan  output_dead_lock_vect_name (output_file, automaton);
7577117395Skan  fprintf (output_file, "[] = {\n");
7578169689Skan  output_vect (dead_lock_vect);
7579117395Skan  fprintf (output_file, "};\n\n");
7580169689Skan  VEC_free (state_t,heap, output_states_vect);
7581169689Skan  VEC_free (vect_el_t,heap, dead_lock_vect);
7582117395Skan}
7583117395Skan
7584117395Skan/* Form and output vector representing reserved units of the states of
7585117395Skan   AUTOMATON.  */
7586117395Skanstatic void
7587132718Skanoutput_reserved_units_table (automaton_t automaton)
7588117395Skan{
7589169689Skan  vla_hwint_t reserved_units_table = 0;
7590169689Skan  int state_byte_size;
7591169689Skan  int reserved_units_size;
7592169689Skan  size_t n;
7593117395Skan  int i;
7594117395Skan
7595169689Skan  if (description->query_units_num == 0)
7596169689Skan    return;
7597169689Skan
7598117395Skan  /* Create vect of pointers to states.  */
7599169689Skan  output_states_vect = 0;
7600117395Skan  pass_states (automaton, add_states_vect_el);
7601117395Skan  /* Create vector.  */
7602117395Skan  state_byte_size = (description->query_units_num + 7) / 8;
7603169689Skan  reserved_units_size = (VEC_length (state_t, output_states_vect)
7604169689Skan			 * state_byte_size);
7605169689Skan
7606169689Skan  reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7607169689Skan
7608169689Skan  for (i = 0; i < reserved_units_size; i++)
7609169689Skan    VEC_quick_push (vect_el_t, reserved_units_table, 0);
7610169689Skan  for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7611117395Skan    {
7612169689Skan      state_t s = VEC_index (state_t, output_states_vect, n);
7613117395Skan      for (i = 0; i < description->units_num; i++)
7614132718Skan	if (units_array [i]->query_p
7615169689Skan	    && first_cycle_unit_presence (s, i))
7616169689Skan	  {
7617169689Skan	    int ri = (s->order_state_num * state_byte_size
7618169689Skan		      + units_array [i]->query_num / 8);
7619169689Skan	    vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7620169689Skan
7621169689Skan	    x += 1 << (units_array [i]->query_num % 8);
7622169689Skan	    VEC_replace (vect_el_t, reserved_units_table, ri, x);
7623169689Skan	  }
7624117395Skan    }
7625169689Skan  fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7626117395Skan  fprintf (output_file, "/* Vector for reserved units of states.  */\n");
7627117395Skan  fprintf (output_file, "static const ");
7628117395Skan  output_range_type (output_file, 0, 255);
7629117395Skan  fprintf (output_file, " ");
7630117395Skan  output_reserved_units_table_name (output_file, automaton);
7631117395Skan  fprintf (output_file, "[] = {\n");
7632169689Skan  output_vect (reserved_units_table);
7633169689Skan  fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7634169689Skan	   CPU_UNITS_QUERY_MACRO_NAME);
7635169689Skan
7636169689Skan  VEC_free (state_t,heap, output_states_vect);
7637169689Skan  VEC_free (vect_el_t,heap, reserved_units_table);
7638117395Skan}
7639117395Skan
7640117395Skan/* The function outputs all tables representing DFA(s) used for fast
7641117395Skan   pipeline hazards recognition.  */
7642117395Skanstatic void
7643132718Skanoutput_tables (void)
7644117395Skan{
7645117395Skan  automaton_t automaton;
7646117395Skan
7647117395Skan  initiate_min_issue_delay_pass_states ();
7648117395Skan  for (automaton = description->first_automaton;
7649117395Skan       automaton != NULL;
7650117395Skan       automaton = automaton->next_automaton)
7651117395Skan    {
7652117395Skan      output_translate_vect (automaton);
7653117395Skan      output_trans_table (automaton);
7654117395Skan      output_min_issue_delay_table (automaton);
7655117395Skan      output_dead_lock_vect (automaton);
7656132718Skan      output_reserved_units_table (automaton);
7657117395Skan    }
7658117395Skan  fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7659117395Skan           DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7660117395Skan}
7661117395Skan
7662117395Skan/* The function outputs definition and value of PHR interface variable
7663117395Skan   `max_insn_queue_index'.  Its value is not less than maximal queue
7664117395Skan   length needed for the insn scheduler.  */
7665117395Skanstatic void
7666132718Skanoutput_max_insn_queue_index_def (void)
7667117395Skan{
7668117395Skan  int i, max, latency;
7669117395Skan  decl_t decl;
7670117395Skan
7671117395Skan  max = description->max_insn_reserv_cycles;
7672117395Skan  for (i = 0; i < description->decls_num; i++)
7673117395Skan    {
7674117395Skan      decl = description->decls [i];
7675117395Skan      if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7676117395Skan	{
7677117395Skan	  latency = DECL_INSN_RESERV (decl)->default_latency;
7678117395Skan	  if (latency > max)
7679117395Skan	    max = latency;
7680117395Skan	}
7681117395Skan      else if (decl->mode == dm_bypass)
7682117395Skan	{
7683117395Skan	  latency = DECL_BYPASS (decl)->latency;
7684117395Skan	  if (latency > max)
7685117395Skan	    max = latency;
7686117395Skan	}
7687117395Skan    }
7688117395Skan  for (i = 0; (1 << i) <= max; i++)
7689117395Skan    ;
7690169689Skan  gcc_assert (i >= 0);
7691169689Skan  fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7692169689Skan	   (1 << i) - 1);
7693117395Skan}
7694117395Skan
7695132718Skan/* The function outputs switch cases for insn reservations using
7696117395Skan   function *output_automata_list_code.  */
7697117395Skanstatic void
7698132718Skanoutput_insn_code_cases (void (*output_automata_list_code)
7699132718Skan			(automata_list_el_t))
7700117395Skan{
7701117395Skan  decl_t decl, decl2;
7702117395Skan  int i, j;
7703117395Skan
7704117395Skan  for (i = 0; i < description->decls_num; i++)
7705117395Skan    {
7706117395Skan      decl = description->decls [i];
7707117395Skan      if (decl->mode == dm_insn_reserv)
7708117395Skan	DECL_INSN_RESERV (decl)->processed_p = FALSE;
7709117395Skan    }
7710117395Skan  for (i = 0; i < description->decls_num; i++)
7711117395Skan    {
7712117395Skan      decl = description->decls [i];
7713117395Skan      if (decl->mode == dm_insn_reserv
7714117395Skan	  && !DECL_INSN_RESERV (decl)->processed_p)
7715117395Skan	{
7716117395Skan	  for (j = i; j < description->decls_num; j++)
7717117395Skan	    {
7718117395Skan	      decl2 = description->decls [j];
7719117395Skan	      if (decl2->mode == dm_insn_reserv
7720117395Skan		  && (DECL_INSN_RESERV (decl2)->important_automata_list
7721117395Skan		      == DECL_INSN_RESERV (decl)->important_automata_list))
7722117395Skan		{
7723117395Skan		  DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7724117395Skan		  fprintf (output_file, "    case %d: /* %s */\n",
7725117395Skan			   DECL_INSN_RESERV (decl2)->insn_num,
7726117395Skan			   DECL_INSN_RESERV (decl2)->name);
7727117395Skan		}
7728117395Skan	    }
7729117395Skan	  (*output_automata_list_code)
7730117395Skan	    (DECL_INSN_RESERV (decl)->important_automata_list);
7731117395Skan	}
7732117395Skan    }
7733117395Skan}
7734117395Skan
7735117395Skan
7736117395Skan/* The function outputs a code for evaluation of a minimal delay of
7737117395Skan   issue of insns which have reservations in given AUTOMATA_LIST.  */
7738117395Skanstatic void
7739132718Skanoutput_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7740117395Skan{
7741117395Skan  automata_list_el_t el;
7742117395Skan  automaton_t automaton;
7743117395Skan
7744117395Skan  for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7745117395Skan    {
7746117395Skan      automaton = el->automaton;
7747117395Skan      fprintf (output_file, "\n      %s = ", TEMPORARY_VARIABLE_NAME);
7748117395Skan      output_min_issue_delay_vect_name (output_file, automaton);
7749117395Skan      fprintf (output_file,
7750117395Skan	       (automaton->min_issue_delay_table_compression_factor != 1
7751117395Skan		? " [(" : " ["));
7752117395Skan      output_translate_vect_name (output_file, automaton);
7753117395Skan      fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7754117395Skan      fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7755117395Skan      output_chip_member_name (output_file, automaton);
7756117395Skan      fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7757117395Skan      if (automaton->min_issue_delay_table_compression_factor == 1)
7758117395Skan	fprintf (output_file, "];\n");
7759117395Skan      else
7760117395Skan	{
7761117395Skan	  fprintf (output_file, ") / %d];\n",
7762117395Skan		   automaton->min_issue_delay_table_compression_factor);
7763117395Skan	  fprintf (output_file, "      %s = (%s >> (8 - (",
7764117395Skan		   TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7765117395Skan	  output_translate_vect_name (output_file, automaton);
7766117395Skan	  fprintf
7767117395Skan	    (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7768117395Skan	     INTERNAL_INSN_CODE_NAME,
7769117395Skan	     automaton->min_issue_delay_table_compression_factor,
7770117395Skan	     8 / automaton->min_issue_delay_table_compression_factor,
7771117395Skan	     (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7772117395Skan	     - 1);
7773117395Skan	}
7774117395Skan      if (el == automata_list)
7775117395Skan	fprintf (output_file, "      %s = %s;\n",
7776117395Skan		 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7777117395Skan      else
7778117395Skan	{
7779117395Skan	  fprintf (output_file, "      if (%s > %s)\n",
7780117395Skan		   TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7781117395Skan	  fprintf (output_file, "        %s = %s;\n",
7782117395Skan		   RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7783117395Skan	}
7784117395Skan    }
7785117395Skan  fprintf (output_file, "      break;\n\n");
7786117395Skan}
7787117395Skan
7788117395Skan/* Output function `internal_min_issue_delay'.  */
7789117395Skanstatic void
7790132718Skanoutput_internal_min_issue_delay_func (void)
7791117395Skan{
7792117395Skan  fprintf (output_file,
7793132718Skan	   "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7794117395Skan	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7795132718Skan	   CHIP_NAME, CHIP_PARAMETER_NAME);
7796117395Skan  fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n  int %s = -1;\n",
7797117395Skan	   TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7798117395Skan  fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
7799117395Skan  output_insn_code_cases (output_automata_list_min_issue_delay_code);
7800117395Skan  fprintf (output_file,
7801117395Skan	   "\n    default:\n      %s = -1;\n      break;\n    }\n",
7802117395Skan	   RESULT_VARIABLE_NAME);
7803117395Skan  fprintf (output_file, "  return %s;\n", RESULT_VARIABLE_NAME);
7804117395Skan  fprintf (output_file, "}\n\n");
7805117395Skan}
7806117395Skan
7807117395Skan/* The function outputs a code changing state after issue of insns
7808117395Skan   which have reservations in given AUTOMATA_LIST.  */
7809117395Skanstatic void
7810132718Skanoutput_automata_list_transition_code (automata_list_el_t automata_list)
7811117395Skan{
7812117395Skan  automata_list_el_t el, next_el;
7813117395Skan
7814117395Skan  fprintf (output_file, "      {\n");
7815117395Skan  if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7816117395Skan    for (el = automata_list;; el = next_el)
7817117395Skan      {
7818117395Skan        next_el = el->next_automata_list_el;
7819117395Skan        if (next_el == NULL)
7820117395Skan          break;
7821117395Skan        fprintf (output_file, "        ");
7822117395Skan        output_state_member_type (output_file, el->automaton);
7823117395Skan	fprintf (output_file, " ");
7824117395Skan        output_temp_chip_member_name (output_file, el->automaton);
7825117395Skan        fprintf (output_file, ";\n");
7826117395Skan      }
7827117395Skan  for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7828117395Skan    if (comb_vect_p (el->automaton->trans_table))
7829117395Skan      {
7830117395Skan	fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);
7831117395Skan	output_trans_base_vect_name (output_file, el->automaton);
7832117395Skan	fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7833117395Skan	output_chip_member_name (output_file, el->automaton);
7834117395Skan	fprintf (output_file, "] + ");
7835117395Skan	output_translate_vect_name (output_file, el->automaton);
7836117395Skan	fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7837117395Skan	fprintf (output_file, "        if (");
7838117395Skan	output_trans_check_vect_name (output_file, el->automaton);
7839117395Skan	fprintf (output_file, " [%s] != %s->",
7840117395Skan		 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7841117395Skan	output_chip_member_name (output_file, el->automaton);
7842117395Skan	fprintf (output_file, ")\n");
7843117395Skan	fprintf (output_file, "          return %s (%s, %s);\n",
7844117395Skan		 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7845117395Skan		 CHIP_PARAMETER_NAME);
7846117395Skan	fprintf (output_file, "        else\n");
7847117395Skan	fprintf (output_file, "          ");
7848117395Skan	if (el->next_automata_list_el != NULL)
7849117395Skan	  output_temp_chip_member_name (output_file, el->automaton);
7850117395Skan	else
7851117395Skan	  {
7852117395Skan	    fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7853117395Skan	    output_chip_member_name (output_file, el->automaton);
7854117395Skan	  }
7855117395Skan	fprintf (output_file, " = ");
7856117395Skan	output_trans_comb_vect_name (output_file, el->automaton);
7857117395Skan	fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7858117395Skan      }
7859117395Skan    else
7860117395Skan      {
7861117395Skan	fprintf (output_file, "\n        %s = ", TEMPORARY_VARIABLE_NAME);
7862117395Skan	output_trans_full_vect_name (output_file, el->automaton);
7863117395Skan	fprintf (output_file, " [");
7864117395Skan	output_translate_vect_name (output_file, el->automaton);
7865117395Skan	fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7866117395Skan	fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7867117395Skan	output_chip_member_name (output_file, el->automaton);
7868117395Skan	fprintf (output_file, " * %d];\n",
7869117395Skan		 el->automaton->insn_equiv_classes_num);
7870117395Skan	fprintf (output_file, "        if (%s >= %d)\n",
7871117395Skan		 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7872117395Skan	fprintf (output_file, "          return %s (%s, %s);\n",
7873117395Skan		 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7874117395Skan		 CHIP_PARAMETER_NAME);
7875117395Skan	fprintf (output_file, "        else\n          ");
7876117395Skan	if (el->next_automata_list_el != NULL)
7877117395Skan	  output_temp_chip_member_name (output_file, el->automaton);
7878117395Skan	else
7879117395Skan	  {
7880117395Skan	    fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7881117395Skan	    output_chip_member_name (output_file, el->automaton);
7882117395Skan	  }
7883117395Skan	fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7884117395Skan      }
7885117395Skan  if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7886117395Skan    for (el = automata_list;; el = next_el)
7887117395Skan      {
7888117395Skan        next_el = el->next_automata_list_el;
7889117395Skan        if (next_el == NULL)
7890117395Skan          break;
7891117395Skan        fprintf (output_file, "        %s->", CHIP_PARAMETER_NAME);
7892117395Skan        output_chip_member_name (output_file, el->automaton);
7893117395Skan        fprintf (output_file, " = ");
7894117395Skan        output_temp_chip_member_name (output_file, el->automaton);
7895117395Skan        fprintf (output_file, ";\n");
7896117395Skan      }
7897117395Skan  fprintf (output_file, "        return -1;\n");
7898117395Skan  fprintf (output_file, "      }\n");
7899117395Skan}
7900117395Skan
7901117395Skan/* Output function `internal_state_transition'.  */
7902117395Skanstatic void
7903132718Skanoutput_internal_trans_func (void)
7904117395Skan{
7905117395Skan  fprintf (output_file,
7906132718Skan	   "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7907117395Skan	   INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7908117395Skan	   CHIP_NAME, CHIP_PARAMETER_NAME);
7909117395Skan  fprintf (output_file, "{\n  int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7910117395Skan  fprintf (output_file, "\n  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
7911117395Skan  output_insn_code_cases (output_automata_list_transition_code);
7912117395Skan  fprintf (output_file, "\n    default:\n      return -1;\n    }\n");
7913117395Skan  fprintf (output_file, "}\n\n");
7914117395Skan}
7915117395Skan
7916117395Skan/* Output code
7917117395Skan
7918117395Skan  if (insn != 0)
7919117395Skan    {
7920117395Skan      insn_code = dfa_insn_code (insn);
7921117395Skan      if (insn_code > DFA__ADVANCE_CYCLE)
7922117395Skan        return code;
7923117395Skan    }
7924117395Skan  else
7925117395Skan    insn_code = DFA__ADVANCE_CYCLE;
7926117395Skan
7927117395Skan  where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7928117395Skan  code denotes CODE.  */
7929117395Skanstatic void
7930132718Skanoutput_internal_insn_code_evaluation (const char *insn_name,
7931132718Skan				      const char *insn_code_name,
7932132718Skan				      int code)
7933117395Skan{
7934117395Skan  fprintf (output_file, "\n  if (%s != 0)\n    {\n", insn_name);
7935117395Skan  fprintf (output_file, "      %s = %s (%s);\n", insn_code_name,
7936117395Skan	   DFA_INSN_CODE_FUNC_NAME, insn_name);
7937117395Skan  fprintf (output_file, "      if (%s > %s)\n        return %d;\n",
7938117395Skan	   insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7939117395Skan  fprintf (output_file, "    }\n  else\n    %s = %s;\n\n",
7940117395Skan	   insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7941117395Skan}
7942117395Skan
7943117395Skan
7944132718Skan/* This function outputs `dfa_insn_code' and its helper function
7945132718Skan   `dfa_insn_code_enlarge'.  */
7946117395Skanstatic void
7947132718Skanoutput_dfa_insn_code_func (void)
7948117395Skan{
7949132718Skan  /* Emacs c-mode gets really confused if there's a { or } in column 0
7950132718Skan     inside a string, so don't do that.  */
7951132718Skan  fprintf (output_file, "\
7952132718Skanstatic void\n\
7953132718Skandfa_insn_code_enlarge (int uid)\n\
7954132718Skan{\n\
7955132718Skan  int i = %s;\n\
7956132718Skan  %s = 2 * uid;\n\
7957132718Skan  %s = xrealloc (%s,\n\
7958132718Skan                 %s * sizeof(int));\n\
7959132718Skan  for (; i < %s; i++)\n\
7960132718Skan    %s[i] = -1;\n}\n\n",
7961132718Skan	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7962132718Skan	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7963117395Skan	   DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7964132718Skan	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7965132718Skan	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7966132718Skan	   DFA_INSN_CODES_VARIABLE_NAME);
7967132718Skan  fprintf (output_file, "\
7968132718Skanstatic inline int\n%s (rtx %s)\n\
7969132718Skan{\n\
7970132718Skan  int uid = INSN_UID (%s);\n\
7971132718Skan  int %s;\n\n",
7972132718Skan	   DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7973132718Skan	   INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7974132718Skan
7975132718Skan  fprintf (output_file,
7976132718Skan	   "  if (uid >= %s)\n    dfa_insn_code_enlarge (uid);\n\n",
7977117395Skan	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7978132718Skan  fprintf (output_file, "  %s = %s[uid];\n",
7979132718Skan	   INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7980132718Skan  fprintf (output_file, "\
7981132718Skan  if (%s < 0)\n\
7982132718Skan    {\n\
7983132718Skan      %s = %s (%s);\n\
7984132718Skan      %s[uid] = %s;\n\
7985132718Skan    }\n",
7986132718Skan	   INTERNAL_INSN_CODE_NAME,
7987132718Skan	   INTERNAL_INSN_CODE_NAME,
7988132718Skan	   INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7989132718Skan	   DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7990132718Skan  fprintf (output_file, "  return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7991117395Skan}
7992117395Skan
7993117395Skan/* The function outputs PHR interface function `state_transition'.  */
7994117395Skanstatic void
7995132718Skanoutput_trans_func (void)
7996117395Skan{
7997132718Skan  fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7998132718Skan	   TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7999132718Skan	   INSN_PARAMETER_NAME);
8000117395Skan  fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
8001117395Skan  output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8002117395Skan					INTERNAL_INSN_CODE_NAME, -1);
8003117395Skan  fprintf (output_file, "  return %s (%s, %s);\n}\n\n",
8004117395Skan	   INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8005117395Skan}
8006117395Skan
8007117395Skan/* Output function `min_issue_delay'.  */
8008117395Skanstatic void
8009132718Skanoutput_min_issue_delay_func (void)
8010117395Skan{
8011132718Skan  fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8012132718Skan	   MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8013132718Skan	   INSN_PARAMETER_NAME);
8014117395Skan  fprintf (output_file, "{\n  int %s;\n", INTERNAL_INSN_CODE_NAME);
8015117395Skan  fprintf (output_file, "\n  if (%s != 0)\n    {\n", INSN_PARAMETER_NAME);
8016117395Skan  fprintf (output_file, "      %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8017117395Skan	   DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8018117395Skan  fprintf (output_file, "      if (%s > %s)\n        return 0;\n",
8019117395Skan	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8020117395Skan  fprintf (output_file, "    }\n  else\n    %s = %s;\n",
8021117395Skan	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8022117395Skan  fprintf (output_file, "\n  return %s (%s, %s);\n",
8023132718Skan	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8024117395Skan	   STATE_NAME);
8025117395Skan  fprintf (output_file, "}\n\n");
8026117395Skan}
8027117395Skan
8028117395Skan/* Output function `internal_dead_lock'.  */
8029117395Skanstatic void
8030132718Skanoutput_internal_dead_lock_func (void)
8031117395Skan{
8032117395Skan  automaton_t automaton;
8033117395Skan
8034169689Skan  fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8035132718Skan	   INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8036117395Skan  fprintf (output_file, "{\n");
8037117395Skan  for (automaton = description->first_automaton;
8038117395Skan       automaton != NULL;
8039117395Skan       automaton = automaton->next_automaton)
8040169689Skan    if (automaton->locked_states)
8041169689Skan      {
8042169689Skan	fprintf (output_file, "  if (");
8043169689Skan	output_dead_lock_vect_name (output_file, automaton);
8044169689Skan	fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8045169689Skan	output_chip_member_name (output_file, automaton);
8046169689Skan	fprintf (output_file, "])\n    return 1/* TRUE */;\n");
8047169689Skan      }
8048117395Skan  fprintf (output_file, "  return 0/* FALSE */;\n}\n\n");
8049117395Skan}
8050117395Skan
8051117395Skan/* The function outputs PHR interface function `state_dead_lock_p'.  */
8052117395Skanstatic void
8053132718Skanoutput_dead_lock_func (void)
8054117395Skan{
8055132718Skan  fprintf (output_file, "int\n%s (%s %s)\n",
8056132718Skan	   DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8057117395Skan  fprintf (output_file, "{\n  return %s (%s);\n}\n\n",
8058117395Skan	   INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8059117395Skan}
8060117395Skan
8061117395Skan/* Output function `internal_reset'.  */
8062117395Skanstatic void
8063132718Skanoutput_internal_reset_func (void)
8064117395Skan{
8065132718Skan  fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8066132718Skan	   INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8067117395Skan  fprintf (output_file, "{\n  memset (%s, 0, sizeof (struct %s));\n}\n\n",
8068117395Skan	   CHIP_PARAMETER_NAME, CHIP_NAME);
8069117395Skan}
8070117395Skan
8071117395Skan/* The function outputs PHR interface function `state_size'.  */
8072117395Skanstatic void
8073132718Skanoutput_size_func (void)
8074117395Skan{
8075132718Skan  fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8076117395Skan  fprintf (output_file, "{\n  return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8077117395Skan}
8078117395Skan
8079117395Skan/* The function outputs PHR interface function `state_reset'.  */
8080117395Skanstatic void
8081132718Skanoutput_reset_func (void)
8082117395Skan{
8083132718Skan  fprintf (output_file, "void\n%s (%s %s)\n",
8084132718Skan	   RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8085117395Skan  fprintf (output_file, "{\n  %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8086117395Skan	   STATE_NAME);
8087117395Skan}
8088117395Skan
8089117395Skan/* Output function `min_insn_conflict_delay'.  */
8090117395Skanstatic void
8091132718Skanoutput_min_insn_conflict_delay_func (void)
8092117395Skan{
8093117395Skan  fprintf (output_file,
8094132718Skan	   "int\n%s (%s %s, rtx %s, rtx %s)\n",
8095132718Skan	   MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8096132718Skan	   STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8097169689Skan  fprintf (output_file, "{\n  struct %s %s;\n  int %s, %s, transition;\n",
8098117395Skan	   CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8099117395Skan	   INTERNAL_INSN2_CODE_NAME);
8100117395Skan  output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8101117395Skan					INTERNAL_INSN_CODE_NAME, 0);
8102117395Skan  output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8103117395Skan					INTERNAL_INSN2_CODE_NAME, 0);
8104117395Skan  fprintf (output_file, "  memcpy (&%s, %s, sizeof (%s));\n",
8105117395Skan	   CHIP_NAME, STATE_NAME, CHIP_NAME);
8106117395Skan  fprintf (output_file, "  %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8107169689Skan  fprintf (output_file, "  transition = %s (%s, &%s);\n",
8108117395Skan	   INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8109169689Skan  fprintf (output_file, "  gcc_assert (transition <= 0);\n");
8110117395Skan  fprintf (output_file, "  return %s (%s, &%s);\n",
8111117395Skan	   INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8112117395Skan	   CHIP_NAME);
8113117395Skan  fprintf (output_file, "}\n\n");
8114117395Skan}
8115117395Skan
8116117395Skan/* Output function `internal_insn_latency'.  */
8117117395Skanstatic void
8118132718Skanoutput_internal_insn_latency_func (void)
8119117395Skan{
8120117395Skan  decl_t decl;
8121117395Skan  struct bypass_decl *bypass;
8122132718Skan  int i, j, col;
8123132718Skan  const char *tabletype = "unsigned char";
8124117395Skan
8125132718Skan  /* Find the smallest integer type that can hold all the default
8126132718Skan     latency values.  */
8127132718Skan  for (i = 0; i < description->decls_num; i++)
8128132718Skan    if (description->decls[i]->mode == dm_insn_reserv)
8129132718Skan      {
8130132718Skan	decl = description->decls[i];
8131132718Skan	if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8132132718Skan	    && tabletype[0] != 'i')  /* Don't shrink it.  */
8133132718Skan	  tabletype = "unsigned short";
8134132718Skan	if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8135132718Skan	  tabletype = "int";
8136132718Skan      }
8137132718Skan
8138132718Skan  fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\tint %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8139117395Skan	   INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8140117395Skan	   INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8141117395Skan	   INSN2_PARAMETER_NAME);
8142132718Skan  fprintf (output_file, "{\n");
8143132718Skan
8144132718Skan  if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8145117395Skan    {
8146132718Skan      fputs ("  return 0;\n}\n\n", output_file);
8147132718Skan      return;
8148117395Skan    }
8149132718Skan
8150132718Skan  fprintf (output_file, "  static const %s default_latencies[] =\n    {",
8151132718Skan	   tabletype);
8152132718Skan
8153132718Skan  for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8154132718Skan    if (description->decls[i]->mode == dm_insn_reserv
8155132718Skan	&& description->decls[i] != advance_cycle_insn_decl)
8156132718Skan      {
8157132718Skan	if ((col = (col+1) % 8) == 0)
8158132718Skan	  fputs ("\n     ", output_file);
8159132718Skan	decl = description->decls[i];
8160169689Skan	gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8161132718Skan	fprintf (output_file, "% 4d,",
8162132718Skan		 DECL_INSN_RESERV (decl)->default_latency);
8163132718Skan      }
8164169689Skan  gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8165132718Skan  fputs ("\n    };\n", output_file);
8166132718Skan
8167132718Skan  fprintf (output_file, "  if (%s >= %s || %s >= %s)\n    return 0;\n",
8168132718Skan	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8169132718Skan	   INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8170132718Skan
8171132718Skan  fprintf (output_file, "  switch (%s)\n    {\n", INTERNAL_INSN_CODE_NAME);
8172132718Skan  for (i = 0; i < description->decls_num; i++)
8173132718Skan    if (description->decls[i]->mode == dm_insn_reserv
8174132718Skan	&& DECL_INSN_RESERV (description->decls[i])->bypass_list)
8175132718Skan      {
8176132718Skan	decl = description->decls [i];
8177132718Skan	fprintf (output_file,
8178132718Skan		 "    case %d:\n      switch (%s)\n        {\n",
8179132718Skan		 DECL_INSN_RESERV (decl)->insn_num,
8180132718Skan		 INTERNAL_INSN2_CODE_NAME);
8181132718Skan	for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8182132718Skan	     bypass != NULL;
8183132718Skan	     bypass = bypass->next)
8184132718Skan	  {
8185169689Skan	    gcc_assert (bypass->in_insn_reserv->insn_num
8186169689Skan			!= (DECL_INSN_RESERV
8187169689Skan			    (advance_cycle_insn_decl)->insn_num));
8188132718Skan	    fprintf (output_file, "        case %d:\n",
8189132718Skan		     bypass->in_insn_reserv->insn_num);
8190132718Skan	    if (bypass->bypass_guard_name == NULL)
8191132718Skan	      fprintf (output_file, "          return %d;\n",
8192132718Skan		       bypass->latency);
8193132718Skan	    else
8194132718Skan	      {
8195132718Skan		fprintf (output_file,
8196132718Skan			 "          if (%s (%s, %s))\n",
8197132718Skan			 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8198132718Skan			 INSN2_PARAMETER_NAME);
8199132718Skan		fprintf (output_file,
8200132718Skan			 "            return %d;\n          break;\n",
8201132718Skan			 bypass->latency);
8202132718Skan	      }
8203132718Skan	  }
8204132718Skan	fputs ("        }\n      break;\n", output_file);
8205132718Skan      }
8206132718Skan
8207132718Skan  fprintf (output_file, "    }\n  return default_latencies[%s];\n}\n\n",
8208132718Skan	   INTERNAL_INSN_CODE_NAME);
8209117395Skan}
8210117395Skan
8211117395Skan/* The function outputs PHR interface function `insn_latency'.  */
8212117395Skanstatic void
8213132718Skanoutput_insn_latency_func (void)
8214117395Skan{
8215132718Skan  fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8216132718Skan	   INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8217117395Skan  fprintf (output_file, "{\n  int %s, %s;\n",
8218117395Skan	   INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8219117395Skan  output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8220117395Skan					INTERNAL_INSN_CODE_NAME, 0);
8221117395Skan  output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8222117395Skan					INTERNAL_INSN2_CODE_NAME, 0);
8223117395Skan  fprintf (output_file, "  return %s (%s, %s, %s, %s);\n}\n\n",
8224117395Skan	   INTERNAL_INSN_LATENCY_FUNC_NAME,
8225117395Skan	   INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8226117395Skan	   INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8227117395Skan}
8228117395Skan
8229117395Skan/* The function outputs PHR interface function `print_reservation'.  */
8230117395Skanstatic void
8231132718Skanoutput_print_reservation_func (void)
8232117395Skan{
8233117395Skan  decl_t decl;
8234132718Skan  int i, j;
8235117395Skan
8236132718Skan  fprintf (output_file,
8237132718Skan	   "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8238117395Skan           PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8239117395Skan           INSN_PARAMETER_NAME);
8240132718Skan
8241132718Skan  if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8242117395Skan    {
8243132718Skan      fprintf (output_file, "  fputs (\"%s\", %s);\n}\n\n",
8244132718Skan	       NOTHING_NAME, FILE_PARAMETER_NAME);
8245132718Skan      return;
8246132718Skan    }
8247132718Skan
8248132718Skan
8249132718Skan  fputs ("  static const char *const reservation_names[] =\n    {",
8250132718Skan	 output_file);
8251132718Skan
8252132718Skan  for (i = 0, j = 0; i < description->decls_num; i++)
8253132718Skan    {
8254117395Skan      decl = description->decls [i];
8255117395Skan      if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8256117395Skan	{
8257169689Skan	  gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8258169689Skan	  j++;
8259169689Skan
8260132718Skan	  fprintf (output_file, "\n      \"%s\",",
8261132718Skan		   regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8262132718Skan	  finish_regexp_representation ();
8263132718Skan	}
8264117395Skan    }
8265169689Skan  gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8266132718Skan
8267132718Skan  fprintf (output_file, "\n      \"%s\"\n    };\n  int %s;\n\n",
8268132718Skan	   NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8269132718Skan
8270132718Skan  fprintf (output_file, "  if (%s == 0)\n    %s = %s;\n",
8271132718Skan	   INSN_PARAMETER_NAME,
8272132718Skan	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8273132718Skan  fprintf (output_file, "  else\n\
8274132718Skan    {\n\
8275132718Skan      %s = %s (%s);\n\
8276132718Skan      if (%s > %s)\n\
8277132718Skan        %s = %s;\n\
8278132718Skan    }\n",
8279132718Skan	   INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8280132718Skan	       INSN_PARAMETER_NAME,
8281132718Skan	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8282132718Skan	   INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8283132718Skan
8284132718Skan  fprintf (output_file, "  fputs (reservation_names[%s], %s);\n}\n\n",
8285132718Skan	   INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8286117395Skan}
8287117395Skan
8288117395Skan/* The following function is used to sort unit declaration by their
8289117395Skan   names.  */
8290117395Skanstatic int
8291132718Skanunits_cmp (const void *unit1, const void *unit2)
8292117395Skan{
8293117395Skan  const unit_decl_t u1 = *(unit_decl_t *) unit1;
8294117395Skan  const unit_decl_t u2 = *(unit_decl_t *) unit2;
8295117395Skan
8296117395Skan  return strcmp (u1->name, u2->name);
8297117395Skan}
8298117395Skan
8299117395Skan/* The following macro value is name of struct containing unit name
8300117395Skan   and unit code.  */
8301117395Skan#define NAME_CODE_STRUCT_NAME  "name_code"
8302117395Skan
8303117395Skan/* The following macro value is name of table of struct name_code.  */
8304117395Skan#define NAME_CODE_TABLE_NAME   "name_code_table"
8305117395Skan
8306117395Skan/* The following macro values are member names for struct name_code.  */
8307117395Skan#define NAME_MEMBER_NAME       "name"
8308117395Skan#define CODE_MEMBER_NAME       "code"
8309117395Skan
8310117395Skan/* The following macro values are local variable names for function
8311117395Skan   `get_cpu_unit_code'.  */
8312117395Skan#define CMP_VARIABLE_NAME      "cmp"
8313117395Skan#define LOW_VARIABLE_NAME      "l"
8314117395Skan#define MIDDLE_VARIABLE_NAME   "m"
8315117395Skan#define HIGH_VARIABLE_NAME     "h"
8316117395Skan
8317117395Skan/* The following function outputs function to obtain internal cpu unit
8318117395Skan   code by the cpu unit name.  */
8319117395Skanstatic void
8320132718Skanoutput_get_cpu_unit_code_func (void)
8321117395Skan{
8322117395Skan  int i;
8323117395Skan  unit_decl_t *units;
8324132718Skan
8325169689Skan  fprintf (output_file, "int\n%s (const char *%s)\n",
8326169689Skan	   GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8327117395Skan  fprintf (output_file, "{\n  struct %s {const char *%s; int %s;};\n",
8328117395Skan	   NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8329117395Skan  fprintf (output_file, "  int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8330117395Skan	   LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8331117395Skan  fprintf (output_file, "  static struct %s %s [] =\n    {\n",
8332117395Skan	   NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8333132718Skan  units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8334117395Skan  memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8335117395Skan  qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8336117395Skan  for (i = 0; i < description->units_num; i++)
8337117395Skan    if (units [i]->query_p)
8338117395Skan      fprintf (output_file, "      {\"%s\", %d},\n",
8339117395Skan	       units[i]->name, units[i]->query_num);
8340117395Skan  fprintf (output_file, "    };\n\n");
8341117395Skan  fprintf (output_file, "  /* The following is binary search: */\n");
8342117395Skan  fprintf (output_file, "  %s = 0;\n", LOW_VARIABLE_NAME);
8343117395Skan  fprintf (output_file, "  %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8344117395Skan	   HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8345117395Skan  fprintf (output_file, "  while (%s <= %s)\n    {\n",
8346117395Skan	   LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8347117395Skan  fprintf (output_file, "      %s = (%s + %s) / 2;\n",
8348117395Skan	   MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8349117395Skan  fprintf (output_file, "      %s = strcmp (%s, %s [%s].%s);\n",
8350117395Skan	   CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8351117395Skan	   NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8352117395Skan  fprintf (output_file, "      if (%s < 0)\n", CMP_VARIABLE_NAME);
8353117395Skan  fprintf (output_file, "        %s = %s - 1;\n",
8354117395Skan	   HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8355117395Skan  fprintf (output_file, "      else if (%s > 0)\n", CMP_VARIABLE_NAME);
8356117395Skan  fprintf (output_file, "        %s = %s + 1;\n",
8357117395Skan	   LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8358117395Skan  fprintf (output_file, "      else\n");
8359117395Skan  fprintf (output_file, "        return %s [%s].%s;\n    }\n",
8360117395Skan	   NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8361117395Skan  fprintf (output_file, "  return -1;\n}\n\n");
8362117395Skan  free (units);
8363117395Skan}
8364117395Skan
8365117395Skan/* The following function outputs function to check reservation of cpu
8366117395Skan   unit (its internal code will be passed as the function argument) in
8367117395Skan   given cpu state.  */
8368117395Skanstatic void
8369132718Skanoutput_cpu_unit_reservation_p (void)
8370117395Skan{
8371117395Skan  automaton_t automaton;
8372117395Skan
8373169689Skan  fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8374169689Skan	   CPU_UNIT_RESERVATION_P_FUNC_NAME,
8375169689Skan	   STATE_TYPE_NAME, STATE_NAME,
8376117395Skan	   CPU_CODE_PARAMETER_NAME);
8377169689Skan  fprintf (output_file, "{\n  gcc_assert (%s >= 0 && %s < %d);\n",
8378117395Skan	   CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8379117395Skan	   description->query_units_num);
8380169689Skan  if (description->query_units_num > 0)
8381169689Skan    for (automaton = description->first_automaton;
8382169689Skan	 automaton != NULL;
8383169689Skan	 automaton = automaton->next_automaton)
8384169689Skan      {
8385169689Skan	fprintf (output_file, "  if ((");
8386169689Skan	output_reserved_units_table_name (output_file, automaton);
8387169689Skan	fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8388169689Skan	output_chip_member_name (output_file, automaton);
8389169689Skan	fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8390169689Skan		 (description->query_units_num + 7) / 8,
8391169689Skan		 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8392169689Skan	fprintf (output_file, "    return 1;\n");
8393169689Skan      }
8394117395Skan  fprintf (output_file, "  return 0;\n}\n\n");
8395117395Skan}
8396117395Skan
8397169689Skan/* The function outputs PHR interface functions `dfa_clean_insn_cache'
8398169689Skan   and 'dfa_clear_single_insn_cache'.  */
8399117395Skanstatic void
8400132718Skanoutput_dfa_clean_insn_cache_func (void)
8401117395Skan{
8402117395Skan  fprintf (output_file,
8403132718Skan	   "void\n%s (void)\n{\n  int %s;\n\n",
8404132718Skan	   DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8405117395Skan  fprintf (output_file,
8406117395Skan	   "  for (%s = 0; %s < %s; %s++)\n    %s [%s] = -1;\n}\n\n",
8407117395Skan	   I_VARIABLE_NAME, I_VARIABLE_NAME,
8408117395Skan	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8409117395Skan	   DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8410169689Skan
8411169689Skan  fprintf (output_file,
8412169689Skan           "void\n%s (rtx %s)\n{\n  int %s;\n\n",
8413169689Skan           DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8414169689Skan	   I_VARIABLE_NAME);
8415169689Skan  fprintf (output_file,
8416169689Skan           "  %s = INSN_UID (%s);\n  if (%s < %s)\n    %s [%s] = -1;\n}\n\n",
8417169689Skan           I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8418169689Skan	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8419169689Skan	   I_VARIABLE_NAME);
8420117395Skan}
8421117395Skan
8422132718Skan/* The function outputs PHR interface function `dfa_start'.  */
8423132718Skanstatic void
8424132718Skanoutput_dfa_start_func (void)
8425132718Skan{
8426132718Skan  fprintf (output_file,
8427132718Skan	   "void\n%s (void)\n{\n  %s = get_max_uid ();\n",
8428132718Skan	   DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8429132718Skan  fprintf (output_file, "  %s = xmalloc (%s * sizeof (int));\n",
8430132718Skan	   DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8431132718Skan  fprintf (output_file, "  %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8432132718Skan}
8433132718Skan
8434117395Skan/* The function outputs PHR interface function `dfa_finish'.  */
8435117395Skanstatic void
8436132718Skanoutput_dfa_finish_func (void)
8437117395Skan{
8438132718Skan  fprintf (output_file, "void\n%s (void)\n{\n  free (%s);\n}\n\n",
8439117395Skan	   DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8440117395Skan}
8441117395Skan
8442117395Skan
8443117395Skan
8444117395Skan/* The page contains code for output description file (readable
8445117395Skan   representation of original description and generated DFA(s).  */
8446117395Skan
8447117395Skan/* The function outputs string representation of IR reservation.  */
8448117395Skanstatic void
8449132718Skanoutput_regexp (regexp_t regexp)
8450117395Skan{
8451117395Skan  fprintf (output_description_file, "%s", regexp_representation (regexp));
8452117395Skan  finish_regexp_representation ();
8453117395Skan}
8454117395Skan
8455117395Skan/* Output names of units in LIST separated by comma.  */
8456117395Skanstatic void
8457132718Skanoutput_unit_set_el_list (unit_set_el_t list)
8458117395Skan{
8459117395Skan  unit_set_el_t el;
8460117395Skan
8461117395Skan  for (el = list; el != NULL; el = el->next_unit_set_el)
8462117395Skan    {
8463117395Skan      if (el != list)
8464132718Skan	fprintf (output_description_file, ", ");
8465117395Skan      fprintf (output_description_file, "%s", el->unit_decl->name);
8466117395Skan    }
8467117395Skan}
8468117395Skan
8469132718Skan/* Output patterns in LIST separated by comma.  */
8470132718Skanstatic void
8471132718Skanoutput_pattern_set_el_list (pattern_set_el_t list)
8472132718Skan{
8473132718Skan  pattern_set_el_t el;
8474132718Skan  int i;
8475132718Skan
8476132718Skan  for (el = list; el != NULL; el = el->next_pattern_set_el)
8477132718Skan    {
8478132718Skan      if (el != list)
8479132718Skan	fprintf (output_description_file, ", ");
8480132718Skan      for (i = 0; i < el->units_num; i++)
8481132718Skan	fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8482132718Skan		 el->unit_decls [i]->name);
8483132718Skan    }
8484132718Skan}
8485132718Skan
8486117395Skan/* The function outputs string representation of IR define_reservation
8487117395Skan   and define_insn_reservation.  */
8488117395Skanstatic void
8489132718Skanoutput_description (void)
8490117395Skan{
8491117395Skan  decl_t decl;
8492117395Skan  int i;
8493117395Skan
8494117395Skan  for (i = 0; i < description->decls_num; i++)
8495117395Skan    {
8496117395Skan      decl = description->decls [i];
8497117395Skan      if (decl->mode == dm_unit)
8498117395Skan	{
8499117395Skan	  if (DECL_UNIT (decl)->excl_list != NULL)
8500117395Skan	    {
8501117395Skan	      fprintf (output_description_file, "unit %s exlusion_set: ",
8502117395Skan		       DECL_UNIT (decl)->name);
8503117395Skan	      output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8504117395Skan	      fprintf (output_description_file, "\n");
8505117395Skan	    }
8506117395Skan	  if (DECL_UNIT (decl)->presence_list != NULL)
8507117395Skan	    {
8508117395Skan	      fprintf (output_description_file, "unit %s presence_set: ",
8509117395Skan		       DECL_UNIT (decl)->name);
8510132718Skan	      output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8511117395Skan	      fprintf (output_description_file, "\n");
8512117395Skan	    }
8513132718Skan	  if (DECL_UNIT (decl)->final_presence_list != NULL)
8514132718Skan	    {
8515132718Skan	      fprintf (output_description_file, "unit %s final_presence_set: ",
8516132718Skan		       DECL_UNIT (decl)->name);
8517132718Skan	      output_pattern_set_el_list
8518132718Skan		(DECL_UNIT (decl)->final_presence_list);
8519132718Skan	      fprintf (output_description_file, "\n");
8520132718Skan	    }
8521117395Skan	  if (DECL_UNIT (decl)->absence_list != NULL)
8522117395Skan	    {
8523117395Skan	      fprintf (output_description_file, "unit %s absence_set: ",
8524117395Skan		       DECL_UNIT (decl)->name);
8525132718Skan	      output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8526117395Skan	      fprintf (output_description_file, "\n");
8527117395Skan	    }
8528132718Skan	  if (DECL_UNIT (decl)->final_absence_list != NULL)
8529132718Skan	    {
8530132718Skan	      fprintf (output_description_file, "unit %s final_absence_set: ",
8531132718Skan		       DECL_UNIT (decl)->name);
8532132718Skan	      output_pattern_set_el_list
8533132718Skan		(DECL_UNIT (decl)->final_absence_list);
8534132718Skan	      fprintf (output_description_file, "\n");
8535132718Skan	    }
8536117395Skan	}
8537117395Skan    }
8538117395Skan  fprintf (output_description_file, "\n");
8539117395Skan  for (i = 0; i < description->decls_num; i++)
8540117395Skan    {
8541117395Skan      decl = description->decls [i];
8542117395Skan      if (decl->mode == dm_reserv)
8543117395Skan	{
8544132718Skan          fprintf (output_description_file, "reservation %s: ",
8545132718Skan		   DECL_RESERV (decl)->name);
8546117395Skan          output_regexp (DECL_RESERV (decl)->regexp);
8547117395Skan          fprintf (output_description_file, "\n");
8548117395Skan        }
8549117395Skan      else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8550117395Skan        {
8551117395Skan          fprintf (output_description_file, "insn reservation %s ",
8552117395Skan		   DECL_INSN_RESERV (decl)->name);
8553117395Skan          print_rtl (output_description_file,
8554117395Skan		     DECL_INSN_RESERV (decl)->condexp);
8555117395Skan          fprintf (output_description_file, ": ");
8556117395Skan          output_regexp (DECL_INSN_RESERV (decl)->regexp);
8557117395Skan          fprintf (output_description_file, "\n");
8558117395Skan        }
8559117395Skan      else if (decl->mode == dm_bypass)
8560117395Skan	fprintf (output_description_file, "bypass %d %s %s\n",
8561117395Skan		 DECL_BYPASS (decl)->latency,
8562117395Skan		 DECL_BYPASS (decl)->out_insn_name,
8563117395Skan		 DECL_BYPASS (decl)->in_insn_name);
8564117395Skan    }
8565117395Skan  fprintf (output_description_file, "\n\f\n");
8566117395Skan}
8567117395Skan
8568117395Skan/* The function outputs name of AUTOMATON.  */
8569117395Skanstatic void
8570132718Skanoutput_automaton_name (FILE *f, automaton_t automaton)
8571117395Skan{
8572117395Skan  if (automaton->corresponding_automaton_decl == NULL)
8573117395Skan    fprintf (f, "#%d", automaton->automaton_order_num);
8574117395Skan  else
8575117395Skan    fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8576117395Skan}
8577117395Skan
8578117395Skan/* Maximal length of line for pretty printing into description
8579117395Skan   file.  */
8580117395Skan#define MAX_LINE_LENGTH 70
8581117395Skan
8582117395Skan/* The function outputs units name belonging to AUTOMATON.  */
8583117395Skanstatic void
8584132718Skanoutput_automaton_units (automaton_t automaton)
8585117395Skan{
8586117395Skan  decl_t decl;
8587169689Skan  const char *name;
8588117395Skan  int curr_line_length;
8589117395Skan  int there_is_an_automaton_unit;
8590117395Skan  int i;
8591117395Skan
8592169689Skan  fprintf (output_description_file, "\n  Corresponding units:\n");
8593117395Skan  fprintf (output_description_file, "    ");
8594117395Skan  curr_line_length = 4;
8595117395Skan  there_is_an_automaton_unit = 0;
8596117395Skan  for (i = 0; i < description->decls_num; i++)
8597117395Skan    {
8598117395Skan      decl = description->decls [i];
8599117395Skan      if (decl->mode == dm_unit
8600117395Skan          && (DECL_UNIT (decl)->corresponding_automaton_num
8601117395Skan	      == automaton->automaton_order_num))
8602117395Skan	{
8603117395Skan	  there_is_an_automaton_unit = 1;
8604117395Skan	  name = DECL_UNIT (decl)->name;
8605117395Skan	  if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8606117395Skan	    {
8607117395Skan	      curr_line_length = strlen (name) + 4;
8608117395Skan	      fprintf (output_description_file, "\n    ");
8609117395Skan	    }
8610117395Skan	  else
8611117395Skan	    {
8612117395Skan	      curr_line_length += strlen (name) + 1;
8613117395Skan	      fprintf (output_description_file, " ");
8614117395Skan	    }
8615132718Skan	  fprintf (output_description_file, "%s", name);
8616117395Skan	}
8617117395Skan    }
8618117395Skan  if (!there_is_an_automaton_unit)
8619117395Skan    fprintf (output_description_file, "<None>");
8620117395Skan  fprintf (output_description_file, "\n\n");
8621117395Skan}
8622117395Skan
8623117395Skan/* The following variable is used for forming array of all possible cpu unit
8624117395Skan   reservations described by the current DFA state.  */
8625169689Skanstatic VEC(reserv_sets_t,heap) *state_reservs;
8626117395Skan
8627117395Skan/* The function forms `state_reservs' for STATE.  */
8628117395Skanstatic void
8629132718Skanadd_state_reservs (state_t state)
8630117395Skan{
8631117395Skan  alt_state_t curr_alt_state;
8632117395Skan
8633117395Skan  if (state->component_states != NULL)
8634117395Skan    for (curr_alt_state = state->component_states;
8635117395Skan         curr_alt_state != NULL;
8636117395Skan         curr_alt_state = curr_alt_state->next_sorted_alt_state)
8637117395Skan      add_state_reservs (curr_alt_state->state);
8638117395Skan  else
8639169689Skan    VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8640117395Skan}
8641117395Skan
8642132718Skan/* The function outputs readable representation of all out arcs of
8643117395Skan   STATE.  */
8644117395Skanstatic void
8645132718Skanoutput_state_arcs (state_t state)
8646117395Skan{
8647117395Skan  arc_t arc;
8648117395Skan  ainsn_t ainsn;
8649169689Skan  const char *insn_name;
8650117395Skan  int curr_line_length;
8651117395Skan
8652117395Skan  for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8653117395Skan    {
8654117395Skan      ainsn = arc->insn;
8655169689Skan      gcc_assert (ainsn->first_insn_with_same_reservs);
8656117395Skan      fprintf (output_description_file, "    ");
8657117395Skan      curr_line_length = 7;
8658117395Skan      fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8659117395Skan      do
8660117395Skan        {
8661117395Skan          insn_name = ainsn->insn_reserv_decl->name;
8662117395Skan          if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8663117395Skan            {
8664117395Skan              if (ainsn != arc->insn)
8665117395Skan                {
8666117395Skan                  fprintf (output_description_file, ",\n      ");
8667117395Skan                  curr_line_length = strlen (insn_name) + 6;
8668117395Skan                }
8669117395Skan              else
8670117395Skan                curr_line_length += strlen (insn_name);
8671117395Skan            }
8672117395Skan          else
8673117395Skan            {
8674117395Skan              curr_line_length += strlen (insn_name);
8675117395Skan              if (ainsn != arc->insn)
8676117395Skan                {
8677117395Skan                  curr_line_length += 2;
8678117395Skan                  fprintf (output_description_file, ", ");
8679117395Skan                }
8680117395Skan            }
8681132718Skan          fprintf (output_description_file, "%s", insn_name);
8682117395Skan          ainsn = ainsn->next_same_reservs_insn;
8683117395Skan        }
8684117395Skan      while (ainsn != NULL);
8685169689Skan      fprintf (output_description_file, "    %d \n",
8686169689Skan	       arc->to_state->order_state_num);
8687117395Skan    }
8688117395Skan  fprintf (output_description_file, "\n");
8689117395Skan}
8690117395Skan
8691117395Skan/* The following function is used for sorting possible cpu unit
8692117395Skan   reservation of a DFA state.  */
8693117395Skanstatic int
8694132718Skanstate_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8695117395Skan{
8696117395Skan  return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
8697117395Skan                          *(reserv_sets_t *) reservs_ptr_2);
8698117395Skan}
8699117395Skan
8700117395Skan/* The following function is used for sorting possible cpu unit
8701117395Skan   reservation of a DFA state.  */
8702117395Skanstatic void
8703132718Skanremove_state_duplicate_reservs (void)
8704117395Skan{
8705169689Skan  size_t i, j;
8706117395Skan
8707169689Skan  for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8708169689Skan    if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8709169689Skan			 VEC_index (reserv_sets_t, state_reservs, i)))
8710117395Skan      {
8711169689Skan	j++;
8712169689Skan	VEC_replace (reserv_sets_t, state_reservs, j,
8713169689Skan		     VEC_index (reserv_sets_t, state_reservs, i));
8714117395Skan      }
8715169689Skan  VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8716117395Skan}
8717117395Skan
8718117395Skan/* The following function output readable representation of DFA(s)
8719117395Skan   state used for fast recognition of pipeline hazards.  State is
8720132718Skan   described by possible (current and scheduled) cpu unit
8721117395Skan   reservations.  */
8722117395Skanstatic void
8723132718Skanoutput_state (state_t state)
8724117395Skan{
8725169689Skan  size_t i;
8726117395Skan
8727169689Skan  state_reservs = 0;
8728169689Skan
8729117395Skan  fprintf (output_description_file, "  State #%d", state->order_state_num);
8730117395Skan  fprintf (output_description_file,
8731117395Skan	   state->new_cycle_p ? " (new cycle)\n" : "\n");
8732117395Skan  add_state_reservs (state);
8733169689Skan  qsort (VEC_address (reserv_sets_t, state_reservs),
8734169689Skan	 VEC_length (reserv_sets_t, state_reservs),
8735117395Skan         sizeof (reserv_sets_t), state_reservs_cmp);
8736117395Skan  remove_state_duplicate_reservs ();
8737169689Skan  for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8738117395Skan    {
8739117395Skan      fprintf (output_description_file, "    ");
8740169689Skan      output_reserv_sets (output_description_file,
8741169689Skan			  VEC_index (reserv_sets_t, state_reservs, i));
8742117395Skan      fprintf (output_description_file, "\n");
8743117395Skan    }
8744117395Skan  fprintf (output_description_file, "\n");
8745117395Skan  output_state_arcs (state);
8746169689Skan  VEC_free (reserv_sets_t,heap, state_reservs);
8747117395Skan}
8748117395Skan
8749117395Skan/* The following function output readable representation of
8750117395Skan   DFAs used for fast recognition of pipeline hazards.  */
8751117395Skanstatic void
8752132718Skanoutput_automaton_descriptions (void)
8753117395Skan{
8754117395Skan  automaton_t automaton;
8755117395Skan
8756117395Skan  for (automaton = description->first_automaton;
8757117395Skan       automaton != NULL;
8758117395Skan       automaton = automaton->next_automaton)
8759117395Skan    {
8760117395Skan      fprintf (output_description_file, "\nAutomaton ");
8761117395Skan      output_automaton_name (output_description_file, automaton);
8762117395Skan      fprintf (output_description_file, "\n");
8763117395Skan      output_automaton_units (automaton);
8764117395Skan      pass_states (automaton, output_state);
8765117395Skan    }
8766117395Skan}
8767117395Skan
8768117395Skan
8769117395Skan
8770117395Skan/* The page contains top level function for generation DFA(s) used for
8771117395Skan   PHR.  */
8772117395Skan
8773117395Skan/* The function outputs statistics about work of different phases of
8774117395Skan   DFA generator.  */
8775117395Skanstatic void
8776132718Skanoutput_statistics (FILE *f)
8777117395Skan{
8778117395Skan  automaton_t automaton;
8779132718Skan  int states_num;
8780117395Skan#ifndef NDEBUG
8781117395Skan  int transition_comb_vect_els = 0;
8782117395Skan  int transition_full_vect_els = 0;
8783117395Skan  int min_issue_delay_vect_els = 0;
8784169689Skan  int locked_states = 0;
8785117395Skan#endif
8786117395Skan
8787117395Skan  for (automaton = description->first_automaton;
8788117395Skan       automaton != NULL;
8789117395Skan       automaton = automaton->next_automaton)
8790117395Skan    {
8791117395Skan      fprintf (f, "\nAutomaton ");
8792117395Skan      output_automaton_name (f, automaton);
8793117395Skan      fprintf (f, "\n    %5d NDFA states,          %5d NDFA arcs\n",
8794117395Skan	       automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8795117395Skan      fprintf (f, "    %5d DFA states,           %5d DFA arcs\n",
8796117395Skan	       automaton->DFA_states_num, automaton->DFA_arcs_num);
8797132718Skan      states_num = automaton->DFA_states_num;
8798117395Skan      if (!no_minimization_flag)
8799132718Skan	{
8800132718Skan	  fprintf (f, "    %5d minimal DFA states,   %5d minimal DFA arcs\n",
8801132718Skan		   automaton->minimal_DFA_states_num,
8802132718Skan		   automaton->minimal_DFA_arcs_num);
8803132718Skan	  states_num = automaton->minimal_DFA_states_num;
8804132718Skan	}
8805117395Skan      fprintf (f, "    %5d all insns      %5d insn equivalence classes\n",
8806117395Skan	       description->insns_num, automaton->insn_equiv_classes_num);
8807169689Skan      fprintf (f, "    %d locked states\n", automaton->locked_states);
8808117395Skan#ifndef NDEBUG
8809117395Skan      fprintf
8810117395Skan	(f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8811169689Skan	 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8812169689Skan	 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8813117395Skan	 (comb_vect_p (automaton->trans_table)
8814117395Skan	  ? "use comb vect" : "use simple vect"));
8815117395Skan      fprintf
8816117395Skan        (f, "%5ld min delay table els, compression factor %d\n",
8817132718Skan         (long) states_num * automaton->insn_equiv_classes_num,
8818117395Skan	 automaton->min_issue_delay_table_compression_factor);
8819117395Skan      transition_comb_vect_els
8820169689Skan	+= VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8821132718Skan      transition_full_vect_els
8822169689Skan        += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8823117395Skan      min_issue_delay_vect_els
8824132718Skan	+= states_num * automaton->insn_equiv_classes_num;
8825169689Skan      locked_states
8826169689Skan	+= automaton->locked_states;
8827117395Skan#endif
8828117395Skan    }
8829117395Skan#ifndef NDEBUG
8830117395Skan  fprintf (f, "\n%5d all allocated states,     %5d all allocated arcs\n",
8831117395Skan	   allocated_states_num, allocated_arcs_num);
8832117395Skan  fprintf (f, "%5d all allocated alternative states\n",
8833117395Skan	   allocated_alt_states_num);
8834117395Skan  fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8835117395Skan	   transition_comb_vect_els, transition_full_vect_els);
8836117395Skan  fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8837169689Skan  fprintf (f, "%5d all locked states\n", locked_states);
8838117395Skan#endif
8839117395Skan}
8840117395Skan
8841117395Skan/* The function output times of work of different phases of DFA
8842117395Skan   generator.  */
8843117395Skanstatic void
8844132718Skanoutput_time_statistics (FILE *f)
8845117395Skan{
8846117395Skan  fprintf (f, "\n  transformation: ");
8847117395Skan  print_active_time (f, transform_time);
8848117395Skan  fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8849117395Skan  print_active_time (f, NDFA_time);
8850117395Skan  if (ndfa_flag)
8851117395Skan    {
8852117395Skan      fprintf (f, ", NDFA -> DFA: ");
8853117395Skan      print_active_time (f, NDFA_to_DFA_time);
8854117395Skan    }
8855117395Skan  fprintf (f, "\n  DFA minimization: ");
8856117395Skan  print_active_time (f, minimize_time);
8857117395Skan  fprintf (f, ", making insn equivalence: ");
8858117395Skan  print_active_time (f, equiv_time);
8859117395Skan  fprintf (f, "\n all automaton generation: ");
8860117395Skan  print_active_time (f, automaton_generation_time);
8861117395Skan  fprintf (f, ", output: ");
8862117395Skan  print_active_time (f, output_time);
8863117395Skan  fprintf (f, "\n");
8864117395Skan}
8865117395Skan
8866132718Skan/* The function generates DFA (deterministic finite state automaton)
8867117395Skan   for fast recognition of pipeline hazards.  No errors during
8868117395Skan   checking must be fixed before this function call.  */
8869117395Skanstatic void
8870132718Skangenerate (void)
8871117395Skan{
8872117395Skan  automata_num = split_argument;
8873117395Skan  if (description->units_num < automata_num)
8874117395Skan    automata_num = description->units_num;
8875117395Skan  initiate_states ();
8876117395Skan  initiate_arcs ();
8877117395Skan  initiate_automata_lists ();
8878117395Skan  initiate_pass_states ();
8879117395Skan  initiate_excl_sets ();
8880132718Skan  initiate_presence_absence_pattern_sets ();
8881117395Skan  automaton_generation_time = create_ticker ();
8882117395Skan  create_automata ();
8883117395Skan  ticker_off (&automaton_generation_time);
8884117395Skan}
8885117395Skan
8886117395Skan
8887117395Skan
8888117395Skan/* This page mainly contains top level functions of pipeline hazards
8889117395Skan   description translator.  */
8890117395Skan
8891117395Skan/* The following macro value is suffix of name of description file of
8892117395Skan   pipeline hazards description translator.  */
8893117395Skan#define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8894117395Skan
8895117395Skan/* The function returns suffix of given file name.  The returned
8896117395Skan   string can not be changed.  */
8897117395Skanstatic const char *
8898132718Skanfile_name_suffix (const char *file_name)
8899117395Skan{
8900117395Skan  const char *last_period;
8901117395Skan
8902117395Skan  for (last_period = NULL; *file_name != '\0'; file_name++)
8903117395Skan    if (*file_name == '.')
8904117395Skan      last_period = file_name;
8905117395Skan  return (last_period == NULL ? file_name : last_period);
8906117395Skan}
8907117395Skan
8908117395Skan/* The function returns base name of given file name, i.e. pointer to
8909117395Skan   first char after last `/' (or `\' for WIN32) in given file name,
8910117395Skan   given file name itself if the directory name is absent.  The
8911117395Skan   returned string can not be changed.  */
8912117395Skanstatic const char *
8913132718Skanbase_file_name (const char *file_name)
8914117395Skan{
8915117395Skan  int directory_name_length;
8916117395Skan
8917117395Skan  directory_name_length = strlen (file_name);
8918117395Skan#ifdef WIN32
8919117395Skan  while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8920117395Skan         && file_name[directory_name_length] != '\\')
8921117395Skan#else
8922117395Skan  while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8923117395Skan#endif
8924117395Skan    directory_name_length--;
8925117395Skan  return file_name + directory_name_length + 1;
8926117395Skan}
8927117395Skan
8928117395Skan/* The following is top level function to initialize the work of
8929117395Skan   pipeline hazards description translator.  */
8930169689Skanstatic void
8931132718Skaninitiate_automaton_gen (int argc, char **argv)
8932117395Skan{
8933117395Skan  const char *base_name;
8934117395Skan  int i;
8935117395Skan
8936117395Skan  ndfa_flag = 0;
8937117395Skan  split_argument = 0;  /* default value */
8938117395Skan  no_minimization_flag = 0;
8939117395Skan  time_flag = 0;
8940117395Skan  v_flag = 0;
8941117395Skan  w_flag = 0;
8942132718Skan  progress_flag = 0;
8943117395Skan  for (i = 2; i < argc; i++)
8944117395Skan    if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8945117395Skan      no_minimization_flag = 1;
8946117395Skan    else if (strcmp (argv [i], TIME_OPTION) == 0)
8947117395Skan      time_flag = 1;
8948117395Skan    else if (strcmp (argv [i], V_OPTION) == 0)
8949117395Skan      v_flag = 1;
8950117395Skan    else if (strcmp (argv [i], W_OPTION) == 0)
8951117395Skan      w_flag = 1;
8952117395Skan    else if (strcmp (argv [i], NDFA_OPTION) == 0)
8953117395Skan      ndfa_flag = 1;
8954132718Skan    else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8955132718Skan      progress_flag = 1;
8956117395Skan    else if (strcmp (argv [i], "-split") == 0)
8957117395Skan      {
8958117395Skan	if (i + 1 >= argc)
8959117395Skan	  fatal ("-split has no argument.");
8960117395Skan	fatal ("option `-split' has not been implemented yet\n");
8961117395Skan	/* split_argument = atoi (argument_vect [i + 1]); */
8962117395Skan      }
8963169689Skan
8964117395Skan  /* Initialize IR storage.  */
8965117395Skan  obstack_init (&irp);
8966117395Skan  initiate_automaton_decl_table ();
8967117395Skan  initiate_insn_decl_table ();
8968117395Skan  initiate_decl_table ();
8969117395Skan  output_file = stdout;
8970117395Skan  output_description_file = NULL;
8971117395Skan  base_name = base_file_name (argv[1]);
8972117395Skan  obstack_grow (&irp, base_name,
8973117395Skan		strlen (base_name) - strlen (file_name_suffix (base_name)));
8974117395Skan  obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8975117395Skan		strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8976117395Skan  obstack_1grow (&irp, '\0');
8977117395Skan  output_description_file_name = obstack_base (&irp);
8978222097Sbenl  (void) obstack_finish (&irp);
8979117395Skan}
8980117395Skan
8981117395Skan/* The following function checks existence at least one arc marked by
8982117395Skan   each insn.  */
8983117395Skanstatic void
8984132718Skancheck_automata_insn_issues (void)
8985117395Skan{
8986117395Skan  automaton_t automaton;
8987117395Skan  ainsn_t ainsn, reserv_ainsn;
8988117395Skan
8989117395Skan  for (automaton = description->first_automaton;
8990117395Skan       automaton != NULL;
8991117395Skan       automaton = automaton->next_automaton)
8992117395Skan    {
8993117395Skan      for (ainsn = automaton->ainsn_list;
8994117395Skan	   ainsn != NULL;
8995117395Skan	   ainsn = ainsn->next_ainsn)
8996117395Skan	if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
8997117395Skan	  {
8998117395Skan	    for (reserv_ainsn = ainsn;
8999117395Skan		 reserv_ainsn != NULL;
9000117395Skan		 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9001117395Skan	      if (automaton->corresponding_automaton_decl != NULL)
9002117395Skan		{
9003117395Skan		  if (!w_flag)
9004117395Skan		    error ("Automaton `%s': Insn `%s' will never be issued",
9005117395Skan			   automaton->corresponding_automaton_decl->name,
9006117395Skan			   reserv_ainsn->insn_reserv_decl->name);
9007117395Skan		  else
9008117395Skan		    warning
9009169689Skan		      (0, "Automaton `%s': Insn `%s' will never be issued",
9010117395Skan		       automaton->corresponding_automaton_decl->name,
9011117395Skan		       reserv_ainsn->insn_reserv_decl->name);
9012117395Skan		}
9013117395Skan	      else
9014117395Skan		{
9015117395Skan		  if (!w_flag)
9016117395Skan		    error ("Insn `%s' will never be issued",
9017117395Skan			   reserv_ainsn->insn_reserv_decl->name);
9018117395Skan		  else
9019169689Skan		    warning (0, "Insn `%s' will never be issued",
9020117395Skan			     reserv_ainsn->insn_reserv_decl->name);
9021117395Skan		}
9022117395Skan	  }
9023117395Skan    }
9024117395Skan}
9025117395Skan
9026117395Skan/* The following vla is used for storing pointers to all achieved
9027117395Skan   states.  */
9028169689Skanstatic VEC(state_t,heap) *automaton_states;
9029117395Skan
9030117395Skan/* This function is called by function pass_states to add an achieved
9031117395Skan   STATE.  */
9032117395Skanstatic void
9033132718Skanadd_automaton_state (state_t state)
9034117395Skan{
9035169689Skan  VEC_safe_push (state_t,heap, automaton_states, state);
9036117395Skan}
9037117395Skan
9038117395Skan/* The following function forms list of important automata (whose
9039117395Skan   states may be changed after the insn issue) for each insn.  */
9040117395Skanstatic void
9041132718Skanform_important_insn_automata_lists (void)
9042117395Skan{
9043117395Skan  automaton_t automaton;
9044117395Skan  decl_t decl;
9045117395Skan  ainsn_t ainsn;
9046117395Skan  arc_t arc;
9047117395Skan  int i;
9048169689Skan  size_t n;
9049117395Skan
9050169689Skan  automaton_states = 0;
9051117395Skan  /* Mark important ainsns.  */
9052117395Skan  for (automaton = description->first_automaton;
9053117395Skan       automaton != NULL;
9054117395Skan       automaton = automaton->next_automaton)
9055117395Skan    {
9056169689Skan      VEC_truncate (state_t, automaton_states, 0);
9057117395Skan      pass_states (automaton, add_automaton_state);
9058169689Skan      for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9059117395Skan	{
9060169689Skan	  state_t s = VEC_index (state_t, automaton_states, n);
9061169689Skan	  for (arc = first_out_arc (s);
9062117395Skan	       arc != NULL;
9063117395Skan	       arc = next_out_arc (arc))
9064169689Skan	    if (arc->to_state != s)
9065117395Skan	      {
9066169689Skan		gcc_assert (arc->insn->first_insn_with_same_reservs);
9067117395Skan		for (ainsn = arc->insn;
9068117395Skan		     ainsn != NULL;
9069117395Skan		     ainsn = ainsn->next_same_reservs_insn)
9070117395Skan		  ainsn->important_p = TRUE;
9071117395Skan	      }
9072117395Skan	}
9073117395Skan    }
9074169689Skan  VEC_free (state_t,heap, automaton_states);
9075169689Skan
9076117395Skan  /* Create automata sets for the insns.  */
9077117395Skan  for (i = 0; i < description->decls_num; i++)
9078117395Skan    {
9079117395Skan      decl = description->decls [i];
9080117395Skan      if (decl->mode == dm_insn_reserv)
9081117395Skan	{
9082117395Skan	  automata_list_start ();
9083117395Skan	  for (automaton = description->first_automaton;
9084117395Skan	       automaton != NULL;
9085117395Skan	       automaton = automaton->next_automaton)
9086117395Skan	    for (ainsn = automaton->ainsn_list;
9087117395Skan		 ainsn != NULL;
9088117395Skan		 ainsn = ainsn->next_ainsn)
9089117395Skan	      if (ainsn->important_p
9090117395Skan		  && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9091117395Skan		{
9092117395Skan		  automata_list_add (automaton);
9093117395Skan		  break;
9094117395Skan		}
9095117395Skan	  DECL_INSN_RESERV (decl)->important_automata_list
9096117395Skan	    = automata_list_finish ();
9097117395Skan	}
9098117395Skan    }
9099117395Skan}
9100117395Skan
9101117395Skan
9102117395Skan/* The following is top level function to generate automat(a,on) for
9103117395Skan   fast recognition of pipeline hazards.  */
9104169689Skanstatic void
9105132718Skanexpand_automata (void)
9106117395Skan{
9107117395Skan  int i;
9108117395Skan
9109117395Skan  description = create_node (sizeof (struct description)
9110117395Skan			     /* One entry for cycle advancing insn.  */
9111169689Skan			     + sizeof (decl_t) * VEC_length (decl_t, decls));
9112169689Skan  description->decls_num = VEC_length (decl_t, decls);
9113117395Skan  description->query_units_num = 0;
9114117395Skan  for (i = 0; i < description->decls_num; i++)
9115117395Skan    {
9116169689Skan      description->decls [i] = VEC_index (decl_t, decls, i);
9117117395Skan      if (description->decls [i]->mode == dm_unit
9118117395Skan	  && DECL_UNIT (description->decls [i])->query_p)
9119117395Skan        DECL_UNIT (description->decls [i])->query_num
9120117395Skan	  = description->query_units_num++;
9121117395Skan    }
9122117395Skan  all_time = create_ticker ();
9123117395Skan  check_time = create_ticker ();
9124132718Skan  if (progress_flag)
9125132718Skan    fprintf (stderr, "Check description...");
9126117395Skan  check_all_description ();
9127132718Skan  if (progress_flag)
9128132718Skan    fprintf (stderr, "done\n");
9129117395Skan  ticker_off (&check_time);
9130117395Skan  generation_time = create_ticker ();
9131117395Skan  if (!have_error)
9132117395Skan    {
9133117395Skan      transform_insn_regexps ();
9134117395Skan      check_unit_distributions_to_automata ();
9135117395Skan    }
9136117395Skan  if (!have_error)
9137117395Skan    {
9138117395Skan      generate ();
9139117395Skan      check_automata_insn_issues ();
9140117395Skan    }
9141117395Skan  if (!have_error)
9142117395Skan    {
9143117395Skan      form_important_insn_automata_lists ();
9144117395Skan    }
9145117395Skan  ticker_off (&generation_time);
9146117395Skan}
9147117395Skan
9148117395Skan/* The following is top level function to output PHR and to finish
9149117395Skan   work with pipeline description translator.  */
9150169689Skanstatic void
9151132718Skanwrite_automata (void)
9152117395Skan{
9153117395Skan  output_time = create_ticker ();
9154132718Skan  if (progress_flag)
9155132718Skan    fprintf (stderr, "Forming and outputting automata tables...");
9156117395Skan  output_tables ();
9157132718Skan  if (progress_flag)
9158132718Skan    {
9159132718Skan      fprintf (stderr, "done\n");
9160132718Skan      fprintf (stderr, "Output functions to work with automata...");
9161132718Skan    }
9162117395Skan  output_chip_definitions ();
9163117395Skan  output_max_insn_queue_index_def ();
9164117395Skan  output_internal_min_issue_delay_func ();
9165117395Skan  output_internal_trans_func ();
9166117395Skan  /* Cache of insn dfa codes: */
9167117395Skan  fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9168117395Skan  fprintf (output_file, "\nstatic int %s;\n\n",
9169117395Skan	   DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9170117395Skan  output_dfa_insn_code_func ();
9171117395Skan  output_trans_func ();
9172117395Skan  output_min_issue_delay_func ();
9173117395Skan  output_internal_dead_lock_func ();
9174117395Skan  output_dead_lock_func ();
9175117395Skan  output_size_func ();
9176117395Skan  output_internal_reset_func ();
9177117395Skan  output_reset_func ();
9178117395Skan  output_min_insn_conflict_delay_func ();
9179117395Skan  output_internal_insn_latency_func ();
9180117395Skan  output_insn_latency_func ();
9181117395Skan  output_print_reservation_func ();
9182132718Skan  /* Output function get_cpu_unit_code.  */
9183132718Skan  fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9184132718Skan  output_get_cpu_unit_code_func ();
9185132718Skan  output_cpu_unit_reservation_p ();
9186132718Skan  fprintf (output_file, "\n#endif /* #if %s */\n\n",
9187132718Skan	   CPU_UNITS_QUERY_MACRO_NAME);
9188132718Skan  output_dfa_clean_insn_cache_func ();
9189117395Skan  output_dfa_start_func ();
9190117395Skan  output_dfa_finish_func ();
9191132718Skan  if (progress_flag)
9192132718Skan    fprintf (stderr, "done\n");
9193117395Skan  if (v_flag)
9194117395Skan    {
9195117395Skan      output_description_file = fopen (output_description_file_name, "w");
9196117395Skan      if (output_description_file == NULL)
9197117395Skan	{
9198117395Skan	  perror (output_description_file_name);
9199117395Skan	  exit (FATAL_EXIT_CODE);
9200117395Skan	}
9201132718Skan      if (progress_flag)
9202132718Skan	fprintf (stderr, "Output automata description...");
9203117395Skan      output_description ();
9204117395Skan      output_automaton_descriptions ();
9205132718Skan      if (progress_flag)
9206132718Skan	fprintf (stderr, "done\n");
9207117395Skan      output_statistics (output_description_file);
9208117395Skan    }
9209117395Skan  output_statistics (stderr);
9210117395Skan  ticker_off (&output_time);
9211117395Skan  output_time_statistics (stderr);
9212117395Skan  finish_states ();
9213117395Skan  finish_arcs ();
9214117395Skan  finish_automata_lists ();
9215117395Skan  if (time_flag)
9216117395Skan    {
9217117395Skan      fprintf (stderr, "Summary:\n");
9218117395Skan      fprintf (stderr, "  check time ");
9219117395Skan      print_active_time (stderr, check_time);
9220117395Skan      fprintf (stderr, ", generation time ");
9221117395Skan      print_active_time (stderr, generation_time);
9222117395Skan      fprintf (stderr, ", all time ");
9223117395Skan      print_active_time (stderr, all_time);
9224117395Skan      fprintf (stderr, "\n");
9225117395Skan    }
9226117395Skan  /* Finish all work.  */
9227117395Skan  if (output_description_file != NULL)
9228117395Skan    {
9229117395Skan      fflush (output_description_file);
9230117395Skan      if (ferror (stdout) != 0)
9231117395Skan	fatal ("Error in writing DFA description file %s",
9232117395Skan               output_description_file_name);
9233117395Skan      fclose (output_description_file);
9234117395Skan    }
9235117395Skan  finish_automaton_decl_table ();
9236117395Skan  finish_insn_decl_table ();
9237117395Skan  finish_decl_table ();
9238117395Skan  obstack_free (&irp, NULL);
9239117395Skan  if (have_error && output_description_file != NULL)
9240117395Skan    remove (output_description_file_name);
9241117395Skan}
9242169689Skan
9243169689Skanint
9244169689Skanmain (int argc, char **argv)
9245169689Skan{
9246169689Skan  rtx desc;
9247169689Skan
9248169689Skan  progname = "genautomata";
9249169689Skan
9250169689Skan  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9251169689Skan    return (FATAL_EXIT_CODE);
9252169689Skan
9253169689Skan  initiate_automaton_gen (argc, argv);
9254169689Skan  while (1)
9255169689Skan    {
9256169689Skan      int lineno;
9257169689Skan      int insn_code_number;
9258169689Skan
9259169689Skan      desc = read_md_rtx (&lineno, &insn_code_number);
9260169689Skan      if (desc == NULL)
9261169689Skan	break;
9262169689Skan
9263169689Skan      switch (GET_CODE (desc))
9264169689Skan	{
9265169689Skan	case DEFINE_CPU_UNIT:
9266169689Skan	  gen_cpu_unit (desc);
9267169689Skan	  break;
9268169689Skan
9269169689Skan	case DEFINE_QUERY_CPU_UNIT:
9270169689Skan	  gen_query_cpu_unit (desc);
9271169689Skan	  break;
9272169689Skan
9273169689Skan	case DEFINE_BYPASS:
9274169689Skan	  gen_bypass (desc);
9275169689Skan	  break;
9276169689Skan
9277169689Skan	case EXCLUSION_SET:
9278169689Skan	  gen_excl_set (desc);
9279169689Skan	  break;
9280169689Skan
9281169689Skan	case PRESENCE_SET:
9282169689Skan	  gen_presence_set (desc);
9283169689Skan	  break;
9284169689Skan
9285169689Skan	case FINAL_PRESENCE_SET:
9286169689Skan	  gen_final_presence_set (desc);
9287169689Skan	  break;
9288169689Skan
9289169689Skan	case ABSENCE_SET:
9290169689Skan	  gen_absence_set (desc);
9291169689Skan	  break;
9292169689Skan
9293169689Skan	case FINAL_ABSENCE_SET:
9294169689Skan	  gen_final_absence_set (desc);
9295169689Skan	  break;
9296169689Skan
9297169689Skan	case DEFINE_AUTOMATON:
9298169689Skan	  gen_automaton (desc);
9299169689Skan	  break;
9300169689Skan
9301169689Skan	case AUTOMATA_OPTION:
9302169689Skan	  gen_automata_option (desc);
9303169689Skan	  break;
9304169689Skan
9305169689Skan	case DEFINE_RESERVATION:
9306169689Skan	  gen_reserv (desc);
9307169689Skan	  break;
9308169689Skan
9309169689Skan	case DEFINE_INSN_RESERVATION:
9310169689Skan	  gen_insn_reserv (desc);
9311169689Skan	  break;
9312169689Skan
9313169689Skan	default:
9314169689Skan	  break;
9315169689Skan	}
9316169689Skan    }
9317169689Skan
9318169689Skan  if (have_error)
9319169689Skan    return FATAL_EXIT_CODE;
9320169689Skan
9321169689Skan  puts ("/* Generated automatically by the program `genautomata'\n"
9322169689Skan	"   from the machine description file `md'.  */\n\n"
9323169689Skan	"#include \"config.h\"\n"
9324169689Skan	"#include \"system.h\"\n"
9325169689Skan	"#include \"coretypes.h\"\n"
9326169689Skan	"#include \"tm.h\"\n"
9327169689Skan	"#include \"rtl.h\"\n"
9328169689Skan	"#include \"tm_p.h\"\n"
9329169689Skan	"#include \"insn-config.h\"\n"
9330169689Skan	"#include \"recog.h\"\n"
9331169689Skan	"#include \"regs.h\"\n"
9332169689Skan	"#include \"real.h\"\n"
9333169689Skan	"#include \"output.h\"\n"
9334169689Skan	"#include \"insn-attr.h\"\n"
9335169689Skan	"#include \"toplev.h\"\n"
9336169689Skan	"#include \"flags.h\"\n"
9337169689Skan	"#include \"function.h\"\n");
9338169689Skan
9339169689Skan  if (VEC_length (decl_t, decls) > 0)
9340169689Skan    {
9341169689Skan      expand_automata ();
9342169689Skan      write_automata ();
9343169689Skan    }
9344169689Skan
9345169689Skan  fflush (stdout);
9346169689Skan  return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
9347169689Skan}
9348